Должен ли я отказаться от полиморфной ассоциации? - PullRequest
1 голос
/ 27 мая 2011

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

Не хороня вас, ребята, в деталях, я в основном хочу пройтись по нескольким модельным ассоциациям, чтобы получить некоторую информацию на каждом уровне. Одна ассоциация, вызывающая у меня проблемы, - это полиморфная принадлежность. Вот самые актуальные ассоциации

Model Post
  belongs_to :subtopic
  has_many :flags, :as => :flaggable

Model Subtopic
  has_many :flags, :as => :flaggable

Model Flag
  belongs_to :flaggable, :polymorphic => true

Я бы хотел отобразить несколько флагов в виде индекса Flags #. Также есть информация из других моделей, которую я хочу отобразить, но здесь я опускаю детали, чтобы упростить эту задачу.

В моем действии Flags_controller # index в настоящее время я использую @flags = paginate_by_sql, чтобы извлечь все, что я хочу, из базы данных. Я могу успешно получить данные, но я не могу загрузить связанные объекты модели (хотя все данные, которые я хочу, находятся в памяти). Сейчас я смотрю на несколько вариантов:

  • переписать мои представления для работы с данными SQL в объекте @flags. Это должно сработать и предотвратит 5-6 запросов сопоставления-модели-SQL на строку на странице индекса, но будет выглядеть очень хакерски. Я хотел бы избежать этого, если это возможно

  • упростить мои представления и создать дополнительные страницы для более подробной информации, которые будут загружаться только при просмотре одного отдельного флага

  • изменить иерархию / определения моделей от полиморфных ассоциаций к наследованию. Эффективно создайте модуль или класс FlaggableObject, который будет родительским для Subtopic и Post.

Я склоняюсь к третьему варианту, но я не уверен, что смогу аккуратно извлекать всю информацию, которую хочу, используя только помощники RailR ActiveRecord.

Мне бы хотелось узнать, сработает ли это, и, что более важно, если у вас есть лучшее решение

РЕДАКТИРОВАТЬ: Нечто придирчивое include поведение, с которым я столкнулся

@flags = Flag.find(:all,:conditions=> "flaggable_type = 'Post'", :include => [{:flaggable=>[:user,{:subtopic=>:category}]},:user]).paginate(:page => 1)

=> (valid response)


@flags = Flag.find(:all,:conditions=> ["flaggable_type = 'Post' AND 
  post.subtopic.category_id IN ?", [2,3,4,5]], :include => [{:flaggable=>
  [:user, {:subtopic=>:category}]},:user]).paginate(:page => 1)

=> ActiveRecord::EagerLoadPolymorphicError: Can not eagerly load the polymorphic association :flaggable

Ответы [ 2 ]

1 голос
/ 20 июня 2012

Проблемы: считайте полиморфную ассоциацию.

@flags = Flag.find(:all,:conditions => ["flaggable_type = 'Post' AND post.subtopic.category_id IN ?",
[2,3,4,5]], :include => [{:flaggable => [:user, {:subtopic=>:category}]},:user])
.paginate(:page => 1)

Попробуйте сделать следующее:

@flags = Flag.find(:all,:conditions => ["flaggable_type = 'Post' AND post.subtopic.category_id IN ?",
[2,3,4,5]], :include => [{:flaggable => [:user, {:subtopic=>:category}]},:user])
.paginate(:page => 1, :total_entries => Flag.count(:conditions => 
["flaggable_type = 'Post' AND post.subtopic.category_id IN ?", [2,3,4,5]]))
1 голос
/ 27 мая 2011

Не отбрасывайте полиморфную ассоциацию. Используйте includes(:association_name), чтобы загружать связанные объекты. paginate_by_sql не будет работать, но paginate будет.

@flags = Flag.includes(:flaggable).paginate(:page => 1)

Он будет делать именно то, что вы хотите, используя один запрос из каждой таблицы.

См. Руководство по ассоциациям активных записей . Вы можете увидеть более старые примеры с использованием опции :include, но метод includes - это новый интерфейс в Rails 3.0 и 3.1.

Обновление с оригинального постера:

Если вы получаете эту ошибку: Can not eagerly load the polymorphic association :flaggable, попробуйте что-то вроде следующего:

Flag.where("flaggable_type = 'Post'").includes([{:flaggable=>[:user, {:subtopic=>:category}]}, :user]).paginate(:page => 1)

См. Комментарии для более подробной информации.

...