Search code examples
ruby-on-railsdevisecontrollerorder-of-execution

Controlling the Order of Execution in Rails Create Action


New to Ruby and programming in general. So far I've had no problems finding answers to any questions I've had, but can't find this one.

In my app the Teams controller new and create actions are creating several new records across several associated models. One of those records is failing to create because it appears the lower record @pool_user is being executed before @department and thus @department.id is nil and email cannot be null.

To test, I removed the @pool_user line and inserted a specific value into :userid => under @competence and it executed in the expected order, creating all records as expected.

I am using Devise for the User model, which I suspect may be influencing it initializing first, but I can't seem to find a way to get them to execute in the correct order.

teams_controller.rb

def new
  @team = Team.new
  @department = Department.new
  @competence = Competence.new
  @pool_user = User.new
  
  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @team }
  end
end

def create
  @team = Team.new(params[:team])
  @department = @team.departments.build(:organization_id => User.current.organization_id, :team_id => @team.id)
  @pool_user = @team.users.build(:email => @department.id).save(:validate => false)
  @competence = @team.competences.build(:team_id => @team.id, :user_id => @pool_user.id)


  respond_to do |format|
    if @team.save
      format.html { redirect_to @team, notice: 'Team was successfully created.' }
      format.json { render json: @team, status: :created, location: @team }
    else
      format.html { render action: "new" }
      format.json { render json: @team.errors, status: :unprocessable_entity }
    end
  end
end

Feel free to correct any other bad practices or general noob moves you see here. I just want to figure out why it isn't building in the correct order. Thanks.


Solution

  • Just calling a build on collection will not actually save the record. You need to save it before using id attribute.

    after executing,

    @team = Team.new(params[:team])
    

    or

    @department = @team.departments.build(:organization_id => User.current.organization_id, :team_id => @team.id)
    

    @team.id or @department.id will give you the nil value.

    As well

    @team.users.build(:email => @department.id).save(:validate => false) 
    

    will return Boolean value i.e. true or false.

    After building you should save this values explicit if you want, like

        @team = Team.new(params[:team])
        @team.save
    

    and

        @pool_user = @team.users.build(:email => @department.id)
        @pool_user.save(:validate => false)
    

    should work.

    I suggest you to try this all in rails console before actually writing any code.