2010-02-28 39 views
0

我不知道這是否是可行的,甚至最好合計有條件的has_many軌協會

但我想建立的has_many關係或條件named_scope類型的關係,以減輕我的痛苦變成一個簡單的關係,而不是二。

目前我有兩個模型,它們基本上包含相同的信息,屬於相同的模型房間,通過相同的密鑰room_id,但以兩種不同的方式保存數據。一個包含特定日期的特定信息以及一週中的第二個通用費率。主要障礙是Availables可能根本不包含任何特定記錄的信息,在這種情況下,它需要按給定日期的平均值而不是具體價格推遲至room_rates。

任何指針或建議?由於

可獲取

+--------+-------+-------+------------+---------+-----+ 
| 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

+0

只是爲了得到一個更好的理解,同時考慮這件事:如果沒有在可獲取的入口,那不是意味着沒有可供使用的?在其他情況下可能發生的情況是,Availables中沒有條目? 「某一特定記錄的信息」中的「記錄」是否意味着room_id的記錄? – ajmurmann 2010-02-28 17:09:47

+0

那麼有一個特定的房間價格可用的多個來源...它可能完全缺失,仍然可用。如果是淡季,消息來源沒有理由更新,並且回落到room_rates表上。如果房間真的不可用,則在大多數情況下,該房間將具有該特定日期的「景點」= 0的可用記錄。 – holden 2010-02-28 18:57:30

+0

這就是爲什麼我希望有一些has_many魔法或某種範圍來處理我的所有問題的源頭。就目前而言,我有很多邏輯在進行,這些邏輯太分散了。 – holden 2010-02-28 19:02:23

回答

1

存在我只想補充方法房間模型bookdates。我建議你想在特定的一天獲得價格。

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

你需要的東西,會給你一週中的某一天取代dayofweek(date)。這將返回priceavailbles,如果沒有這樣的行,那麼從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 

它會返回與價格散列結果,其中日是一個關鍵

+0

但是如果我想要獲得的不僅僅是一個單獨的日期,並且獲得一系列日期,其中一些來自可用空間,然後是由room_rates填充的空洞? – holden 2010-02-28 17:43:16

+0

@holden:我爲日期範圍添加了解決方案。 – klew 2010-02-28 18:10:59

+0

您也可以嘗試加載可用空間中的所有價格,然後將其映射到散列並填充來自room_rates的數據。 – klew 2010-02-28 18:12:23

4

您可以在一個SQL做到這一點。但它需要你執行一個相當大的SQL。另一方面,您可以通過排序和其他好處得到結果。

免責聲明1:此代碼是農場新鮮,空氣編碼,並沒有受到任何有害的測試。

免責聲明2:對於同一房間日期2010-02-25在availables表中有兩行。我認爲這是一個畸變。否則,您需要將其他參數傳遞給select語句以進一步過濾結果。現在

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 

讓檢查這是從availables表中缺少第26屆率。

rates.keys[3] # Tue, 26 Feb 2010 
rates.values[3] # 14.3999996185303 
+0

有趣的想法,但現在我想知道是否有可能做類似的事情,但與finder_sql方法。這樣我可以使用標準has_many ... – holden 2010-03-01 09:43:26