忍者ブログ
ブログツール、2007/11/06作成
[6] [7] [8] [9] [10] [11] [12] [13
×

[PR]上記の広告は3ヶ月以上新規記事投稿のないブログに表示されています。新しい記事を書く事で広告が消えます。

Railsを使ってると、フリーワード検索はやりにくかったりする。
特に、オブジェクトの関連が絡んでくるとかなり面倒。

で、結局find_by_sqlを使うことになるんだけど、そうなるとパラメータをサニタイジングしないと危なくて使えない。

普通にfindのconditionsオプションでやるときはフレームワークがやってくれるので幸せだが、find_by_sqlだと出来ない。

しょうがないので、たぶんあるだろうとquote()でやってみるも「見つからん」とのことで、APIを読んでみるといろんなところで同一のメソッドが定義されているので、どのクラスのquote()を使うか指定しないといかん。

無難そうなActiveRecord::Baseを使ってみる。
この場合、引き渡されたパラメータをシングルクオートで囲ってくれる。

LIKEで部分一致もしくは、前方、後方一致で検索したいときはこれが引っかかる。
SQLエラーが出ちゃうのだ。

シングルクオートで囲んでほしくないときは、Mysql::quote()を使うのが吉。
DBMSをMySQL以外の時はどうなるんだろ。
ま、ほかを使う気が全くないのでいいけど。

結論

Mysql::quote()を使え。

あらかじめシングルクオートで囲むのがいやならActiveRecord::Base::quote()
PR
久々にRailsじゃないCGIプログラムを書くといろいろ勉強になるけど、ひどくハマる。
レンタルサーバーがRails対応じゃないから仕方ないけど。

で、今回のどハマりはマルチパート。

日記みたいなかんじのCGIなんだけど、
画像ファイルをアップロードさせてサーバーのディレクトリに保存、エントリ投稿時にディレクトリのファイルを選択して貼り付ける言う、それほど難しくもないもの。

デザインと分離したいので、rhtmlが使いたかった所だけど、それがサーバーの都合で出来ない。
頻繁に書き換えるわけでもないので、投稿データはYAMLで保存しておき、
テンプレートとしてデザイナーに作ってもらったファイルの一部を書き換えることで、
HTMLファイルを再構築して出力するようにした。

根本的な機能はrbファイルで作成して、入出力をcgiに持たせる方向で行く。
そうすれば、CGIから作らなければならないページは管理用のページだけになる。

管理用ページはCGI::HtmlExtentionを使って、出力する。

で、はまったのは、マルチパートフォームで画像をアップしたとき。
1.マルチパートで送ったときは、同一フォーム上のパラメータは全部StringIOできちゃうこと。
これはすぐわかった。
CGI.multipart?で処理を分岐してパラメータの取得をおこなって終了。

2.なぜかcgi.outのところでエラーが返る。
cgi.rb 'read_multipart' : no content body {EOFError)
ときたもんだ。

マルチパートの処理は正常に終わってるし、サーバーにも意図通りファイルが保存されている。
何だ何だー?
と調べてみると、CGI.newが再度呼ばれているところが原因。

どういうことかというと、
ページ全体の設定だとか、エントリの編集部分だとか、画像の選択フォームだとかの定型的なものはどうしても繰り返し書いてしまいがちなので、ここは一つDRYにするために、出力部分のヘルパを作ってみた。

特に何も考えず、どうせCGI::HtmlExtentionで出力された文字列をあいだにはめるだけだから、とヘルパにはクラスメソッドのみしか定義せず、出力に必要なオブジェクトのみを引数にして、メソッドが呼ばれるたびにCGI.newしていた。
この部分だ。

うへー。と思いつつ、クラスメソッドにするのをやめて、initializeで呼び出し元のCGIインスタンスを引き回すことにする。

CGI::HtmlExtentionがクラスメソッドじゃないのには理由があるんだねえ。
クラスメソッドじゃないものをクラスメソッドの用に使い回すのにインスタンスを作りまくるのはやっぱ問題があるんだねえ....

CGI::HtmlExtentionでどうしてクラスメソッドじゃないのかは調べる気力がないのでここで終了。

教訓
ヘルパ作るなら、CGIインスタンスを使い回せ。
無駄にnewすんな。
あ~、めんどくせ~、配列がパラメータに一発で入ればいいのに。
なんか便利なものがないものか探すが見つからず。

そんなときは、結構な確率で当たり前に出来たりするのでRailsに期待してテストしてみる。

controller:
@array = ['hoge','fuga','piyo']

view:
# 直入れ
<%= hidden_field_tag 'direct_param', @array %>
# 配列に直入れ
<%= hidden_field_tag 'array_param[]', @array %>
# ループで回す
<% @array.each do |elm| %>
<%= hidden_field_tag 'looped_param[]', elm %>
<% end %>
結果:
hidden_field_tag 'array_param[]', @array
クラス:Array
["hogefugapiyo"]

直入れhidden_field_tag 'direct_param', @array
クラス:String
"hogefugapiyo"

ループで回してhidden_field_tag 'looped_param[]', element
クラス:Array
["hoge", "fuga", "piyo"]

結論。
自分でヘルパ作れ。
  def array_to_param(param_name, array)
ret = ""
array.each do |elm|
ret += hidden_field_tag "#{param_name}[]", elm
end
return ret
end
file_fieldを使用してファイルアップロードなりをするときの注意点。

まず、ブランクチェックを行っておくこと。
ブランクチェックは、
params[:upload_file].blank?
でやるのが吉。

もしくは、params[:upload_file].size == 0
とか。

そのほか、params[:upload_file]に格納されるデータの型がデータ量によって異なることが注意。
10KB以下だとStringIOクラス、それ以上だとTempfileクラスになる。

処理によってはデータサイズ別に振る舞いを分ける必要がありそう。
忘れちゃうのでメモ

関連テーブルなんかだと、関連先IDをDBインデックスに指定するのは常套手段。

migrationファイルで、インデックスを追加するのはいいんだけど、
クラス名と関連クラス名が長いと
name '......' to long
でエラーがかえってきちゃう。

そんなときは、:nameオプションで指定するべし。

こんな感じ
add_index :nandaka_sugoku_nagai_class_names,
          :aitemo_sugoku_nagai_class_name_dane_id, 
          :name=>'short_index'
前のページ      次のページ
ついめ~じ
ブログ内検索
フリーエリア
サニーカメラ
Powered by Ninja Blog    template by Temp* factory    icon by MiniaureType

忍者ブログ [PR]