如何根据子属性设置父属性

时间:2017-07-10 02:16:36

标签: ruby-on-rails callback

我遇到父Order有多个孩子Items的情况。 OrderItem都有一个status_id列。我希望用户更新status_id的{​​{1}},然后当所有Item都有Items时,status_id应该是自动的设置(基于Order's status_id是什么值)。

我目前拥有的代码是:

Item status_ids

这是非常臭的代码,因为它违反了SRP,使用了回调,并且效率非常低,考虑到这意味着class Item after_save :set_order_status_id def set_order_status_id if self.order.items.where(status_id:nil).blank? self.order.update_attributes(status_id:X) end end end 有5 Order且所有5 Items正在更新,在EACH Items更新后,调用Item方法,并运行数据库查询。

所以...有没有更好的方法来写这个以避免这些问题?特别是我有兴趣通过不断检查父set_order_status_id其他子Order's状态来消除效率低下的问题......因为如果一次更新全部5 Items',它就会#&# 39;在每次更新之后检查它应该等到第5次更新时傻傻的.... Rails有一种神奇的方式吗?

2 个答案:

答案 0 :(得分:0)

答案是否定的,使用框架没有神奇的方法可以做到这一点。您最好的选择是使用自定义解决方案,并在您的商品更新后运行支票。类似的东西:

 ...your code...
 order.items.update_all(whatever) <-- update items
 update_status(order) <-- update order status
 ...

 def update_status(order)       
   return if order.items.where(status_id: nil).exist? <-- more efficient
   update_attributes(status_id: X) 
 end

为简单起见,该方法也可以在Offer模型中。

答案 1 :(得分:0)

如果订单状态可以在任何时间点从项目状态派生,那么最好避免完全在数据库中设置它。您可以创建一个访问者来按需查询它:

class Order < ActiveRecord::Base
  def status
    # memoize the calculation, including nils
    return @status if defined? @status

    item_statuses = items.pluck(:status).uniq
    # your logic here:
    # 1. check for any nils
    # 2. check for any 'pending', etc.
    @status = 'pending'
  end
end

此备用解决方案是否符合您的需求取决于您的数据库读取模式。