ИППП и полиморфы - PullRequest
       35

ИППП и полиморфы

10 голосов
/ 09 апреля 2010

У меня проблема с моим кодом

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

И при попытке пойти получить комментарии для некоторых NewsArticle я вижу в журналах что-то вроде

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

Странно, что "commentable_type" = 'Post' . Что не так?

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

Ответы [ 5 ]

5 голосов
/ 09 апреля 2010

В поле commentable_type необходимо сохранить имя таблицы, содержащей данные, после загрузки этой строки из правой таблицы унаследованный тип будет загружен из типа . столбец в таблице сообщений .

Итак:

Здесь комментарий указывает на таблицу, в которой он комментирует. Стол сообщений, 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">

Затем для загрузки NewsArticle из сообщений загружается id 1, а тип там указывает на 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"

Если commentable_type удерживается "NewsArticle", ему придется взглянуть на класс, чтобы определить таблицу. Таким образом, он может просто смотреть на таблицу и беспокоиться о типе, когда попадет туда.

1 голос
/ 30 мая 2012

Хороший вопрос. У меня была точно такая же проблема с использованием Rails 3.1. Похоже, проблема еще не решена. По-видимому, использование полиморфных ассоциаций в сочетании с Single Table Inheritance (STI) в Rails немного сложнее.

Текущая документация по Rails для Rails 3.2 дает этот совет для объединения полиморфных ассоциаций и STI :

Использование полиморфных ассоциаций в сочетании с одной таблицей Наследование (ИППП) немного сложнее. Для того чтобы ассоциации работать как положено, убедитесь, что вы храните базовую модель для ИППП модели в столбце типа полиморфной ассоциации.

В вашем случае базовой моделью будет «Post», то есть «commentable_type» должен быть «Post» для всех комментариев.

1 голос
/ 16 декабря 2010

def commentable_type = (sType) супер (sType.to_s.classify.constantize.base_class.to_s) конец

Этот метод возвращает класс как Post, что делать, если вы хотите сохранить унаследованный класс Post как commentable_type?

1 голос
/ 10 апреля 2010

Взгляните на раздел «Полиморфные ассоциации» ActiveRecord :: Associations API. Немного об использовании полиморфных ассоциаций в сочетании с наследованием одной таблицы. После второго примера кода в этом разделе я думаю, что это может быть близко к тому, что вы хотите

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
0 голосов
/ 23 сентября 2010

Технически, в этом нет ничего плохого. Когда Rails имеет дело с полиморфной ассоциацией, а связанный объект использует STI, он просто использует базовый класс как тип (в вашем случае «commentable_type»).

Если у вас есть Post и NewsArticle в отдельных таблицах, очевидно, что commentable_type будет отображаться как Post и NewsArticle соответственно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...