0

ユーザーをdefault_scope一連の企業に制限する User クラスがあります。

class User < ActiveRecord::Base
  default_scope do
    c_ids = Authorization.current_company_ids
    includes(:companies).where(companies: { id: c_ids })
  end

  has_many :company_users
  has_many :companies, through: company_users
end

class CompanyUser < ActiveRecord::Base
  belongs_to :user
  belongs_to :company
  validates_uniqueness_of :company_id, scope: :user_id
end

class Company < ActiveRecord::Base
  has_many :company_users
  has_many :users, through: company_users
end

期待どおりに、またはUser.lastすべての作業と範囲を呼び出します。User.find_by_email('mhayes@widgetworks.com')User.find(55557)

呼び出すUser.exists?(id)と、奇妙なエラーがスローされます。

Mysql2::Error: Unknown column 'companies.id' in 'where clause': SELECT  1 AS one FROM `users`  WHERE `companies`.`id` IN (4) AND `users`.`id` = 55557 LIMIT 1

基本的に、私がこれを取得している場合、それcompaniesは のコラムではないと言ってUserいます。SQLをステートメントにコピーしても、where正しく評価されます。

User.where("SELECT  1 AS one FROM `users`  WHERE `companies`.`id` IN (4) AND `users`.`id` = 66668 LIMIT 1")

と評価の順番があり、どういうわけか前に呼び出されていると思わせてdefault_scopeくれexists?ますdefault_scope

私が電話した場合:

User.includes(:companies).where(companies: { id: [4] }).exists?(55557)

動作します。そして、これがdefault_scopeが行っていることなので、default_scopeスコープが失敗していないことはわかっています。

4

2 に答える 2

1

正直なところわかりませんが、関係を直接exists?構築し、他のオブジェクトをロードする必要がないと判断したため、句を破棄することにしたように見えます。これは、このメソッド呼び出しで発生します。チェーン化されたものは、以前のリレーションを構築することですでに適切に計算さています( get が に変換されている場合)。includesexists? exists?includesjoins

バグではないかもしれませんが、リストに追加する別の奇妙さdefault_scope.

おそらく最善の解決策は、includesinをdefault_scope実際に作成し、完全なレコードが実際に必要なときにjoins手動で呼び出すことです。(通話includesには実際には必要ないため)exists?

もう 1 つの可能性は、 と の両方includesをチェーンjoinsすることdefault_scopeです。arel私はこれが計算に何をするのか分かりませんが、私は多くのことを疑っています. 機能する場合と機能しない場合があります。

または、全体的に同じままにしたい場合は、次のようなクレイジーなことを行うことができます。

def self.exists?(args)
  self.scoped.exists?(args)
end

基本的に、デフォルトのスコープでリレーションを構築し、すでに->マジックを実行exists?したその構築されたリレーションを呼び出します。includesjoins

于 2015-04-13T21:50:11.920 に答える