Reputation: 5552
I have read this, so I do understand the difference.
But I have inherited an app that is throwing strange behaviour (I think, perhaps I am wrong and this is normal).
There are 2 models:
class Pod < ActiveRecord::Base
has_one :pod_admin
end
class PodAdmin < ActiveRecord::Base
belongs_to :pod
end
In the rails console, I tried this:
p = Pod.find(5)
and it shows this Pod has a pod_admin_id
value of 14. This is correct.
I tried to change the PodAdmin:
p.pod_admin = PodAdmin.last
and it throws this error:
NoMethodError: undefined method pod_admin_id for #<PodAdmin:0x007fa401f1e710>
Why is that? What am I missing?
EDIT
Based on comments/answers, without changing the models, I tried this:
pa = PodAdmin.last
pa.pod = p
and that works, I see the console return the last PodAdmin with a new pod_id.
BUT
pa.save
AND
p.save
both throw the same error as before.
If I look at the database schema, the Pod table has a pod_admin_id field and the PodAdmin table has a pod_id field.
I inherited this schema and I am just wondering if the original developer set this up correctly. Surely I should be able to update the relationship from either direction - isn't that the point of creating has_one and belongs_to, so you can have bi-directional relationships like this?
EDIT 2
I found the problem, which is that I had added this line to PodAdmin table instead of the Pod table:
validates :pod_admin_id, uniqueness: {scope: :id, message: 'The Pod already has a PodAdmin'}
Apologies - but as you can see, what I am trying to achieve here is to prevent a Pod from having 2 PodAdmins. This validates does not seem to achieve that.
I can do this:
p = Pod.find(5)
pa_last = PodAdmin.last
pa_first = PodAdmin.first
pa_last = p
pa_first = p
pa_last.save
pa_first.save
and now both pa's have the same pod_id. How can I prevent that from happening?
EDIT 3
After much reading and testing and with thanks to both @Anand and @Spickerman the problem was that the previous developer put a foreign key into both tables (the has_one
and the belongs_to
). Only the belongs_to table should have a foreign key. Also, the relationship had been defined the wrong way round. However, fixing this does not guarantee a robust solution. I highly recommend others with similar issues read this.
Upvotes: 1
Views: 245
Reputation: 3760
Instead of p.pod_admin = PodAdmin.last
, call PodAdmin.last.pod = p
- as others have mentioned, the pod_id is in the PodAdmin table, and not the other way around.
Based on update to question, the problem is because you have foreign key references both ways - you should either have pod_id in pod_admins table or pod_admin_id in pods table, but not both. Remove one of them with a new migration, and try again
> bundle exec rails g migration RemovePodIdFromPodAdmins
# db/migrations/XXXX_remove_pod_admin_id_from_pods
def change
remove_column :pods, :pod_admin_id
end
bundle exec rake db:migrate
Then, as suggested above, call
pa = PodAdmin.last
pa.pod = p
pa.save!
Upvotes: 1
Reputation: 106792
The foreign key always belongs to the Model with the belongs_to
association.
In your example PodAdmin
belongs_to
Pod
, therefore your pod_admins
table should have a pod_id
column.
Or you can just change your models to the following to reflect your database schema:
class Pod < ActiveRecord::Base
belongs_to :pod_admin
end
class PodAdmin < ActiveRecord::Base
has_one :pod
end
Upvotes: 1