开发者

What's the rails way to load other models collections for new, edit update and create actions?

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.a开发者_如何学Pythonll
 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


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.


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 :)


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜