Ruby on rails 复杂命名范围:查找不属于某个项目的用户

Ruby on rails 复杂命名范围:查找不属于某个项目的用户,ruby-on-rails,named-scope,has-many,Ruby On Rails,Named Scope,Has Many,我正在尝试创建一个类似User.not_in_projectproject的命名作用域,但找不到正确的方法 我将用户、项目和职责作为加入模型: class User < ActiveRecord::Base has_many :duties, :extend => FindByAssociatedExtension has_many :projects, :through => :duties end class Duty < ActiveRecord::Bas

我正在尝试创建一个类似User.not_in_projectproject的命名作用域,但找不到正确的方法

我将用户、项目和职责作为加入模型:

class User < ActiveRecord::Base
  has_many :duties, :extend => FindByAssociatedExtension
  has_many :projects, :through => :duties
end

class Duty < ActiveRecord::Base
  belongs_to :user
  belongs_to :project
end

class Project < ActiveRecord::Base
  has_many :duties
  has_many :users, :through => :duties
end
但这不会返回没有my_项目的用户,而是返回有my_项目以外的项目的用户

换句话说,我希望命名范围的行为与此方法完全相同:

def self.not_present_in p
  self.all.reject{|u| u.projects.include?(p)}
end

我该怎么做呢?

在SQL中,查询应该是这样的:

select id
  from users
 where id not in (select id
                    from users join duties on users.id = duties.user_id
                    join projects on duties.project_id = projects.id
                   where projects.id = %)
但我不太确定使用命名的\u范围它将如何工作。我会说使用类似

def self.not_present_in p
  find_by_sql ["select id from users where id not in (select id from users join duties on users.id = duties.user_id join projects on duties.project_id = projects.id where projects.id = ?)", p]
end

不像使用AR那么漂亮,但可能会工作并为您节省一些查询

你想得到什么?我对此不清楚。我想要一个行为与此方法完全相同的命名作用域:def self.not_present_in p self.all.reject{u|u.projects.include?p}end我希望它返回没有作为参数传递项目的用户。这有帮助吗?我编辑了这个问题以包含上面的澄清,因为它包含源代码。谢谢Yaraher,您提供的sql查询可以按照我的要求工作,只需稍加修改。在第二次选择后,我必须用users.id替换id,以避免歧义。但是,我无法在命名范围中使用find_by_sql:。但为什么需要它成为命名范围?用于将其与其他方法合并?除非是这样,否则它应该可以正常工作。如果您确实希望稍后对其进行细化,您可以提交一个类似于AR使用方式的选项哈希,并将其与find_by_sql查询连接/合并。可能是一点额外的工作,但它可能会接近你能得到的。ORMs并不总是阻止我们使用SQL:
def self.not_present_in p
  find_by_sql ["select id from users where id not in (select id from users join duties on users.id = duties.user_id join projects on duties.project_id = projects.id where projects.id = ?)", p]
end