совокупная условная ассоциация has_many rails - PullRequest
0 голосов
/ 28 февраля 2010

Я не уверен, возможно ли это или даже предпочтительнее

Но я бы хотел построить отношение has_many или условное отношение типа named_scope, чтобы облегчить мою боль в одном простом отношении вместо двух.

В настоящее время у меня есть две модели, которые в основном содержат одну и ту же информацию и принадлежат к одним и тем же комнатам моделей через один и тот же ключ room_id, но хранят данные двумя различными способами. Один содержит конкретную информацию на конкретную дату, а второй общий ставки для дней недели. Основное препятствие заключается в том, что доступные данные могут вообще не содержать информации для конкретной записи, и в этом случае ей необходимо отложить для room_rates средние значения, а не конкретные цены на данную дату.

Какие-нибудь указатели или предложения? Спасибо

1009 * Доступные * +--------+-------+-------+------------+---------+-----+ | id | price | spots | bookdate | room_id | min | +--------+-------+-------+------------+---------+-----+ | 180315 | 14.4 | 1 | 2010-02-27 | 2517 | 1 | | 231726 | 15.84 | 1 | 2010-03-24 | 2517 | 1 | | 180311 | 14.4 | 1 | 2010-02-23 | 2517 | 1 | | 180313 | 14.4 | 1 | 2010-02-25 | 2517 | 1 | +--------+-------+-------+------------+---------+-----+ Room_rates

+-------+---------+-----------+-------+-----+
| id    | room_id | dayofweek | price | min |
+-------+---------+-----------+-------+-----+
| 87936 | 2517    | 0         | 14.58 | 1   |
| 87937 | 2517    | 1         | 14.58 | 1   |
| 87938 | 2517    | 2         | 14.52 | 1   |
| 87939 | 2517    | 3         | 14.52 | 1   |
| 87940 | 2517    | 4         | 14.52 | 1   |
| 87941 | 2517    | 5         | 14.4  | 1   |
| 87942 | 2517    | 6         | 14.63 | 1   |
+-------+---------+-----------+-------+-----+

Или, возможно, метод finder_sql? Такие как:

  has_many :aggregates,
           :class_name => 'Available',
           :finder_sql => 'SELECT room_id, price, spots, bookdate, MIN(source) 
           FROM availables
           WHERE room_id = #{id}
           GROUP BY room_id, price, spots, bookdate'

Но также необходимо заполнить пропущенные записи для несуществующих закладок, присоединившись к room_rates

Ответы [ 2 ]

4 голосов
/ 28 февраля 2010

Вы можете сделать это в одном sql. Но это требует от вас выполнения довольно большого SQL. С другой стороны, вы получите результаты в одном утверждении с сортировкой и другими вкусностями.

Отказ от ответственности 1: Этот код имеет свежую ферму, кодируется воздухом и не подвергается никаким вредным испытаниям.

Отказ от ответственности 2: У вас есть 2 строки для одной комнаты на дату 2010-02-25 в таблице availables. Я предполагаю, что это аберрация. В противном случае вам нужно передать дополнительный параметр в оператор выбора для дальнейшей фильтрации результатов.

class Available < ActiveRecord::Base  
  def self.daily_rates room_id, from_date, to_date 
    date_table = (from_date..to_date).collect do |date| 
      "(SELECT  #{room_id} AS room_id, '#{date.to_formatted_s(:db)}' AS bookdate )"
    end.join(" UNION ")

    ActiveSupport::OrderedHash.new.tap do |hash|
      Available.find_by_sql( " 
         SELECT A.bookdate, IFNULL(B.price, C.price) AS price
         FROM   (#{date_table}) A
         LEFT OUTER JOIN availables B 
                ON A.room_id = B.room_id AND A.bookdate = B.bookdate
         JOIN room_rates C 
                ON A.room_id = C.room_id AND DAYOFWEEK(A.bookdate) = C.dayofweek + 1
         ORDER BY A.bookdate ASC"
      ).each do |rate_info |
        hash[rate_info.bookdate] = rate_info.price
      end
    end
  end  

end

Теперь вы можете совершать звонки, такие как:

rates = Available.daily_rates(1, '2010-02-23'.to_date, '2010-02-27'.to_date)

rates.keys[0]   # Tue, 23 Feb 2010
rates.values[0] # 14.3999996185303

Позволяет проверить ставку для 26-го числа, которая отсутствует в таблице availables.

rates.keys[3]   # Tue, 26 Feb 2010
rates.values[3] # 14.3999996185303
1 голос
/ 28 февраля 2010

Я бы просто добавил метод к модели комнаты. Я полагаю, вы хотите получить цену за определенный день.

def get_price(date)
  (self.availbles.find_by_bookdate(date) || self.room_rates.find_by_dayofweek(dayofweek(date)) ).price
end

Вам нужно заменить dayofweek(date) на что-то, что даст вам определенный день недели. Это вернет price из availbles, а если такой строки нет, то из room_rates. Если обе строки отсутствуют, у вас будет ошибка. Я надеюсь, что это даст вам некоторое представление о том, как решить эту проблему.

В случае диапазона дат я бы добавил другой метод:

def get_prices(start_date, end_date)
  dates = (start_date..end_date).to_a
  prices = {}
  dates.each do |d|
    prices[:d] = get_price(d)
  end
  prices
end

Возвращает хеш с ценами, где дата является ключевым

...