with_lock 是否锁定块内的所有内容?

does with_lock lock everything inside the block?

with_lock 是锁定块中的所有模型还是仅锁定模型本身?例如,下面是 with_lock 内的所有 item 模型都已锁定,还是仅 entry 模型已锁定?

class Entry < ApplicationRecord
  enum state: [:pending, :posted]
    
  has_many :items, dependent: :destroy
 
  def post!
    with_lock do
      return unless pending?
      items.each { |i| i.post! }
      self.posted!
    end
  end
end

with_lock 在单个实例上获得 row-level 悲观锁。 with_lock简单的将锁和事务语句合二为一,所以等价于:

Entity.transaction do
  entity_instance.lock!
end

您在模型内部调用 with_lock,所以您实际上是在执行 self.with_lock。也就是说,您正在获取 Entity 的当前实例的锁。个人 Item 记录不会被锁定,除非您也明确锁定它们。不过,对它们的更改确实包含在同一父事务中。