Willy Xiao
Willy Xiao

Reputation: 430

Does there have to be a foreign key for activerecord associations?

I'm working on associations for two rails models: User and Post

I have a has_many association between user and posts and the inverse relationship of belongs_to.

I would also like to have a has_one association between User and Post but on this association, I don't want a foreign key from Post to User.

For example

class User < ActiveRecord::Base
  has_many :posts
  has_one :current_post
end

class Post < ActiveRecord::Base
  belongs_to :user
end

So the has_many :posts has a foreign_key of user_id on Post, but I don't want the current_post to also have this inverse relationship. Is there a way to do this (e.g. has_one :current_post, :foreign_key => false)?

Upvotes: 1

Views: 2283

Answers (1)

Rab
Rab

Reputation: 2836

It seems like you have the idea of the relationship backwards. The foreign key is what actually creates the association -- without it, nothing is associated. Think of the foreign key as a pointer or address that points back to the parent object. Any particular child is associated with a parent because it stores the parent's foreign key. To search a parent's children, you look for that parent's primary key inside child objects of a type that you have specified the parent "has_one" or "has_many" of. If you just had "has_many" and no foreign keys, zero relationships would be created because no specific object would actually be pointing to any other object.

What you can do, if you really want, is have belongs_to without a has_one or has_many. If you do that, you will be able to find a parent object starting from the child, because the child will have the pointer to the parent. But you'll find it more difficult to find out which child objects the parent has, because you have not told ActiveRecord that the parent model is supposed to have any children.

In your example, User has_many posts and Post belongs_to user are fine. But when you say User has_one current_post you're telling ActiveRecord to look for a key that does not exist.

One way to solve the problem might be to always store the foreign key of the most current post with the user. It sounds counter-intuitive to say User belongs_to current_post but it accomplishes what I think you want it to do.

That said, storing a key to the current or latest post might not be necessary at all. A timestamp is automatically created with any model ActiveRecord generates, so you can just get the post with the most recent timestamp if that is all you're looking for.

Upvotes: 1

Related Questions