私は同様の状況に直面しました。私のソリューションには、シナリオでパフォーマンスの問題がある可能性がありますが、私にはありませんでしたが、同時使用率が低く、合計ユーザー数が 300 しかありません。
私がしたことは、1 つの MEGA AJAX ビュー/フォームを使用することでした! 必要に応じて JavaScript を使用して表示/非表示を切り替えます。この手法では、フォーム タグ ヘルパー (つまり、f.text_field の代わりに text_field_tag) を使用せず、要素名を制御する必要があります。
したがって、最終的に必要になるすべてのフォームを含む単一のビューを作成することから始めてください。それらを区別する必要があるため、それぞれを一意の ID を持つ div 要素に入れます。
<%= form_for @mega, :remote=>true do %>
<div id='main_part'>
<%= render :partial => "main_part", :object=>@mega %>
</div
<div id='subpart1'>
<%= render :partial => "subpart1" , :object=>@foobar , :locals=>{:id=>@foobar.id} %>
</div
<div id='subpart2'>
<%= render :partial => "subpart2" , :object=>@barfoo , :locals=>{:id=>@barfoo.id} %>
</div
<% end %>
送信ボタンを区別するように注意して、フォーム パーシャルの例を示します。
<%= label_tag "main_part[name]" ,"Name" %>
<%= text_field_tag "main_part[name]" , main_part.name %>
<%= submit_tag "UPDATE", :name=>'main_part' %>
<%= hidden_tag_field "subpart1_id" , id %>
<%= label_tag "subpart1[city]" ,"City" %>
<%= text_field_tag "subpart1[city]" , subpart1.city%>
<%= submit_tag "ADD", :name=>'subpart1' %>
この 1 つのフォームが 1 つのコントローラー アクションに投稿されるため、メガ コントローラーが必要になります。このコントローラーは、最上位モデルのみの通常のコントローラーのように見えますが、すべてのモデルのハウスキーピングを行う必要があります。
そのコントローラーアクションは、どの送信ボタンがクリックされたかを把握する必要があります。
def update
if params[:main_part]
# since I controlled the parameter naming I know what's in params[:main_part]
# which is main_part[:name]
@mega = MainThing.find(params[:id])
@mega.attributes = params[:main_part]
@mega.save
# only for main_part is the id valid, in every other case you have to
# manually extract the id
elsif params[:subpart1]
@subpart1_id = params[:subpart1_id]
@foobar = FooBar.find(@subpart1_id)
@foobar.attrubutes = params[:subpart1]
@foobar.save
else
end
end
メガ フォームは remote=>true であるため、すべてのフォーム パーシャルをリロードする JavaScript ファイルを作成する必要があります。
$('#main_part').html('<%= escape_javascript(render :partial=> "main_part", :object=>@mega) %>');
$('#subpart1').html('<%= escape_javascript(render :partial=> "subpart1", :object=>@foobar :locals=>{:id=>@foobar.id) %>');
ここでパフォーマンスの問題が発生します。気づいたら、その JavaScript を実行すると、これらすべてのインスタンス変数が定義されていることが想定されるため、更新の結果として新しい値を取得した選択タグを更新するさまざまなパーシャルがレンダリングされます。 . 私の場合、前のフィルターでそれらをすべてロードするだけです。
class MegaController < ApplicationController
before_filter :load, :only=>[:edit]
def load
@mega = Mega.find(params[:id])
@foobar = @mega.foobar
@barfoo = @foobar.barfoo
end
ただし、それを行わず、代わりに個々の JavaScript ファイルを作成し、コントローラーで具体的にレンダリングすることもできます。
def update
if params[:main_part]
# do whatever...
render :action=>'update_set1', :handler=>[:erb], :formats=>[:js]
elsif params[:subpart1]
# do whatever
render :action=>'update_set1', :handler=>[:erb], :formats=>[:js]
elsif params[:subpart2]
# do whatever
render :action=>'update_set2', :handler=>[:erb], :formats=>[:js]
end
end
ファイル app/views/mega/update_set1.js.erb は、@mega または @foobar への更新によって影響を受けるパーシャルのみを更新し、update_set2.js.erb は、@barfoo への更新によって影響を受けるパーシャルを更新します。
最後のポイント、フォームは remote=>true です。どのように終了しますか? あなたが持っていると仮定します:
<%= submit_tag 'Cancel', :name=>'cancel' %>
次に、コントローラーで次のようにします。
def update
if params[:cancel]
render :js=> "window.location = '/'"
else
# whatever....
end
end
最後のステップは、必要に応じてフォーム div を表示/非表示にする JavaScript を追加することです。
アップデート
class Mega < ActiveRecord::Base
def self.get_param_name
self.class.name
end
def self.get_id_name
"#{self.class.name}_id"
end
end
class MyModel < Mega
end
次に、メガコントローラーで:
def edit
@mymodel = MyModel.find(params[MyModel.get_id_name])
end