Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Understanding Rails ActiveRecord "single model" self joins

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.

like image 436
dubmojo Avatar asked Feb 12 '12 16:02

dubmojo


People also ask

What is self join in rails?

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.

What is ActiveRecord in Ruby on Rails?

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.

What does ActiveRecord base mean?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.

What is difference between include and join in rails?

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.


1 Answers

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.

like image 154
dubmojo Avatar answered Sep 17 '22 11:09

dubmojo