在销毁相机之前,我需要验证是否有任何CameraVectors与任何MonitoredPlace相关联。
相机的型号
class Camera < ApplicationRecord
belongs_to :location
has_many :camera_vectors, inverse_of: :camera, dependent: :destroy
validates :description, :device_serial, :device_name,
:device_type, :device_api_url, :device_user, :device_password,
presence: true
accepts_nested_attributes_for :camera_vectors, allow_destroy: true
end
CameraVector的模型
class CameraVector < ApplicationRecord
belongs_to :camera, inverse_of: :camera_vectors
belongs_to :monitored_place, optional: true
validates :description, presence: true
validates :position, numericality: { greater_than_or_equal_to: 0 }, presence: true
before_destroy :has_monitored_place?
private
def has_monitored_place?
if monitored_place.present?
errors.add(:base, "cannot delete")
throw :abort
end
end
end
MonitoredPlace的模型
class MonitoredPlace < ApplicationRecord
belongs_to :location
belongs_to :place_type
has_many :camera_vectors
validates :place_name, presence: true
validates :place_type_id, uniqueness: { scope: :location_id }, presence: true
scope :enabled, -> { where.not(enabled_on: nil).where(disabled_on: nil) }
end
因为每当我尝试更新或销毁摄像机时的accepts_nested_attributes_for,这个嵌套字段都会被发送为params
"camera_vectors_attributes"=>{"0"=>{"description"=>"A", "position"=>"1", "_destroy"=>"1", "id"=>"47"}}
我想如果我在模型CameraVector中写了一个回调before_destroy我可以验证它,但如果验证发生,它会在控制器中引发ActiveRecord :: RecordNotDestroyed。
if @camera.destroy(camera_params)
redirect_to(action: :index, notice: t(".success"))
else
render :index
end
你可以在api documentation阅读
ActiveRecord::RecordNotDestroyed
由ActiveRecord :: Base#destroy引发!当对#destroy的调用返回false时。
这是结果
before_destroy :has_monitored_place?
调用方法并返回false
。
def has_monitored_place?
if monitored_place.present?
errors.add(:base, "cannot delete")
throw :abort
end
end
要改变这种行为,请实现类似于api中描述的逻辑
begin
complex_operation_that_internally_calls_destroy!
rescue ActiveRecord::RecordNotDestroyed => invalid
puts invalid.record.errors
end
或阅读