2010-02-28 74 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