передача объекта для полиморфного параметра поиска в Rails find / where - PullRequest
4 голосов
/ 16 июля 2011

Допустим, у меня есть:

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

class Article < ActiveRecord::Base
  has_many :comments, :as => :commentable
end
class Photo < ActiveRecord::Base
  has_many :comments, :as => :commentable
  #...
end

Теперь я хочу найти все комментарии к фотографии Джима:

@jims_photo = Photo.where(:of => "Jim")
@photo_comments = Comment.where(:commentable => @jims_photo)

это, похоже, не работает в рельсах (Rails 3).Похоже, что сгенерированный запрос не расширяет полиморфный объект в поля commentable_id и commentable_type:

SQLite3::SQLException: no such column: comments.commentable:

Я новичок в ruby ​​и rails, так что я могу использовать парадигму неправильно, но я ожидал, что rails автоматически расширяется

:commentable => @jims_photo 

до:

:commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name

Ответы [ 2 ]

3 голосов
/ 10 июля 2013

Если вы хотите быть в безопасности с:

:commentable_id => @jims_photo.id, :commentable_type => @jims_photo.class.name

Тогда я бы порекомендовал заменить .class.name на .base_class (на самом деле name: to_s не возвращает name и будет вызываться автоматически).

Причина этого в том, что когда ActiveRecord сохраняет _type для полиморфной ассоциации, он будет использовать base_class, чтобы гарантировать, что он не сохраняет класс, который сам по себе является полиморфным.

Если вы играете с store_full_sti_class, вам, вероятно, придется принять еще больше мер предосторожности.

Я настоятельно рекомендую посмотреть STI-код Rails, здесь .

2 голосов
/ 06 сентября 2012

Руководства по Rails являются одними из лучших, поэтому я бы посоветовал вам начать читать о Полиморфные ассоциации

Ваши объявления классов выглядят нормально, и я предполагаю, что вы тоже переносите. Но только ради этого. Допустим, это выглядит так:

class CreateComment < ActiveRecord::Migration
  def change
    create_table :comments do |t|
      t.string :name
      t.references :commentable, :polymorphic => true
      # this is the equivalent of
      # t.integer :commentable_id
      # t.string  :commentable_type

      t.timestamps
    end
  end
end

Нет, если у вас есть объект Article или Photo и вы хотите получить комментарии для этого объекта, тогда предложение Тило верно. Все, что вам нужно сделать, это: @jims_photo.comments

Если, с другой стороны, у вас есть экземпляр модели Comment, вы можете получить родителя следующим образом: @comment.commentable. Но если вы хотите получить фото комментарии Джима, лучше всего так. В противном случае вы должны будете указать в качестве аргументов :commentable_id и commentable_type. Я не знаю ни одного искателя, который расширяет полиморфный объект в поля commentable_id и commentable_type для вас.

Но вы всегда можете создать метод класса для этого:

def self.find_by_parent(parent)
  where(:commentable_id => parent.id, :commentable_type => parent.class.name)
end
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...