rails 覚えたての頃に書いた以下のようなコード
def items(array)
array.map{ |i| Item.find(i) }
end
を、以下のように書き換えてハマる。
def items(array)
Item.find(array)
end
タイトルに答えを書いちゃったけど、find(array) は array の順序を保存しない。
array が sort されてれば大丈夫かと思ったが、 mysql では OK だが postgresql ではダメだった。
幸い僕のケースでは array が sort 済みのものだったので、 find(array, :order=>:id) で丸く収まったが、array が sort されてない場合には厄介そうだ。
Posts Tagged ‘rails’
Model.find(array) で順序が狂う
list_tag で Array をリストに展開
あったらいいのに、ということで作った。ApplicationHelper とかに入れればOK.
array がnilや空のときには ul そのものが出ないのがポイント。
1 2 3 4 5 6 7 8 9 10 11 |
# ex: # < %= list_tag(:ul, ["menu1", "menu2"], :class=>"menu") %> # => <ul class="menu"><li>menu1</li><li>menu2</li></ul> def list_tag(wrapper, array, *opt) return if array.to_a == [] content_tag(wrapper, *opt) do array.inject(""){|s,i| s < < content_tag(:li, i) }.html_safe end end |
redirect_toの時はflashでrenderの時はflash.now・・だと??
Railsにはflashという便利な仕組みがあって、redirect_toの先でエラーメッセージを出すのがとても簡単に書ける。便利!
しかし、うっかりそのままrenderしちゃうこともあって、そうするとメッセージが2回表示されるという現象が発生してしまうので、そんなときのために、flash.nowという仕組みも用意されている。
[Rails] flash.now[:notice]とflash[:notice]の違い - 拝啓、シーシュポス
なるほど、よく考えられているなあ、さすがRails.
ちょっとまったー!
僕はnoticeを出したいだけなんですよ。それも1度です。0でも2でもなく1度。そんなん、あたりまえじゃないですか。
なんで、ただ1回noticeを出したいだけの僕が、そのあとrenderになるかredirect_toになるかなんて気にしなきゃいけないんだ?
というわけで、以下のようにした。
ApplicationController に追加
def notice_push(msg)
(session[:notice] ||= []).push msg
end
ApplicationHelper に追加
def notice_pop_all
ret = session[:notice]
session[:notice] = nil
ret || []
end
以上!
使い方?説明しなくてもわかるよね!
ControllerとViewは対応しなくてもいいってさ!
Railsのいくつかのチュートリアルをこなし、いくつかのオンラインドキュメントを読んで、MVCの使い分けはだんだんわかってきた。しかし、はたと立ち止まってしまったことがあったので記録。
ごく簡単な名簿アプリケーションを作る。2つのmodel、 Group と Person があるとする。
Person はいずれか1つの Group に関連づけられるものとする。
/:id を GroupController へ繋ぎ、所属する Person のリストが表示されるものとする。
/:id/:person_id をPersonControllerへ繋ぎ、Person の各種属性を表示編集できるようにする。
Groupを新規作成するための form を / とか /new とかに置く。
ここまではまあ、普通。
Person を新規作成するための form は、どうしようか。
教科書的に考えれば、 /:id で表示されるリストの末尾とかに「人を追加」ってなリンクを用意し、これが /:id/new かなんかに飛んで PersonController#new で承る、と、こうなる。
しかしもし、Person の作成に必要な情報が3つとか4つだったら、「人を追加」なんて悠長なことを言うより、とっととそこにFormを埋めてしまえという気分になる。
姓 | ハンドル | 生年 |
---|---|---|
大久保 | kuboon | 1980 |
猫村 | catchocolate | 1989 |
追加 |
こんなかんじぃ?
RailsのMVC哲学からちょっと外れたような気もするが、UIの最適化を考えれば自然の成り行きである。
さてさて、次が問題だ。
このformのPOST先をどうしよう?
formをGroupControllerで生成したとはいえ、これから生成しようとしているのはPersonであるから、PersonControllerで処理してやりたい、というのが人情というものである。
実際そのような記述は可能であるし、一見何の問題も無いような気が、少なくとも僕はしたのだが。。。
Validationめんどい。。。
中止!中止!
明らかにRailsは、formとそのPOST先が同じControllerであることを要求している。
POST先を別のControllerにしちゃあまずいのである。
と、いうことがわかった。
さーてどうするんだ。「この人でなし!」と言われるのを覚悟でGroupControllerでPersonを生成しちゃうのか、それとも、やはりイニシエの掟に従って、GroupController 側は「人を追加」リンクのみに留めておけということなのか、はたまたajaxでformを表示しちゃうようなウルトラCが既に常套となっているのか。
と、一人ぶつぶつと悩んでいたところで頂いた神の助言が表題である。
ControllerとViewは対応しなくてもいいんだよ!
まーじーかー!
ということで、GroupControllerへPOST、そこでPerson.newし、saveに失敗したらそのままformを再表示、成功したら取得したての:person_idを使って /:id/:person_id へとリダイレクトという流れに落ち着いた。
おしまい。