【问题标题】:ActiveRecord find identical set in many_to_many modelsActiveRecord 在 many_to_many 模型中找到相同的集合
【发布时间】:2011-02-25 05:08:28
【问题描述】:

我的 Rails 3 代码中有一个反模式,我想知道如何正确地做到这一点。

假设客户订购了炸薯条和汉堡包。我想知道以前是否下过这样的订单。为简单起见,每个订单只能订购一次(所以没有“请两个汉堡包”),也没有重复订单。

型号:

Order (attributes: id)
  has_many :items_orders
  has_many :items, :through => :items_orders

Item (attributes: id, name) 
  has_many :items_orders
  has_many :orders,:through => :items_orders

ItemsOrder (attributes: id, item_id, order_id)
  belongs_to :order
  belongs_to :item 
  validates_uniqueness_of :item_id, :scope => :order_id

我现在的做法是获取至少包含一个订单项的所有订单。然后我遍历它们以找到匹配的顺序。不用说,它的扩展性不好,看起来也不漂亮。

order = [1, 2]

1 和 2 对应薯条和汉堡的 Item id。

candidates = Order.find(
  :all, 
  :include => :items_orders, 
  :conditions =>  ["items_orders.item_id in (?)", order])

previous_order = nil

candidates.each do |candidate|
  if candidate.items.collect{|i| i.id} == order
    previous_order = candidate
    break
  end 
end

我正在使用 MySQL 和 Postgress,因此我也愿意接受忽略大部分 ActiveRecord 的标准 SQL 解决方案。

【问题讨论】:

  • 能否列出OrderItem' and ItemOrder`的属性和关系?
  • @SjorsProvoost 我下面的回答有帮助吗?如果您有任何问题,请告诉我?
  • @PaulRussell 它肯定会比我现在拥有的要快得多,谢谢。我只是希望有一个不需要冗余的解决方案(或者至少一个让数据库来处理)。

标签: mysql ruby-on-rails activerecord anti-patterns


【解决方案1】:

假设您只想找到 相同 订单,我很想使用哈希来实现这一点。我无法测试我要写的代码,所以请在依赖它之前检查它!

类似这样的: - 使用迁移在您的订单模型中创建一个新属性order_hash。 - 添加一个 before_save 挂钩,使用例如更新此属性订单行的 MD5 哈希。 - 添加一种查找相似订单的方法,该方法使用哈希快速查找其他匹配的订单。

代码看起来有点像这样:

class Order < ActiveRecord
  def before_save
    self.order_hash = calculate_hash
  end

  def find_similar
    Order.where(:order_hash => self.calculate_hash)
  end

  def calculate_hash
    d = Digest::MD5.new()
    self.items.order(:id).each do |i|
      d << i.id
    end
    d.hexdigest
  end
end

此代码将允许您创建和订购,然后调用 order.find_similar 应返回附有相同商品的订单列表。即使您有商品数量等,您也可以应用完全相同的方法。唯一的限制是您必须始终寻找相同的订单,而不仅仅是模糊地相似。

如果代码充满错误,我们深表歉意 - 希望您能理解它!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-21
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多