为什么我们需要传递:object to partials?

时间:2011-02-12 19:27:00

标签: ruby-on-rails

我有一个模型类别has_many:subcategories

我正在使用代码来填充子类别的值,根据使用Ajax的视图中的类别下拉值下拉。这是代码:

_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 'subcategories_div', :partial => 'subcatgories', :object => subcategories
  end
end

最后_subcategories.html.erb

<%= f.select :subcategory_id, subcategories, {}, :tab_index => 5 %>

我的问题是,在代码page.replace_html 'subcategories_div', :partial => 'subcatgories', :object => subcategories中,为什么我们将子类别定义为局部变量并将其作为对象传递给部分?我们本来可以这样写的

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

使用@subcategories作为实例变量,以便它在部分中可用,就像在Rails中的普通视图一样。

同样在_subcategories.html.erb

<%= f.select :subcategory_id, @subcategories, {}, :tab_index => 5 %>

和_form.html.erb

<div id = "subcategories_div">
  <%= render :partial => "subcategories" %>
</div>

为什么第一种方法比第二种方法更受欢迎?是因为我们只有一个变量传递给部分?第一种方法是否有任何性能改进?

2 个答案:

答案 0 :(得分:2)

原因是您希望您的部分视图与视图无关。通过使用@subcategories,您可以在部分视图和视图之间创建不必要的依赖关系。这意味着要再次使用相同的部分,您必须确保定义了@subcategories,并且可能不是这种情况。例如,您可能只定义了@my_subcategories或@filtered_subcategories。更糟糕的是,你可能有@subcategories和@filtered_subcategories,你可能想要使用相同的局部显示两者。在这种情况下,最好能够将子类别传递给partial,而不是依赖于设置的实例变量。这样你的部分就是模块化的,并且符合面向对象的封装原则。

例如:

<h1><%= My Subcategories %></h1>
render :partial => 'subcatgories', :object => @my_subcategories
<h1><%= Other Subcategories %></h1>
render :partial => 'subcatgories', :object => @other_subcategories

答案 1 :(得分:1)

你可以优雅地将你的ivars命名为部分,

render 'subcatgories', :subcategories => @hashtags

render 'subcatgories', :subcategories => @legals

然后你可以在你的部分中使用subcategories,使用ivar就像它的名字假装是

去看看ActionView::Rendering#render

有更长的params形式来实现相同的行为...(:partial => 'subcatgories', :locals => {:subcategories => @hashtags}

我相信:subcategories => @hashtags:object => @hashtags

具有更高的可读性