В: выбор всех постов и связанных комментариев в одном запросе, загрузка комментариев в p.comments, но выбор только заголовка из комментариев
Пост
#db
create_table :posts do |t|
t.string :title
t.text :text
t.timestamps
end
#modlel
class Post < ActiveRecord::Base
has_many :comments
end
Комментарий
#db
create_table :comments do |t|
t.string :title
t.text :text
t.integer :post_id
t.timestamps
end
#model
class Comment < ActiveRecord::Base
belongs_to :post
end
Что мне нужно: выделите все посты и связанные комментарии в одном запросе и загрузите отношение комментариев в p.comments, но выберите только заголовок из комментариев:
posts = Post.includes(:comments).select("posts.*, comments.title")
posts.each do |p|
puts(p.title)
puts(p.text)
p.comments.each do |c|
puts(c.title)
end
end
Если первая часть выполнена.включает в себя:
posts = Post.includes(:comments).select('posts.*, comments.title')
posts.first.comments.loaded? # true
=> SELECT posts
. id
AS t0_r0, posts
. title
AS t0_r1, posts
. text
AS t0_r2, posts
. created_at
AS t0_r3, posts
. updated_at
AS t0_r4, comments
. id
AS t1_r0, comments
. title
AS t1_r1, comments
. text
AS t1_r2, comments
. post_id
AS t1_r3, comments
. created_at
AS t1_r4, comments
. updated_at
AS t1_r5 ОТ posts
ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ comments
ВКЛ comments
. post_id
= posts
. id
полностью игнорирует выбор.
Хорошо, давайте попробуем присоединиться:
Post.joins(:comments).select('posts.*, comments.title')
=> ВЫБРАТЬ сообщения. *, Comments.title ОТ posts
ВНУТРЕННЕЕ СОЕДИНЕНИЕ comments
ON comments
. post_id
= posts
. id
лучше, но нам нужен псевдоним таблицы -- Rails не обрабатывает отношения (почему?)
posts = Post.joins(:comments).select('posts.*, comments.title as comments_title').first
=> ВЫБРАТЬ сообщения. *, Comments.title как comments_title ОТ posts
INNER JOIN comments
ON comments
. post_id
=posts
. id
posts.first.comments.loaded? # false
posts.first.comments_title # "Comment 1.1"
Хорошо, давайте попробуем ARel
p = Post.arel_table
c = Comment.arel_table
posts = Post.find_by_sql(
p.join(c).on(c[:post_id].eq(p[:id])) \
.project(p[:id],p[:title],c[:id],c[:title]).to_sql
)
=> SELECT posts
. id
, posts
. title
, comments
. id
, comments
. title
ОТ posts
ВНУТРЕННЕЕ СОЕДИНЕНИЕ comments
ВКЛ comments
. post_id
= posts
. id
та же история - ActiveRecordне обрабатывает отношения.
есть предложения?
UPD
если этот вопрос не имеет прямого решения, может бытьЕсть способ использовать некоторые методы AR для преобразования результирующего запроса.Потому что AR использует ARel, затем вызывает для него find_by_sql, а затем совершает магию, которую я не могу найти, когда и когда она была выполнена, и альт: генерируемые псевдонимы и ассоциации загрузки.
Может быть, естьтакое решение для отношений один-к-одному?
posts = Post.select ('posts.id, posts.title, comments.id, comments.title'). includes (: comment) posts.first.comment.loaded?# true
=> SELECT posts
. id
AS t0_r0, posts
. title
AS t0_r1, posts
. text
AS t0_r2, posts
. created_at
AS t0_r3, posts
. updated_at
AS t0_r4, comments
. id
AS t1_r0, comments
. title
AS t1_r1, comments
. text
AS t1_r2, comments
. post_id
AS t1_r3, comments
. created_at
AS t1_r4, comments
. updated_at
AS t1_r5 ОТ posts
ВЛЕВО НАРУЖНОЕ СОЕДИНЕНИЕ comments
ВКЛ. comments
. post_id
= posts
. id