【问题标题】:Convert Ruby mapping statement to ActiveRecord query?将 Ruby 映射语句转换为 ActiveRecord 查询?
【发布时间】:2013-08-28 17:57:45
【问题描述】:

在我的数据库中,用户和角色之间存在多对多关系 (HABTM)。我正在尝试获取与特定秘书关联的用户的所有角色名称。

我设法将以下内容拼凑在一起:

class Secretary < ActiveRecord::Base
  def getRoles
    rolenames = Set.new
    Role.all.map { |role| role.users.map { |user| rolenames << role.name if user.manager.secretary == self } }
    rolenames.to_a
  end
end

...这行得通,但似乎一个精心设计的“where”语句应该产生相同的结果,而不会对数据库造成太多影响。

是否可以将上述内容转换为更“原生”的 ActiveRecord 查询?

【问题讨论】:

    标签: ruby-on-rails ruby ruby-on-rails-3 rails-activerecord


    【解决方案1】:

    您没有提供足够的信息来清楚地了解您的模型。从您提供的内容来看,我猜从秘书的角度来看是这样的:

    Secretary
     has_many :managers
    
    Manager
     has_namy :users
    
    User
     has_many :roles
    

    在从深度嵌套的模型中检索记录时,根据 id(外键)进行思考会很有帮助:Rails Nested SQL Queries

    因为 Rails 会在 where 语句的哈希版本中自动将记录转换为 id。

    Role.where(:user_id => User.where(:manager_id => managers))
    

    如果我对您的模型的假设是正确的,应该会得到您的答案。

    编辑: 好吧,HABTM 有点搅浑水。我们不能做嵌套 where's 但我们仍然可以做一个 where 以及一些映射,而不会对数据库造成太大的影响。试试这个:

    User.includes(:roles).where(manager_id: managers).flat_map(&:roles).map(&:name)
    

    【讨论】:

    • 问题中提到,Users和Roles的关系是HABTM关系(has_and_belongs_to_many,有join表)。经理确实有很多系统用户,秘书也确实有很多经理。所以查询应该返回给定秘书下给定经理下所有用户的角色集。这是否说明了问题?
    • 内部查询有效,但外部Role.where(:user_id =&gt; ...) 查询似乎没有返回任何内容。我也试过Role.include(:users).where(:user_id =&gt; ...),结果相似。
    • 我假设您在控制台中。添加 .to_sql 看看你得到了什么。括号中应该有 2 个带有 id 的 IN 子句。
    • 更正:内部 where 应该生成一个带有 id 的 IN 子句,外部 where 应该生成一个带有 select 语句的 IN 子句。也许没有要检索的数据?似乎在这里工作 - Ruby 1.9.3,Rails 3.2.8
    • 查看 .to_sql 的输出,我认为问题一定与两个“IN”中的第一个有关。换句话说,WHERE "roles"."user_id" IN 由于 HABTM 关系而不起作用。有一个连接表,所以没有直接在 Roles 表上的"user_id" 列。我想问题是,如何通过连接表获取"user_id"
    【解决方案2】:

    看来你的模型是这样的:

    Role 
      has_many :users
    User 
      belongs_to :role 
      has_one :manager, :class => 'User'
    

    在这种情况下,只需内部连接表格即可返回您所追求的结果:

    SELECT roles.* FROM roles
    INNER JOIN users u ON u.role_id = roles.id
    INNER JOIN users m ON m.id = u.id
    

    这个查询可以翻译成这样:

    Role.joins(:users => :manager)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2018-12-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多