复杂has_many:通过阻止条件

时间:2015-01-09 19:07:16

标签: ruby-on-rails ruby-on-rails-4 rails-activerecord has-many-through

我在" Rails"中找出如何做到这一点有点困难。如果它甚至可能的话。

背景:我有一个模型客户端,其has_many关系称为:users_and_managers,其定义如下:

has_many :users_and_managers, -> do

  Spree::User.joins(:roles).where( {spree_roles: {name: ["manager", "client"]}})

end, class_name: "Spree::User"

模型Users有一个名为has_many的{​​{1}}关系,它只是一个简单的credit_cards - has_many关系(它在框架中定义)。

简而言之,belongs_to

目标:我想获取属于此客户的用户创建的所有信用卡(如上述关系中所定义)。

问题:我认为我可以使用clients ---has many---> users ---has many---> credit_cards来实现这一点,我这样定义:

has_many ... :through

不幸的是,这与使用角色表的连接产生了错误:

  

SQLite3 :: SQLException:没有这样的列:spree_roles.name

     

SELECT" spree_credit_cards"。*

     

FROM" spree_credit_cards"

     

INNER JOIN" spree_users" ON" spree_credit_cards"。" user_id" =" spree_users"。" id"

     

WHERE" spree_users"。" client_id" = 9 AND" spree_roles"。" name" IN('经理','客户')

(重点和格式化我的)

正如您在生成的查询中看到的那样,Rails似乎忽略了我在has_many :credit_cards, through: :users_and_managers 块中定义的查询的join(:roles)部分,同时仍然保留了where子句部分。

当前解决方案:当然,我可以通过定义一个简单的方法来解决问题:

:users_and_managers

但我觉得必须有更简洁的方法来做这件事,而且我对错误信息的来源感到困惑。

问题:有谁知道为什么AR / Rails似乎是"选择性"关于它将在查询中包含哪些AR方法,以及如何使用def credit_cards Spree::CreditCard.where(user_id: self.users_and_managers.joins(:credit_cards)) end 关系为该客户的所有用户和管理者获取信用卡集合,假设它是可能的?

1 个答案:

答案 0 :(得分:1)

joins(:roles)被忽略,因为无法将ActiveRecord::Relation附加到class Spree::Role < ActiveRecord::Base scope :clients_and_managers, -> { where(name: %w{client manager}) } # a better scope name would be nice :) end class Client < ActiveRecord::Base has_many :users, class_name: "Spree::User", foreign_key: :client_id has_many :clients_and_managers_roles, -> { merge(Spree::Role.clients_and_managers) }, through: :users, source: :roles has_many :clients_and_managers_credit_cards, -> { joins(:clients_and_managers_roles) }, through: :users, source: :credit_cards end 。您需要在块中使用直接AR方法。另外,让我们稍微清理一下:

client = # find client according to your criteria

credit_card_ids = Client.
                  clients_and_managers_credit_cards.
                  where(clients: {id: client.id}).
                  pluck("DISTINCT spree_credit_cards.id")

credit_cards = Spree::CreditCard.where(id: credit_card_ids)

使用该设置,您应该能够执行以下操作:

class Spree::CreditCard < ActiveRecord::Base
  belongs_to :user # with Spree::User conditions, if necessary
end

credit_cards = Spree::CreditCard.
                where(spree_users: {id: client.id}).
                joins(user: :roles).
                merge(Spree::Role.clients_and_managers)

如您所见,该查询数据库两次。要查询一次,请查看以下内容:

{{1}}