Brian Piercy
Brian Piercy

Reputation: 649

Confused by Rails 4 association bug

I'm fleshing out a new Rails app & am using Rails 4 for the first time. The scaffolding is in place with a single "name" field defined for each MVC.

I then created a simple migration & first model association:

class Ability < ActiveRecord::Base
    belongs_to :player, class_name: "Player", foreign_key: "player_id"
end

class Player < ActiveRecord::Base
    has_many :abilities
end

The console shows the correct fields being in place. I can save things:

> Ability.first
Ability Load (0.1ms)  SELECT  "abilities".* FROM "abilities"   ORDER BY "abilities"."id" ASC LIMIT 1
=> #<Ability id: 1, name: "Ability0", value: 50, created_at: "2014-07-31 16:41:59", updated_at: "2014-07-31 18:14:57", player_id: nil> 

> Player.first
Player Load (0.3ms)  SELECT  "players".* FROM "players"   ORDER BY "players"."id" ASC LIMIT 1
=> #<Player id: 1, name: "Player0", created_at: "2014-07-31 16:42:00", updated_at: "2014-07-31 16:42:00"> 

> Ability.first.player = Player.first
Ability Load (0.4ms)  SELECT  "abilities".* FROM "abilities"   ORDER BY "abilities"."id" ASC LIMIT 1
Player Load (0.2ms)  SELECT  "players".* FROM "players"   ORDER BY "players"."id" ASC LIMIT 1
=> #<Player id: 1, name: "Player0", created_at: "2014-07-31 16:42:00", updated_at: "2014-07-31 16:42:00"> 

> Ability.first.save!
Ability Load (0.4ms)  SELECT  "abilities".* FROM "abilities"   ORDER BY "abilities"."id" ASC LIMIT 1
(0.1ms)  begin transaction
(0.1ms)  commit transaction
=> true

But the save doesn't want to "take":

> Ability.first
Ability Load (0.4ms)  SELECT  "abilities".* FROM "abilities"   ORDER BY "abilities"."id" ASC LIMIT 1
=> #<Ability id: 1, name: "Ability0", value: 50, created_at: "2014-07-31 16:41:59", updated_at: "2014-07-31 18:14:57", player_id: nil>

I know this is a simple thing, but I'm flummoxed. What's the issue?

Upvotes: 1

Views: 37

Answers (1)

Kirti Thorat
Kirti Thorat

Reputation: 53018

You are associating a player to an instance of Ability and saving a completely different instance of Ability (without the associated player) which is why the player is not mapped with your Ability instance.

Let's go through the steps:

Step 1

Ability.first.player = Player.first

Here you created an anonymous instance of Ability which is referring to the first record from abilities table and after this you associated it to the first record from players table. This is all in-memory and the association is not yet saved in table.

Step 2

Ability.first.save!

Next, you are again creating a new anonymous instance of Ability which is referring to the first record from abilities table. BUT it is nowhere related to the instance created in Step 1. Hence, when you fire save! on it, its not going to save anything as none of the fields were changed in this instance.


What you can do is:

ability = Ability.first
ability.player = Player.first
ability.save!

In all the steps you are using the same instance to make changes.

Upvotes: 1

Related Questions