Как заставить сложную именованную область видимости хорошо играть с ассоциациями и другими именованными областями действия [rails] - PullRequest
1 голос
/ 07 февраля 2010

У меня есть следующая именованная область на

  class RentableItem < ActiveRecord::Base
  named_scope :available_at, lambda{ |starts_at, ends_at| { 
      :select => "t.*",
      :from => "(SELECT ri.*, COALESCE(c1.start_date, '#{starts_at}') AS EarliestAvailable,
                              COALESCE(c2.end_date, '#{ends_at}') AS LatestAvailable
                FROM rentable_items ri
                LEFT OUTER JOIN contracts c1 ON (ri.id = c1.rentable_item_id AND c1.start_date BETWEEN '#{starts_at}' AND '#{ends_at}')
                LEFT OUTER JOIN contracts c2 ON (ri.id = c2.rentable_item_id AND c2.end_date BETWEEN '#{starts_at}'
                AND '#{ends_at}' AND c2.start_date >= c1.end_date))
                AS t",
      :joins =>"LEFT OUTER JOIN contracts x ON (t.id = x.rentable_item_id AND x.start_date < t.LatestAvailable
                AND x.end_date > t.EarliestAvailable)",
      :conditions => "x.id IS NULL AND DATEDIFF(t.LatestAvailable, t.EarliestAvailable) >= #{(starts_at.to_date..ends_at.to_date).to_a.size - 1}"
      }}
end

Одиночный вызов этого named_scope работает как чудо, но когда я пытаюсь объединить несколько именованных областей вместе или получить доступ к named_scope через область ассоциации, он взрывается. Я думаю, что оператором select и предложением from является проблема. Может быть, у кого-то есть идея, как переписать этот named_scope, чтобы разрешить ассоциации цепочек и областей видимости?

редактирование:

благодаря Shtéf он работает почти все.

  named_scope :available_at, lambda{ |starts_at, ends_at| { 
      :select => "rentable_items.*",
      :from => "(SELECT ri.*, COALESCE(c1.start_date, '#{starts_at}') AS EarliestAvailable,
                              COALESCE(c2.end_date, '#{ends_at}') AS LatestAvailable
                FROM rentable_items ri
                LEFT OUTER JOIN contracts c1 ON (ri.id = c1.rentable_item_id AND c1.start_date BETWEEN '#{starts_at}' AND '#{ends_at}')
                LEFT OUTER JOIN contracts c2 ON (ri.id = c2.rentable_item_id AND c2.end_date BETWEEN '#{starts_at}'
 AND '#{ends_at}' AND c2.start_date >= c1.end_date))
 AS rentable_items",
      :joins =>"LEFT OUTER JOIN contracts x ON (rentable_items.id = x.rentable_item_id AND x.start_date < rentable_items.LatestAvailable
AND x.end_date > rentable_items.EarliestAvailable)",
      :conditions => "x.id IS NULL AND DATEDIFF(rentable_items.LatestAvailable, rentable_items.EarliestAvailable) >= #{(starts_at.to_date..ends_at.to_date).to_a.size - 1}"
      }}

Теперь я могу связать области видимости и получить к ней доступ через ассоциации.

Есть, может быть, только косметическая, небольшая проблема с удвоенным условием, которое генерирует рельсы (в начале и в конце:

WHERE (`rentable_items`.container_item_id = 1) AND (((size > 10) AND (x.id IS NULL AND DATEDIFF(rentable_items.LatestAvailable, rentable_items.EarliestAvailable) >= 28)) AND (`rentable_items`.container_item_id = 1)) 

1 Ответ

0 голосов
/ 07 февраля 2010

Вы должны проверить файлы журналов для вашего приложения и посмотреть, какие предположения делает Rails и которые вызывают сгенерированный запрос. Если вы не можете это исправить, покажите нам пример ассоциации, через которую вы пытаетесь получить доступ, и запрос Rails генерирует из файла журнала.

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

...