Question

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.

Was it helpful?

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.

OTHER TIPS

The problem is not the order of execution. The problem is that .build creates an object in memory, but doesn't save it to the database yet. That's why you don't have an id yet. You may want to use .create instead.

Another problem with your code is that you are passing :team_id => @team.id when it's not necessary.

In this code:

@team.departments.build

:team_id will be set implicitly by the build method. So, you can simply do:

@department = @team.departments.build(:organization_id => ...)
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top