철도 파괴에서 '검증'하는 방법
-
02-07-2019 - |
문제
편안한 자원을 파괴 할 때 파괴 작업이 계속되기 전에 몇 가지를 보장하고 싶습니다. 기본적으로, 데이터베이스가 무효 상태에있을 것이라고 주목하면 파괴 작업을 중지 할 수있는 능력을 원하십니까? 파괴 작업에는 검증 콜백이 없으므로 파괴 작업을 수락 해야하는지 여부를 어떻게 "검증"합니까?
해결책
당신은 당신이 잡는 예외를 제기 할 수 있습니다. Rails는 거래에 삭제를 마무리하여 문제를 돕습니다.
예를 들어:
class Booking < ActiveRecord::Base
has_many :booking_payments
....
def destroy
raise "Cannot delete booking with payments" unless booking_payments.count == 0
# ... ok, go ahead and destroy
super
end
end
또는 prever_destroy 콜백을 사용할 수 있습니다. 이 콜백은 일반적으로 종속 레코드를 파괴하는 데 사용되지만 예외를 던지거나 오류를 추가 할 수 있습니다.
def before_destroy
return true if booking_payments.count == 0
errors.add :base, "Cannot delete booking with payments"
# or errors.add_to_base in Rails 2
false
# Rails 5
throw(:abort)
end
myBooking.destroy
이제 false를 반환하고 myBooking.errors
반환시 채집됩니다.
다른 팁
그냥 메모 :
레일 3
class Booking < ActiveRecord::Base
before_destroy :booking_with_payments?
private
def booking_with_payments?
errors.add(:base, "Cannot delete booking with payments") unless booking_payments.count == 0
errors.blank? #return false, to not destroy the element, otherwise, it will delete.
end
내가 레일 5로 한 일입니다.
before_destroy do
cannot_delete_with_qrcodes
throw(:abort) if errors.present?
end
def cannot_delete_with_qrcodes
errors.add(:base, 'Cannot delete shop with qrcodes') if qrcodes.any?
end
ActivereCord Associations Has_many 및 Has_one은 관련 테이블 행이 삭제에서 삭제 될 수있는 종속 옵션을 허용하지만 일반적으로 데이터베이스가 유효하지 않도록 데이터베이스를 깨끗하게 유지하는 것입니다.
컨트롤러의 "if"문으로 파괴 동작을 래핑 할 수 있습니다.
def destroy # in controller context
if (model.valid_destroy?)
model.destroy # if in model context, use `super`
end
end
어디에 valid_destroy? 레코드 파괴 조건이 충족되면 TRUE를 반환하는 모델 클래스의 메소드입니다.
이와 같은 방법을 사용하면 사용자에게 삭제 옵션이 표시되는 것을 방지 할 수 있습니다. 이는 사용자가 불법 작업을 수행 할 수 없으므로 사용자 경험을 향상시킵니다.
여기에서 코드를 사용하여 ActiveRecord에서 CAN_DESTROY OVERMED를 작성했습니다.https://gist.github.com/andhapp/1761098
class ActiveRecord::Base
def can_destroy?
self.class.reflect_on_all_associations.all? do |assoc|
assoc.options[:dependent] != :restrict || (assoc.macro == :has_one && self.send(assoc.name).nil?) || (assoc.macro == :has_many && self.send(assoc.name).empty?)
end
end
end
이것은 UI에서 삭제 버튼을 숨기거나 표시하는 것이 사소한 이점이 있습니다.
이전 _destroy 콜백을 사용하여 예외를 제기 할 수도 있습니다.
이 수업이나 모델이 있습니다
class Enterprise < AR::Base
has_many :products
before_destroy :enterprise_with_products?
private
def empresas_with_portafolios?
self.portafolios.empty?
end
end
class Product < AR::Base
belongs_to :enterprises
end
이제 엔터프라이즈를 삭제할 때이 프로세스는 기업과 관련된 제품이 있는지 확인합니다. 참고 : 먼저 검증하려면 클래스 상단에 이것을 작성해야합니다.
레일 5에서 ActivereCord 컨텍스트 검증을 사용하십시오.
class ApplicationRecord < ActiveRecord::Base
before_destroy do
throw :abort if invalid?(:destroy)
end
end
class Ticket < ApplicationRecord
validate :validate_expires_on, on: :destroy
def validate_expires_on
errors.add :expires_on if expires_on > Time.now
end
end
나는 이것이 뒷받침되기를 바라고 있었기 때문에 그것을 추가하기 위해 레일 문제를 열었습니다.