T

DataMapperを教えておじいさん

Ruby初心者です。

DataMapperとやらを使ってみているわけですが。

とにかく、情報が少なくて困ってしまいます。例えば、複数の LIKE 条件をつなぐときとか、どうすればいいの?

class Repo #例えばこんなクラスがあるとする
  include DataMapper::Resource
  property :id, Serial
  property :body, String
end

普通のLIKE節の作成の仕方はこうなる。

Repo.all('body.like' => '%test%')
#=> SELECT * FROM repos WHERE body LIKE '%test%';

または、シンボルで書くこともできる。

Repo.all(:body.like => '%here%')
#=> SELECT * FROM repos WHERE body LIKE '%here%';

でも、複数のLIKE節をつなげる方法がいまいちわからない。そこで試してみた。

まずは配列。

Repo.all('body.like' => ['%test%', '%here%'])
#=> SELECT * FROM repos WHERE body LIKE '%test%%here%';

失敗。

じゃあ羅列。

Repo.all('body.like' => '%test%', 'body.like' => '%here%')
#=> SELECT * FROM repos WHERE body LIKE '%here%';

これも失敗。

ところが、こんな風にチェーンさせるとうまくいく。

Repo.all('body.like' => '%test%') 
+ Repo.all('body.like' => '%here%')
#=> SELECT * FROM repos WHERE body LIKE '%test%' OR body LIKE '%here%';

でも、確かにうまくいくのだけれど、プログラムに組み込むのはどうすればいいんだろう。「+」なんか使われたら、文字列の連結になっちゃうのでエラーになりそうだ。思いつく方法で検索フォームから検索語が入力されたらLIKE検索で結果を返すプログラムを作成してみる。

search_options = []
params[:keyword].gsub(' ', '').strip.split([\s]).each do |keyword|
  search_options << "Post.all('body.like' => '%#{keyword}%')"
end
eval_str = search_options.join(' + ') #まさか!?
@repos = eval eval_str #な、なんと!!

よし、エスケープも用意するか。

def escape_shell_cmd keyword
  keyword.gsub!(/(["'#&;`|*?~<>^()\[\]{}$\\\x0A\xFF])/) { "\\" + $1 }
end

うーん、どんどん間違った方向に進んでしまう。なんか、一般的なやり方っていうのがあって、こちらがそれを知らないだけなんだと思うんだけど、これ以上進むのは危険すぎるので調べることにする。

Posted by on 12月 20, 2010 in Ruby

Comments

  • […] This post was mentioned on Twitter by 超電磁ねこきっく. 超電磁ねこきっく said: "Ruby初心者です。 DataMapperとやらを使ってみているわけですが。 とにかく、情報が少なくて困ってしまいます。" http://selfkleptomaniac.org/archives/1458 […]

  • なかだ より:

    @repos = params[:keyword].split(/[\s ]+/).
    map {|keyword| Repo.all(‘body.like’ => “%#{keyword}%”)}.inject(:+)

  • y より:

    ほ、ほんまや、できとる!
    ありがとうございます。

  • コメントを残す