【问题标题】:Arel::SelectManager how to access the result including the projectionsArel::SelectManager 如何访问包括投影在内的结果
【发布时间】:2019-03-04 04:19:49
【问题描述】:

我正在尝试访问连接的结果,其中两个表的列都被指定为投影的一部分。

我有 2 个模型(Rails 4.2.11;Arel 6.0.4;Ruby 2.5.3)

# Table name: users
#
#  id         :integer          not null, primary key
#  name       :string(255)
#  email      :string(255)
#  created_at :datetime         not null
#  updated_at :datetime         not null

class User < ActiveRecord::Base
  has_many :photos
end

# Table name: photos
#
#  id            :integer          not null, primary key
#  name          :string(255)
#  created_by_id :integer
#  assigned_id   :integer
#  created_at    :datetime         not null
#  updated_at    :datetime         not null
#  user_id       :integer

class Photo < ActiveRecord::Base
  belongs_to :user
end
creators = User.arel_table.alias('creators')
updaters = User.arel_table.alias('updaters')
photos = Photo.arel_table

photos_with_credits = photos.
join(photos.join(creators, Arel::Nodes::OuterJoin).on(photos[:created_by_id].eq(creators[:id]))).
join(photos.join(updaters, Arel::Nodes::OuterJoin).on(photos[:assigned_id].eq(updaters[:id]))).
project(photos[:name], photos[:created_at], creators[:name].as('creator'), updaters[:name].as('editor'))
# generated SQL
SELECT photos.name, photos.created_at, creators.name AS creator, updaters.name AS editor 
FROM photos 
INNER JOIN (SELECT FROM photos LEFT OUTER JOIN users creators ON photos.created_by_id = creators.id) 
INNER JOIN (SELECT FROM photos LEFT OUTER JOIN users updaters ON photos.updated_by_id = updaters.id)

我想如何处理结果

photos_with_credits.map{|x| "#{photo.name} - copyright #{photo.created_at.year} #{photo.creator}, edited by #{photo.editor}"}.join('; ')

这可能是一个非常愚蠢的问题,但是...... 由于 map 已从 SelectManager 类中弃用(并删除),因此我无法找到一种方法来使用 SelectManager 结果来产生有意义的输出。

感谢您的帮助。

【问题讨论】:

    标签: ruby-on-rails arel


    【解决方案1】:

    简化了 activerecord / arel 查询生成器

    修改代码

    photos_with_credits = Photo.select([photos[:name], photos[:created_at], creators[:name].as('creator'), updaters[:name].as('editor')]).
    joins(photos.outer_join(creators).on(photos[:created_by_id].eq(creators[:id])).join_sources).
    joins(photos.outer_join(updaters).on(photos[:assigned_id].eq(updaters[:id])).join_sources)
    
    photos_with_credits.map do |photo|
      puts "#{photo.name} - copyright #{photo.created_at.year} #{photo.creator}, edited by #{photo.editor}".light_blue
    end
    
    修正 SQL(更简单)
    SELECT photos.name, photos.created_at, creators.name AS creator, updaters.name AS editor 
    FROM photos 
        LEFT OUTER JOIN users creators ON photos.created_by_id = creators.id 
        LEFT OUTER JOIN users updaters ON photos.assigned_id = updaters.id
    

    【讨论】:

      【解决方案2】:

      我们应该想办法触发SelectManage并得到ActiveRelation结果,然后我们可以通过使用map等来迭代它。

      所以我想建议:

      Photo.join(photos_with_credits.join_sources).map do |photo|
        "#{photo.name} - copyright #{photo.created_at.year} #{photo.creator}, edited by #{photo.editor}"}.join('; ')
      end
      

      【讨论】:

      • 谢谢。它确实生成了一个 ActiveRelation。但是,它也会导致错误“#<:selectmanager:0x000055dc3cdb0e48> 的未定义方法 `table_name'”。我看不出它可能来自哪里(除了 SelectManager)。我错过了什么?
      • 在进一步的研究中,我已经改变了上面的查询photos_with_credits,它现在可以工作了。仍然无法在 join_sources 上找到任何文档。
      • 很难找到 SelectManager 的文档,因为 Arel lib 已合并到 Rails 存储库。你可以参考这个github.com/rails/rails/blob/…查看它的方法。无论如何,如果您认为 join_sources 解决了您的问题,请给我 1 个赞。
      猜你喜欢
      • 1970-01-01
      • 2011-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-20
      • 2013-03-27
      • 1970-01-01
      相关资源
      最近更新 更多