【问题标题】:Should I drop a polymorphic association?我应该删除多态关联吗?
【发布时间】:2011-05-27 01:53:01
【问题描述】:

我的代码仍处于开发阶段,而不是生产阶段,我在生成某些视图所需的数据时遇到了困难。

在不详细介绍你们的情况下,我基本上是想浏览多个模型关联以获取每个级别的一些信息。给我带来问题的一个关联是多态的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 查询,但看起来很不雅。如果可能的话,我想避免这种情况

  • 简化我的视图并为更详细的信息创建附加页面,仅在查看单个标志时加载

  • 将模型层次结构/定义从多态关联更改为继承。有效地创建一个模块或类 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

【问题讨论】:

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


    【解决方案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)
    

    请参阅 cmets 了解更多详情。

    【讨论】:

    • 我使用 paginate_by_sql 的原因是急切加载不适用于多态关联。我只是仔细检查以确定并收到此错误Can not eagerly load the polymorphic association :flaggable
    • 您使用的是什么版本的 rails/will_paginate?在发布此答案之前,我在 Rails 3.0.7 和 will_paginate 2.3.15 上对此进行了测试。 will_paginate 寻找缺少的add_limit! 方法,但是在破解之后,它工作正常。
    • 我在 rails 3.0.7 和 will_paginate 3.0.pre2。我试过没有 will_paginate,g = Flag.includes(:flaggable).all,效果很好。添加 will_paginate 调用会产生错误。你对add_limit! 做了什么?
    • 在搜索您的错误消息后,我突然想到您可能从发布的问题中遗漏了查询的相关部分,b/c 我的答案中的代码确实有效。查看thisthis。你能用你的完整查询/分页_by_sql语句更新你的问题吗?
    • 我不确定。我了解您想使用 ActiveRecord 而不是下拉到 SQL 中,但是 AR 提供了一种下拉到 SQL b/c 中的方法,有时这种方法更容易。您是否考虑过使用subqueries?有时它使您的 SQL 更简单。此外,在未来,您应该编辑您的问题并为其添加更新,而不是评论大量代码,尤其是当它与您的整个问题相关时。在与特定答案相关或您想通知回答者时对答案发表评论。
    【解决方案2】:

    问题:对多态关联进行计数。

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多