DRY up ivar assignment in Rails new and create controller actions When creating a new model in Rails, I need to pass a bunch of other models into the view so I can define the correct associations. All I’m really doing here is querying the persistence layer for models and assigning them to instance variables, but I’m having to do it twice. What’s the best way of extracting the assignment? Just creating a controller method and calling it? I’m not sure.

class ProjectsController &lt; ApplicationController
  def new
    @project = Project.new
    @companies = Company.as_select_options
    @project_varieties = ProjectVariety.as_select_options
    @prices = Price.as_select_options
    @users = User.as_select_options
  end

  def create
    @project = Project.new(project_params)
    @companies = Company.as_select_options
    @project_varieties = ProjectVariety.as_select_options
    @prices = Price.as_select_options
    @users = User.as_select_options
    if @project.save
      flash[:success] = "#{@project.name} has been created."
      redirect_to @project
    else
      render :new
    end
  end
end
Simplest thing would be to add a protected method to the controller and a matching before_filter/before_action callback:

Your actions become:

class ProjectsController &lt; ApplicationController
  before_filter :load_select_options, only: [:new, :create]

  def new
    @project = Project.new
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      flash[:success] = "#{@project.name} has been created."
      redirect_to @project
    else
      render :new
    end
  end

  protected

  def load_select_options
    @companies = Company.as_select_options
    @project_varieties = ProjectVariety.as_select_options
    @prices = Price.as_select_options
    @users = User.as_select_options
  end
end


If you have an edit action, add that to the before-filter's list too.

However, since you (presumably) only need to load all that stuff in create if you have to render the new template, you can skip the before filter, and instead do something more targeted:

class ProjectsController &lt; ApplicationController
  def new
    @project = Project.new
    load_select_options
  end

  def create
    @project = Project.new(project_params)
    if @project.save
      flash[:success] = "#{@project.name} has been created."
      redirect_to @project
    else
      load_select_options
      render :new
    end
  end

  protected

  def load_select_options
    @companies = Company.as_select_options
    @project_varieties = ProjectVariety.as_select_options
    @prices = Price.as_select_options
    @users = User.as_select_options
  end
end