【问题标题】:rails find: using conditions while including same table twice via different named associationsrails find:使用条件,同时通过不同的命名关联两次包含同一个表
【发布时间】:2017-02-15 15:19:45
【问题描述】:

我有用户发送给其他用户的帖子。有两种模型 - :post 和 :user,并且 :post 具有以下命名关联:

belongs_to :from_user, :class_name => "User", :foreign_key => "from_user_id"
belongs_to :to_user, :class_name => "User", :foreign_key => "to_user_id"

:user 和 :post 都有“is_public”列,表示单个帖子和/或整个用户个人资料可以是公开的或私密的。

我的目标是获取公开且收件人拥有公开个人资料的帖子列表。同时,我想“包括”发件人和收件人信息,以尽量减少数据库调用的数量。挑战在于,我通过命名关联有效地“包含”了同一个表两次,但在我的“条件”中,我需要确保仅按收件人的“is_public”列进行过滤。

我无法执行以下操作,因为“条件”不接受关联名称作为参数:

Post.find(:all, :include => [ :to_user, :from_user ], 
  :conditions => { :is_public => true, :to_user => { :is_public => true }})

因此,我可以实现此目的的一种方法是在“用户”表上进行额外的“加入”:

Post.find(:all, :include => [ :to_user, :from_user ], 
  :joins => "inner join users toalias on posts.to_user_id = toalias.id", 
  :conditions => { :is_public => true, 'toalias.is_public' => true })

有没有更好的,也许更清洁的方法来做到这一点?

提前致谢

【问题讨论】:

  • 你是在 Rails3 中还是在 2.3.x 中?
  • 仍在 2.3 中。希望看到两者的解决方案

标签: ruby-on-rails activerecord


【解决方案1】:

我也遇到了同样的问题,看了rails查询生成的sql查询后找到了解决办法,sql查询自动生成别名 试试这个,

Post.find(:all, :include => [ :to_user, :from_user ], 
       :conditions => { :is_public => true, 'to_users_posts.is_public' => true })

它对我有用:)

【讨论】:

    【解决方案2】:

    我找不到比我最初在问题中提出的解决方案更好的解决方案。这个不依赖于 Rails 在编译查询时如何命名/别名表,因此看起来比替代方案更干净(缺少使用 3rd 方 gem 或插件):

    Post.find(:all, :include => [ :to_user, :from_user ],
    :joins => "inner join users toalias on posts.to_user_id = toalias.id", 
    :conditions => { :is_public => true, 'toalias.is_public' => true })
    

    【讨论】:

      【解决方案3】:

      如果您使用的是 Rails 3,请查看 squeel gem,尤其是如果您经常执行此类复杂的连接。或者,如果您不想添加额外的 gem,请查看 Rails 3 中的 Arel 表。

      【讨论】:

        【解决方案4】:

        我对这个问题感到非常满意,因为我试图在 2 小时左右找到合适的解决方案,所以在使用了上面的一些技巧之后,我找到了合适的解决方案,就我而言。我的情况: 我需要通过 created_by_id/updated_by_id 字段过滤实例,该字段在每个表中,所以......我做了什么 考虑到“可过滤”,我编写了该方法,当我需要按该字段进行过滤时,我使用了该方法->

        key = "#{key.pluralize}_#{name.pluralize.downcase}.email" if %w(created_by updated_by).include?(key)

        # in case with invoices key = 'updated_bies_invoices.email'
        

        results = results.eager_load(:created_by, :updated_by).where("#{key} = ?", value)

        【讨论】:

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