忍者ブログ
ブログツール、2007/11/06作成
[1] [2] [3] [4] [5] [6] [7] [8
×

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

ActionHelperのsubmit_tagで値を渡す方法。

見た目の関係上で、submit_tagを二つ作って、たとえば「完了」「取り消し」とやりたいときがある。

普通にsubmit_tagを二つ作って、コントローラでどっちのボタンが押されたか判別してあげればいい。

このとき、どのsubmit_tagが押されたかは、params[:commit]で判別がつく。
どうしても日本人なので、ボタン表示は日本語にしたいが、
条件分岐コードに日本語が入るのはどうもね....
という向きには、
submit_tagのhtmlオプションの:nameを入れてやればいい。
:commitに入るべき値が:nameで指定したシンボルで参照できる。

こんな感じ

view

<% form_tag(:action=>'test') do %>
<%= submit_tag 'ほげ', :name=>'hoge' %>
 <%= submit_tag 'ふが', :name=>'fuga' %>
<% end %>

controller
 
def test
  if params[:hoge]
     # ほげを押された処理
  else
     # ふがを押された処理
   end
end
PR
あ~、やってしまいましたとも。

ありがちなハマり方。

booleanなカラムを:null=>falseで作りましたよ。
んでもって、それにfalseをいれましたとも。
そしたらsaveでキックされちゃいましたよ。

はは、booleanな属性にvalidates_presence_ofを適用したら、falseを入れられなくなるなんてね。
とほほ。

しばらく悩みました。

答えはくまの人の所に。

validates_presence_ofの評価は、blank?でやってるらしい。
で、false.blank?はtrueなので、
ARに怒られちゃうと。

ありがとう、くまの人。
ユーザビリティの向上のため、obseve_fieldを使ってみる。

ActionHelperの一つなんだけど、
ターゲットの出すイベントで非同期のアクションを呼び出してくれる。

使い方は簡単。ビューに埋め込む。
<div id="<%= observe_update_id %>">
<%= check_box_tag observe_target_id, value %>
<%= observe_field observe_target_id, 
                  {:on=>'change',
                   :update=>observe_update_id, 
                   :with=>"'value_param_name='+(value)", 
                   :url=>{:controller=>'controller_name', 
                          :action=>'action_name', 
                          :addtion_param=>addition_param_vaule}}%>
 
</div> 
とこんな感じ。
observe_fieldの第一引数に監視するフィールドのIDを入れておき、
:updateオプションに更新したい要素のIDを入れておく。
サンプルの場合、チェックボックスのチェックを入れたり、外したりしたときにアクションが発生して、
自分自身が含まれる要素を書き換えることになる。

自分以外の所に指定してやれば、結果が返ってくる。
自分以外の所に指定して、そのIDも動的に生成してやれば、再帰的に呼び出すことも可能。

呼び出し先はurl_forの形式なので、固定的なパラメータはここに埋め込んでやればいい。

問題なのは、監視対象のフィールドの値をどうやって送るか。
:withオプションを指定しないときは、
value = request.raw_post || request.query_string
で受け取るらしい。

なんか生っぽくて気持ちが悪いのっで、出来ればparams[:name] = valueで受け取りたい。

で、:withオプションに
"'value_param_name='+(value)"
と指定してやる。ダブルクオートとシングルクオートが入り交じっているのは、
:withオプションの中身をJavascriptが評価するから。

ちなみにテキストフィールドなんかで定期的に評価したいときは、
:onオプションをやめて、
:frequencyオプションに秒数を入れてやればいい。

:onオプションには、change以外にもイベントを指定できる。

いやあ、便利便利。
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()
あ~、めんどくせ~、配列がパラメータに一発で入ればいいのに。
なんか便利なものがないものか探すが見つからず。

そんなときは、結構な確率で当たり前に出来たりするので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
ついめ~じ
ブログ内検索
フリーエリア
サニーカメラ
Powered by Ninja Blog    template by Temp* factory    icon by MiniaureType

忍者ブログ [PR]