2015-10-21 2 views
1

ActiveRecord новичок здесь, разочарованный тем, что похоже на простой SQL-запрос не может легко превратиться в ActiveRecord (возможно, из-за моего отсутствия опыта).ActiveRecord простая максимальная дата от нуля до многих отношений

У меня есть следующий SQL, который работает:

select j.id, j.title, jac.latest from jobs j 
    left join (select job_id, max(created_at) latest from job_activity_logs group by job_id) jac 
    on j.id = jac.job_id 
where j.state = 0 

... что я хочу, чтобы включить в запрос ActiveRecord.

В моей модели Rails Я соотношение определяется:

class Job < ActiveRecord::Base 
    has_many :job_activity_logs 

и

class JobActivityLog < ActiveRecord::Base 
    belongs_to :job 

Другие решения используют ActiveRecord :: Base.connection.execute, что я не хочу использовать, потому что Мне нужно создать запрос на основе параметров querystring (уродливые строки concat и SQL-инъекции).

Как достичь такого же, как мой SQL в ActiveRecord?

+0

Пожалуйста, ознакомьтесь с этим вопросом http://stackoverflow.com/questions/8567175/correct-way-to-find-max-value-with-association-rails – tegon

+0

К сожалению, не @tegon, потому что мне нужны детали последняя запись в списке выбора –

+0

Итак, почему вы не можете выполнить 'Job.first.job_activity_logs', так как вы объявили об ассоциации? Это даст все журналы активности для этой работы. Затем, чтобы выбрать конкретный атрибут, вам нужно сделать что-то. Было бы необходимо создать запрос, если вы действительно не знаете, какой результат должен быть .. но я думаю, что это запрос, который вы ищете в AR. 'Job.select (: id,: title,: latest) .where (state: 0) .first.job_activity_logs.group_by (&: job_id)' – Vlad

ответ

2

Возможно, это будет не так красиво, как вы надеетесь, но, по крайней мере, вы можете получить от него безопасность от инъекций.

Прежде всего, давайте преобразуем ваш запрос в простой JOIN вместо подзапроса, который ActiveRecord не преуспевает.

SELECT j.id, j.title, max(jal.created_at) 
FROM jobs j 
LEFT JOIN job_activity_logs jal ON j.id = jal.job_id 
WHERE j.state = 0 
GROUP BY j.id, j.title; 

Теперь мы можем предоставить ActiveRecord каждую из этих частей.

Job 
    .joins('LEFT JOIN job_activity_logs ON jobs.id = job_activity_logs.job_id') 
    .group('jobs.id', 'jobs.title') 
    .where(state: 0) 
    .select('jobs.id', 'jobs.title', 'max(job_activity_logs.created_at) latest') 

Это должно помочь вам набор Job с с id, title и latest заполненными полями.

В зависимости от остальных ваших потребностей, вы можете проверить Arel, который ActiveRecord использует под капот. Это более выразительно за счет того, что Rails имеет упрощенные общие действия.

+0

уродливый, чем я надеялся, но красивее, чем я боялся :) Спасибо ... это хорошо работает –

+0

Я знаю чувство :-D –

Смежные вопросы