Rails habtm 和查找没有关联的记录

发布于 2024-11-29 01:40:36 字数 799 浏览 7 评论 0原文

我有 2 个模型:

class User < ActiveRecord::Base
    has_and_belongs_to_many :groups
end

class Group < ActiveRecord::Base
    has_and_belongs_to_many :users
end

我想创建一个返回不属于任何组的用户的范围(这很重要 - 对于效率和链接范围的能力)。 经过多次尝试,我未能执行方法而不是作用域,这使得 User.all 上的 collect 很丑陋而且......不正确。

有什么帮助吗?

也许对于第二个问题: 我设法创建一个范围,返回属于任何给定组的用户(以 id 数组形式给出)。

scope :in_groups, lambda { |g|
        {
          :joins      => :groups,
          :conditions => {:groups => {:id => g}},
          :select     => "DISTINCT `users`.*" # kill duplicates
        }
      }

它可以更好/更漂亮吗? (使用 Rails 3.0.9)

I have 2 models:

class User < ActiveRecord::Base
    has_and_belongs_to_many :groups
end

class Group < ActiveRecord::Base
    has_and_belongs_to_many :users
end

I want to make a scope (that's important - for efficiency and for ability to chain scopes) that returns Users that doesn't belong to ANY Groups.
After many tries, I failed in doing a method instead of scope, which makes collect on User.all which is ugly and.. not right.

Any help?

And maybe for 2nd question:
I managed to make a scope that returns Users who belongs to any of given groups (given as an array of id's).

scope :in_groups, lambda { |g|
        {
          :joins      => :groups,
          :conditions => {:groups => {:id => g}},
          :select     => "DISTINCT `users`.*" # kill duplicates
        }
      }

Can it be better/prettier?
(Using Rails 3.0.9)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

偏爱你一生 2024-12-06 01:40:36

根据命名约定,您的隐式联接表将被命名为groups_users。在您的数据库中确认一次。假设是:

在较新的 Rails 版本中:

scope :not_in_any_group, -> {
    joins("LEFT JOIN groups_users ON users.id = groups_users.user_id")
    .where("groups_users.user_id IS NULL")
}

对于较旧的 Rails 版本:

scope :not_in_any_group, {
    :joins      => "LEFT JOIN groups_users ON users.id = groups_users.user_id",
    :conditions => "groups_users.user_id IS NULL",
    :select     => "DISTINCT users.*"
}

Your implicit join table would have been named groups_users based on naming conventions. Confirm it once in your db. Assuming it is:

In newer Rails version:

scope :not_in_any_group, -> {
    joins("LEFT JOIN groups_users ON users.id = groups_users.user_id")
    .where("groups_users.user_id IS NULL")
}

For older Rails versions:

scope :not_in_any_group, {
    :joins      => "LEFT JOIN groups_users ON users.id = groups_users.user_id",
    :conditions => "groups_users.user_id IS NULL",
    :select     => "DISTINCT users.*"
}
2024-12-06 01:40:36

如果您通过(更灵活的)关联从 HABTM 转换为 has_many,那么您可以使用如下内容:

class Group < ActiveRecord::Base
  has_many :groups_users, dependent: :destroy
  has_many :users, through: :groups_users, uniq: true

  scope :in_groups, -> { includes(:groups_users).where(groups_users: {group_id: nil}) }
end

class User < ActiveRecord::Base
  has_many :groups_users, dependent: :destroy
  has_many :groups, through: :groups_users
end

class GroupsUser < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

If you convert from HABTM to has_many through (more flexible) association, then you can use something like this:

class Group < ActiveRecord::Base
  has_many :groups_users, dependent: :destroy
  has_many :users, through: :groups_users, uniq: true

  scope :in_groups, -> { includes(:groups_users).where(groups_users: {group_id: nil}) }
end

class User < ActiveRecord::Base
  has_many :groups_users, dependent: :destroy
  has_many :groups, through: :groups_users
end

class GroupsUser < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end
白云悠悠 2024-12-06 01:40:36

在Rails >= 5中,有left_outer_joins,组合使用新的(ish) .where() 语法,使作用域更具​​可读性:

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups

  scope :not_in_any_group, -> {
    left_outer_joins(:groups)
    .where(groups_users: { user_id: nil })
  }
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
end

In Rails >= 5, there is left_outer_joins, combined with the new(ish) .where() syntax, makes the scope a bit more readable:

class User < ActiveRecord::Base
  has_and_belongs_to_many :groups

  scope :not_in_any_group, -> {
    left_outer_joins(:groups)
    .where(groups_users: { user_id: nil })
  }
end

class Group < ActiveRecord::Base
  has_and_belongs_to_many :users
end

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文