Как превратить SQL подзапроса к собственной таблице в Rails named_scope?

#ruby-on-rails #activerecord #subquery #named-scope

#ruby-on-rails #activerecord #подзапрос #named-scope

Вопрос:

Я использую rails 2.3.10 и новичок в named_scope . Я имею дело с SQL, который извлекает список последних приглашений на определенное событие. Я придумал SQL с подзапросом, и похоже, что он может делать то, что я хочу. Я думаю о том, можно ли использовать named_scope для выполнения того же самого, чтобы я мог использовать его с find() .

У меня есть следующие вопросы:

  1. Возможно ли реализовать SQL с named_scope ?
  2. Может ли это быть элегантным способом, чтобы подвыборка не включалась в :condition ? требуется более одного named_scope?
  3. Как named_scope (ы) выглядят?
  4. Как find() выглядит, когда он включает name_scope (ы)?

SQL:

 SELECT *
  FROM invitation inv1
  JOIN (
         SELECT event_id, user_id, MAX(invite_time) AS last_invite_time
           FROM invitation
          GROUP BY event_id, user_id
       ) AS last_invite ON
       inv1.event_id = last_invite.event_id AND
       inv1.user_id = last_invite.user_id AND
       inv1.invite_time = last_invite.last_invite_time
  

Данные приглашения:

 event_id     user_id     invite_time       invite_reply_code
1            78          2011-02-01 15:21  1
2            78          2011-02-02 11:45  1
2            79          2011-02-02 11:50  1
2            79          2011-02-02 11:55  1
2            80          2011-02-02 11:50  1
2            80          2011-02-02 11:51  1
  

Ожидаемый результат:

 event_id     user_id     invite_time       invite_reply_code
2            78          2011-02-02 11:45  1
2            79          2011-02-02 11:55  1
2            80          2011-02-02 11:51  1
  

Ответ №1:

:joins Опция в find может принимать строку, которую она просто вставит в SQL. Чтобы получить свой event_id там, вам нужно будет использовать лямбда, так что вам нужно что-то вроде этого:

 named_scope :foo, lambda { |event_id|
  { :select => "oinv.*",
    :from => "invitation AS oinv"
    :joins => <<-SQL
      JOIN (
             SELECT event_id, user_id, MAX(invite_time) AS last_invite_time
               FROM invitation AS jinv
              GROUP BY event_id, user_id
           ) AS last_invite ON
           oinv.event_id       = last_invite.event_id AND
           oinv.user_id        = last_invite.user_id AND
           oinv.invite_time    = last_invite.last_invite_time
      SQL
    , :conditions => [ "oinv.event_id = ?", event_id ]
  }
}
  

Это совершенно непроверено, но, надеюсь, вы видите, что я делаю, и это указывает вам правильный путь.