I have a model Category has_many :subcategories
I am using code to populate value of subcategories drop down according to value of categories drop down in a view using Ajax. Here is the code:
_form.html.erb
<%= f.select :category_id, @categories, {}, :tab_index => 4, :onchange => "#{remote_function(:url => {:action => "populate_subcategories"},
:with => "'category_id='+value")}" %>
<div id = "subcategories_div">
<%= render :partial => "subcategories", :object => @subcategories %>
</div>
deals_controller.rb
def new
@deal = Deal.new
@categories = Category.all.map { |category| [category.name, category.id]}
@subcategories = @categories.first.subcategories.map { |subcategory| [subcategory.name, subcategory.id] }
end
def populate_subcategories
subcategories = Subcategory.where(:category_id => params[:category_id]).map { |subcategory| [subcategory.name, subcategory.id] }
render :update do |page|
page.replace_html 'subcateg开发者_开发技巧ories_div', :partial => 'subcatgories', :object => subcategories
end
end
and finally _subcategories.html.erb
<%= f.select :subcategory_id, subcategories, {}, :tab_index => 5 %>
My question is, in the code page.replace_html 'subcategories_div', :partial => 'subcatgories', :object => subcategories
why are we defining subcategories as local variable and passing it as an object to the partial? We could have written like this
def populate_subcategories
@subcategories = Subcategory.where(:category_id => params[:category_id]).map { |subcategory| [subcategory.name, subcategory.id] }
render :update do |page|
page.replace_html 'subcategories_div', :partial => 'subcategories'
end
end
use @subcategories as the instance variable so that it is available in the partial as in the case of normal views in Rails.
Also in the _subcategories.html.erb
<%= f.select :subcategory_id, @subcategories, {}, :tab_index => 5 %>
and in _form.html.erb
<div id = "subcategories_div">
<%= render :partial => "subcategories" %>
</div>
Why is first method preferred over the second one? Is it because we have only one variable to pass to the partial? Is there any performance improvement for first method?
The reason is that you want your partials to be code-independent from your views. By using @subcategories you create a dependency between your partial and your view that is unnecessary. It means that to use that same partial again you must ensure that you have @subcategories defined, and that might not be the case. For example, you might only have @my_subcategories, or @filtered_subcategories defined. Even worse, you might have @subcategories and @filtered_subcategories and you might want to display both using the same partial. In this case it's better to be able to pass your subcategories to the partial instead of depending on instance variables being set. That way your partials are really modular and conform to the object oriented principle of encapsulation.
For example:
<h1><%= My Subcategories %></h1>
render :partial => 'subcatgories', :object => @my_subcategories
<h1><%= Other Subcategories %></h1>
render :partial => 'subcatgories', :object => @other_subcategories
you can gracefully name your ivars in partials,
render 'subcatgories', :subcategories => @hashtags
or
render 'subcatgories', :subcategories => @legals
then you can use subcategories
in your partial, using ivar as like its name pretends to be
go and see ActionView::Rendering#render
there is longer params form to achieve the same behavior ... (:partial => 'subcatgories', :locals => {:subcategories => @hashtags}
)
I believe :subcategories => @hashtags
has superior readability over :object => @hashtags
精彩评论