【发布时间】:2021-04-09 06:14:30
【问题描述】:
我经常听说.reload 在测试 Rails 应用程序中很常见,但在实际应用程序代码中呢?
下面的代码有效,但我一直在想,在这里使用.reload 是否有点粗糙。特别是因为我正在做的那种操作(通过辅助方法 add_passenger 添加到 has_many 关系,调用 rotate!)看起来很典型。
.reload 的用法可以吗?或者有没有更好的方法来构建我的代码?
def organize
Driver.find_each(&:clear_space)
untaken = Rider.unassigned
open_drivers = Driver.available
# assume enough seats for all riders
while untaken.reload.size > 0
cur = untaken.first
open_drivers.reload.each do |driver|
if cur.prefers_strongest?(driver: driver)
driver.add_passenger(rider: cur)
end
end
untaken.rotate! if cur.car.nil?
end
Car.all
end
class Driver < Person
has_one :car, inverse_of: :driver, dependent: :destroy
delegate :riders, :riders_count, :clear_space, to: :car
after_create :create_car!
scope :available, -> { joins(:car).where('riders_count < ?', :total_space) }
def clear_space
riders.delete_all if riders_count > 0
end
def add_passenger(rider:)
riders << rider if car.has_space?
end
def remove_passenger(rider:)
riders.delete(rider) if riders.exists?(rider.id)
end
end
【问题讨论】:
-
reload将使用接收到的值进行数据库查询和更新对象。可能的竞争条件可以在不“重新加载”的情况下解决,但这不是一个完美的解决方案。 -
在这里使用
reload似乎有点笨拙。我想如果你真的想每次都重新运行查询也没关系(尽管我什至没有意识到你可以使用reload重新运行集合上的查询,所以它可能不是最容易理解的?) .但是,如果您的untaken列表永远不会变大,最好将其视为普通列表,并使用 Enumerable / Array 方法根据需要删除元素,而不是重新运行查询 -
是的@maxpleaner 我同意。如果我确实通过
.to_a将untaken和open_driver范围调用(它返回我相信的关系?)转换为数组,我会失去双向能力虽然正确吗?然后我必须手动添加另一行来表示从untaken骑手数组中删除,一旦其中一个骑手被添加到司机?
标签: ruby-on-rails ruby activerecord model