views:

36

answers:

2

Let's say I have a User model, and an Invoice model with a belongs_to :user association.

Now I'm creating a new action for my InvoicesController, and the view that will be rendered. The view will have a select-element for selecting the user that this invoice will belong to.

So I need to fetch those users somewhere; my instinct is to leave this kind of thing out of the view. I end up with this:

def new
  @users = User.all
end

The form submit action is create. When the creation fails for some reason, I re-render the new action's view.

def create
  invoice = Invoice.new params[:invoice]
  if invoice.save
    flash[:notice] = 'Invoice created!'
    redirect_to :action => 'show', :id => invoice.id
  else
    @users = User.all
    render :action => 'new'
  end
end

But as you can see, in order the re-render the new action, I have to fetch the users again.

This is just an example, but consider that I have some forms with several select-elements filled from the database, or similar constructs. That turns into an awful lot of repetition.

So how should I structure my controller in this situation?

  • Should I simply use User.all from my view?
  • Should I call new from within create to do the fetching for me?
  • Or something else?
+2  A: 

For this I'd use a before_filter. For example you'd do something like:

  before_filter :fetch_all_users, :only => [:new, :create]

protected

  def fetch_all_users
    @users = User.all
  end

For 90% of my controllers I use the inherited resources plugin. It cuts down the amount of controller code you need to write for CRUD controllers, which also means you can cut down on the amount of tests you need to write.

jonnii
But that would fetch the complete user list in my `list` and `show` actions too. That sounds expensive.
Shtééf
You can use `only` and `except` to scope to a specific set of actions.
jonnii
+1  A: 

I don't seem to have enough rep to just leave this as a comment, but to expand on jonnii's answer, you could use a before_filter to fetch the full user list for only the actions you need it in:

before_filter: :fetch_all_users, :only => [:new, :create, :edit, :update]
Pete Thompson