Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I faced a similar situation. My solution may have performance issues in your scenario, it didn't for me but it's a low concurrent usage system, only 300 total users.</p> <p>What I did was go with one MEGA AJAX view/form! and use JavaScript to show/hide as needed. This technique requires that you NOT use the form tag helpers (i.e. text_field_tag instead of f.text_field) an YOU have to take control of the element names.</p> <p>So start out creating a single view with all of the forms you'll eventually need. You'll have to distinguish them so put each one in a div element with a unique ID. </p> <pre><code>&lt;%= form_for @mega, :remote=&gt;true do %&gt; &lt;div id='main_part'&gt; &lt;%= render :partial =&gt; "main_part", :object=&gt;@mega %&gt; &lt;/div &lt;div id='subpart1'&gt; &lt;%= render :partial =&gt; "subpart1" , :object=&gt;@foobar , :locals=&gt;{:id=&gt;@foobar.id} %&gt; &lt;/div &lt;div id='subpart2'&gt; &lt;%= render :partial =&gt; "subpart2" , :object=&gt;@barfoo , :locals=&gt;{:id=&gt;@barfoo.id} %&gt; &lt;/div &lt;% end %&gt; </code></pre> <p>An example of the form partials, taking care to distinguish the submit buttons:</p> <pre><code>&lt;%= label_tag "main_part[name]" ,"Name" %&gt; &lt;%= text_field_tag "main_part[name]" , main_part.name %&gt; &lt;%= submit_tag "UPDATE", :name=&gt;'main_part' %&gt; &lt;%= hidden_tag_field "subpart1_id" , id %&gt; &lt;%= label_tag "subpart1[city]" ,"City" %&gt; &lt;%= text_field_tag "subpart1[city]" , subpart1.city%&gt; &lt;%= submit_tag "ADD", :name=&gt;'subpart1' %&gt; </code></pre> <p>So now you'd need a mega controller, because this one form posts to a single controller action. This controller would look like a regular controller for your top level model only, but it will need to do the housekeeping for ALL the models.</p> <p>That controller action has to figure out which submit button was clicked, i.e.</p> <pre><code>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 </code></pre> <p>Since the mega form is remote=>true, you need to create a javascript file that will reload all your form partials, so in app/views/megas/update.js.erb:</p> <pre><code>$('#main_part').html('&lt;%= escape_javascript(render :partial=&gt; "main_part", :object=&gt;@mega) %&gt;'); $('#subpart1').html('&lt;%= escape_javascript(render :partial=&gt; "subpart1", :object=&gt;@foobar :locals=&gt;{:id=&gt;@foobar.id) %&gt;'); </code></pre> <p>Now here is where the performance issues comes in. If you notice, if I run that javascript, it will expect all these instance variables be defined, so the various partial will render refreshing any select tags that got new values as a result of the update. In my case I just load them all up, in a before filter, i.e.</p> <pre><code>class MegaController &lt; ApplicationController before_filter :load, :only=&gt;[:edit] def load @mega = Mega.find(params[:id]) @foobar = @mega.foobar @barfoo = @foobar.barfoo end </code></pre> <p>But you could also NOT to that, and instead create individual javascript files and render them specifically in the controller, i.e.</p> <pre><code>def update if params[:main_part] # do whatever... render :action=&gt;'update_set1', :handler=&gt;[:erb], :formats=&gt;[:js] elsif params[:subpart1] # do whatever render :action=&gt;'update_set1', :handler=&gt;[:erb], :formats=&gt;[:js] elsif params[:subpart2] # do whatever render :action=&gt;'update_set2', :handler=&gt;[:erb], :formats=&gt;[:js] end end </code></pre> <p>The file app/views/mega/update_set1.js.erb would only update the partials affected by an update to @mega or @foobar, update_set2.js.erb would update partials affected by an update to @barfoo.</p> <p>Last point, you're form is remote=>true, how do you exit? Assuming you have:</p> <pre><code>&lt;%= submit_tag 'Cancel', :name=&gt;'cancel' %&gt; </code></pre> <p>Then in a controller you'd do something like:</p> <pre><code> def update if params[:cancel] render :js=&gt; "window.location = '/'" else # whatever.... end end </code></pre> <p>The last step is to add javascript to show/hide the form divs as needed, an exercise left to the reader....</p> <p>UPDATE</p> <pre><code>class Mega &lt; ActiveRecord::Base def self.get_param_name self.class.name end def self.get_id_name "#{self.class.name}_id" end end class MyModel &lt; Mega end </code></pre> <p>then in a mega controller:</p> <pre><code>def edit @mymodel = MyModel.find(params[MyModel.get_id_name]) end </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload