Arel :: SelectManager如何访问包括投影的结果

时间:2019-03-04 04:19:49

标签: ruby-on-rails arel

我正在尝试访问将两个表的列都指定为投影一部分的联接结果。

我有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结果产生有意义输出的方法。

感谢您的帮助。

2 个答案:

答案 0 :(得分:1)

我们应该找出一种触发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

答案 1 :(得分:0)

简化了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