我应该放弃多态关联吗?

时间:2011-05-27 01:53:01

标签: ruby-on-rails-3 inheritance polymorphic-associations eager-loading will-paginate

我的代码仍处于开发阶段,而不是生产阶段,而且我正在创建一些可以生成我想要的数据的墙。

在没有详细介绍你们的情况下,我基本上想要浏览多个模型关联以获得每个级别的一些信息。给我带来问题的一个关联是多态的belongs_to。以下是最相关的协会

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 #index视图中显示多个标志。我想要显示其他模型的信息,但是我在这里省略了具体细节以保持简单。

在我的Flags_controller #index动作中,我正在使用@flags = paginate_by_sql从数据库中提取我想要的所有内容。我可以成功获取数据,但是我无法获得关联的模型对象(尽管我想要的数据都在内存中)。我现在正在看几个选项:

  • 重写我的视图以处理@flags对象中的SQL数据。这应该工作,并将阻止索引页上每行5-6关联模型-SQL查询,但看起来非常h​​ackish。如果可能的话,我想避免这种情况

  • 简化我的观点并创建其他页面以获取更详细的信息,仅在查看单个旗帜时加载

  • 将模型层次结构/定义从多态关联更改为继承。有效地制作一个模块或类FlaggableObject,它将是SubtopicPost的父级。

我倾向于第三种选择,但我不确定我是否能够使用Rails的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 个答案:

答案 0 :(得分:1)

不要放弃多态关联。使用includes(:association_name)急切加载关联的对象。 paginate_by_sql无效,但paginate会。

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

使用每个表中的一个查询,它将完全符合您的要求。

A Guide to Active Record Associations。您可能会看到使用:include选项的旧示例,但includes方法是Rails 3.0和3.1中的new interface

从原始海报更新:

如果您收到此错误:Can not eagerly load the polymorphic association :flaggable,请尝试以下操作:

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

有关详细信息,请参阅评论。

答案 1 :(得分: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)

尝试以下内容:

@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]]))