问题
How is the best way to load Category model, for ProductController in new, edit update and create actions
Product has categories collection
class Product < ActiveRecord::Base
has_many :categories
end
Always for new, edit, create and update actions, I need to load the categories collection to populate a check_box_tag list
The "baby steps" for this situation is:
class Admin::ProductsController < Admin::AdminApplicationController
def new
@product = Product.new
@categories = Category.all
end
def edit
@product = Product.find(params[:id])
@categories = Category.all
end
def create
@product = Product.new(params[:product])
if @product.save
flash[:notice] = 'Product was successfully created'
redirect_to edit_admin_product_path(@product)
else
@categories = Category.all
render :new
end
end
def update
@product = Product.find(params[:id])
@product.update_attributes(params[:product])
if @product.save
flash[:notice] = 'Product was successfully updated'
redirect_to edit_admin_product_path(@product)
else
@categories = Category.all
render :edit
end
end
end
I don't want to load always Category.all in different situations for same purpose
Options:
First - load categories over the view:
<% Category.all.each do |cat| %>
<li>
<%= check_box_tag .... %>
</li>
<% end %>
:/
Second - load categories over the ProductsHelper :
module ProductsHelper
def categories
Category.all
end
end
:/
"Third" - Exist a filter like 'before_render'?
class Admin::ProductsController < Admin::AdminApplicationController
before_render :load_categories :edit, :new
def load_categories
@categories = Category.all
end
end
:D :D :D
What's the rails way for this situations?
Best Regards, Pablo Cantero
回答1:
In your controller, or if needed elsewhere, in application_controller.rb:
def all_categories
@all_categories ||= Category.all
end
helper_method :all_categories
The first time it's called, it will hit the db, and later it will return the controller instance variable.
回答2:
I would prefer your third solution. I don't like using business logic in view, because I guess gathering information is the controller's task, in the view layer I just want to use the data and the helper methods. Using Category.all in the view layer can be good when you're using cache, but in this case you should send an expired signal somehow if it changed.
Your first solution has many repeated lines, which you can erase by using your third solution. So I would choose the third one :)
回答3:
I'd go for the first option in this case.
Edit
As I've mentioned in the comments, it depends on the situation. A relatively clean way for me would be to define a categories
method in the controller and declare it a helper. Then call that when you need it in the view.
However (and this is the situation I envisaged when first answering) if it's a single form field I'd simply call the model from the view just for the sake of simplicity - methods like
helper_method :all_categories
private
def all_categories
Category.all
end
aren't exactly the most elegant code.
来源:https://stackoverflow.com/questions/4297269/whats-the-rails-way-to-load-other-models-collections-for-new-edit-update-and-c