I'm having a hard time understanding how to implement a single model self-join in Rails. The Guide to ActiveRecord Associations section 2.10 briefly explains Self-Joins but doesn't offer enough information, and every example or post about this such references the Friendly Friend Railcast example that isn't a single model self join, as described in the Rails Guide section 2.10.
The idea is a model that has_many and belongs_to itself, without needing a separate table for the relationship. The only reason I see for needing a separate table is if you want the relationship to contain more information than just the relationship. e.g. "best friends", "barely know them"
I have a simple Post schema:
create_table "posts", :force => true do |t|
t.datetime "posted"
t.string "nick"
t.string "title"
t.text "content"
t.integer "parent_post_id"
t.datetime "created_at", :null => false
t.datetime "updated_at", :null => false
end
The parent_post_id is a self-reference to other Post post_id's. The posts.rb model has the relationship defined:
class Post < ActiveRecord::Base
has_many :replies, :class_name => "Post"
belongs_to :parent_post, :class_name => "Post",
:foreign_key => "parent_post_id"
end
In the Controller or View I'm hoping to be able to do something like this:
@posts.each do |post|
...
@replies = post.replies
@replies.each do |reply|
...
end
end
Or find a post's parent:
@parent_post = post.parent_post
This may all be some syntax mis-understanding. So thanks in advance to anyone who can slap some sense into me. I've looked through every SO and blog post out there and none try the single model self-referential self-join method described in the Guide.
Points for anyone offering an explanation that doesn't point to the Friendly Friend example that uses a separate relationship table.
A self-join is a join in which a table is joined with itself using a FOREIGN KEY which references its own PRIMARY KEY. This can be viewed as a join of two copies of the same table.
1 What is Active Record? Active Record is the M in MVC - the model - which is the layer of the system responsible for representing business data and logic. Active Record facilitates the creation and use of business objects whose data requires persistent storage to a database.
ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.
What is the difference between includes and joins? The most important concept to understand when using includes and joins is they both have their optimal use cases. Includes uses eager loading whereas joins uses lazy loading, both of which are powerful but can easily be abused to reduce or overkill performance.
I was missing the has_many foreign key to "parent_post_id". Once its set, the post.replies will reference other Post instances by parent_post_id.
The posts.rb model has the relationship defined:
class Post < ActiveRecord::Base
has_many :replies, :class_name => "Post",
:foreign_key => "parent_post_id"
belongs_to :parent_post, :class_name => "Post",
:foreign_key => "parent_post_id"
end
I can now create Posts, assign a parent_post_id to a different Post, then later get all Posts that are replies to any parent Post.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With