STI and polymorphs
Asked Answered
H

5

10

I have problem with my code

class Post < ActiveRecord::Base
end

class NewsArticle < Post
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true
end

And on attempt go get comments for some NewsArticle i see in logs something like

  Comment Load (0.9ms)   SELECT "comments".* FROM "comments" WHERE ("comments"."commentable_id" = 1 and "comments"."commentable_type" = 'Post') ORDER BY created_at

Strange that "commentable_type" = 'Post'. What's wrong?

PS: Rails 2.3.5 && ruby 1.8.7 (2010-01-10 patchlevel 249) [i686-darwin10]

Headwards answered 8/4, 2010 at 21:31 Comment(0)
G
5

The commentable_type field needs to store the name of the table that contains the data, once that row is loaded from the right table, the inherited type will be loaded from the type column on the Posts table.

So:

Here the comment points to the table that it comments on. The posts table, id 1

>> Comment.first
=> #<Comment id: 1, commentable_id: 1, commentable_type: "Post", body: "test", created_at: "2010-04-09 00:56:36", updated_at: "2010-04-09 00:56:36">

Then to load the NewsArticle, id 1 is loaded from posts, and the type there indicates a NewsArticle.

>> Comment.first.commentable
=> #<NewsArticle id: 1, type: "NewsArticle", name: "one", body: "body", created_at: "2010-04-09 00:55:35", updated_at: "2010-04-09 00:55:35">
>> Comment.first.commentable.class.table_name
=> "posts"

If commentable_type held "NewsArticle" it would have to look at the class to determine the table. This way it can just look to the table and worry about the type once it gets there.

Gatias answered 9/4, 2010 at 1:4 Comment(1)
For the polymorphic relationship, only the table matters, once that table is loaded, the inheritance type can be determined.Gatias
G
1

Take a look at the Polymorphic Associations section of ActiveRecord::Associations API. There is a little bit about using polymorphic associations in combination with single table inheritance. Following the second code example in that section I think this might be close to what you want

class Comment < ActiveRecord::Base
  belongs_to :commentable, :polymorphic => true, :counter_cache => true

  def commentable_type=(sType)
   super(sType.to_s.classify.constantize.base_class.to_s)
  end
end

class Post < ActiveRecord::Base
  has_many :comments, :as => :commentable, :dependent => :destroy, :order => 'created_at'
end

class NewsArticle < Post
end
Gittle answered 9/4, 2010 at 21:17 Comment(0)
U
1

def commentable_type=(sType) super(sType.to_s.classify.constantize.base_class.to_s) end

This method is returning class as Post, what to do if you want to store the inherited class Post as commentable_type?

Ulcerous answered 16/12, 2010 at 14:33 Comment(0)
B
1

Good question. I had exactly the same problem using Rails 3.1. Looks the problem is not solved yet. Apparently, using polymorphic associations in combination with Single Table Inheritance (STI) in Rails is a bit complicated.

The current Rails documentation for Rails 3.2 gives this advice for combining polymorphic associations and STI:

Using polymorphic associations in combination with single table inheritance (STI) is a little tricky. In order for the associations to work as expected, ensure that you store the base model for the STI models in the type column of the polymorphic association.

In your case the base model would be "Post", i.e. "commentable_type" should be "Post" for all comments.

Biddie answered 30/5, 2012 at 16:53 Comment(0)
Q
0

Technically, there's actually nothing wrong with this. When Rails is dealing with a polymorphic association, and the object being associated is using STI, it simply uses the base class as the type (in your case "commentable_type").

If you have Post and NewsArticle in separate tables, obviously the commentable_type will show up as Post and NewsArticle respectively.

Quattrocento answered 23/9, 2010 at 12:55 Comment(1)
How can you retrieve the comments from a NewsArticle if this is correct? I am having a similar issue where my query is returning nothing because it is searching for the base class type.Nineteenth

© 2022 - 2024 — McMap. All rights reserved.