我遇到父Order
有多个孩子Items
的情况。 Order
和Item
都有一个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有一种神奇的方式吗?
答案 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
此备用解决方案是否符合您的需求取决于您的数据库读取模式。