替代与ActiveRecord的联合

时间:2013-01-10 22:40:05

标签: sql activerecord

我想我想在Rails中建立联盟,但根据这篇文章rails union hack, how to pull two different queries together,Rails本身不支持联合。我想知道是否有更好的方法来解决这个问题。

我有物品表,每个物品都有很多价格,但我只想为每个物品加一个价格。

要确定商品的正确价格,我在价格模型中有两个额外的外键:category_id和discount_id。每个人都可以独立申报物品的价格。

实施例。 Item + Category = Price1 and Item + Discount = Price 2

如果discount_id与传递的ID匹配,我想要排除仅与项目+类别匹配的价格结果。我也试图不要放松延迟加载。

希望问题很清楚!如果不是,我会提前澄清一下,谢谢。

1 个答案:

答案 0 :(得分:1)

你的模型会开始看起来像这样:

class Price < ActiveRecord::Base
  belongs_to :item
  belongs_to :category
  belongs_to :discount

  scope :category, where("prices.category_id IS NOT NULL")
  scope :discount, where("prices.discount_id IS NOT NULL")
end

class Item < ActiveRecord::Base
  has_many :prices
end

class Category < ActiveRecord::Base
  has_many :prices
end

class Discount < ActiveRecord::Base
  has_many :prices
end

这样做的一种方法是向Price添加一个封装此逻辑的类方法:

class Price < ActiveRecord::Base
  def self.used
    discount_items_sql = self.discount.select("prices.item_id").to_sql
    where("prices.discount_id IS NOT NULL OR prices.item_id NOT IN (#{discount_items_sql})")
  end
end

这实际上与此查询相同:

SELECT * FROM prices
WHERE prices.discount_id IS NOT NULL -- the discount_id is present on this record,
  OR prices.item_id NOT IN (         -- or no discount_id is present for this item
      SELECT item_id FROM prices WHERE discount_id IS NOT NULL)

为简单起见,您可以在Item模型上添加这些辅助方法:

class Item < ActiveRecord::Base
  def category_price
    prices.category.first
  end

  def discount_price
    prices.discount.first
  end

  def used_price
    prices.used.first
  end
end

现在,您可以轻松获取单个商品的每个“类型”价格(对于不可用的价格,将为nil):

item.category_price
item.discount_price
item.used_price