【问题标题】:Complicated named_scope: Find users who don't belong to a certain project复杂的named_scope:查找不属于某个项目的用户
【发布时间】:2009-09-07 11:43:21
【问题描述】:

我正在尝试创建像 User.not_in_project(project) 这样的命名范围,但我找不到正确的方法。

我将用户、项目和职责作为连接模型:

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

我尝试使用类似于此 find 子句的named_scope

User.all(:joins => :duties, :conditions => ['duties.project_id != ?', my_project])

但这不会返回没有my_project 的用户,而是拥有my_project 以外项目的用户。

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

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

我该怎么做?

【问题讨论】:

  • 您想要返回什么?这个我不是很清楚。
  • 我想要一个行为与此方法完全相同的命名范围:def self.not_present_in p self.all.reject{|u| u.projects.include?(p)} end 我希望它返回没有将 Project 作为参数传递的用户。这有帮助吗?
  • 我编辑了问题以包含上述说明,因为它包含源代码。

标签: ruby-on-rails named-scope has-many


【解决方案1】:

在 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 = %)

但我不太确定使用 named_scope 会如何工作。我会说使用类似

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 漂亮,但可以工作(可能会为您节省一些查询)。

【讨论】:

  • 感谢 Yaraher,您提供的 sql 查询可以按我的意愿工作,但需要进行小修复。在第二次选择之后,我不得不用“users.id”替换“id”,以免模棱两可。但是,我不能在 named_scope 中使用 find_by_sql :(.
  • 但是为什么需要它作为命名范围呢?将其与其他方法合并?除非是这种情况,否则它应该可以正常工作。如果您确实想稍后对其进行改进,您始终可以提交一个类似于 AR 使用方式的选项哈希,并将其与 find_by_sql 查询连接/合并。可能需要做一些额外的工作,但它可能会尽可能接近。 ORM 并不总是阻止我们使用 SQL :)
猜你喜欢
  • 2013-02-05
  • 2016-07-18
  • 2021-02-12
  • 2013-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-05-27
  • 2023-04-02
相关资源
最近更新 更多