Ruby Rails SystemStackError 堆栈级别太深验证 Wicked gem
Ruby on Rails SystemStackError stack level too deep validate Wicked gem
调用 validate :method_name
导致无限循环 SystemStackError
。
直接内联进行验证允许验证无错误地通过。
一定是我忽略了或做错了什么...
直接在模型中而不是在 conditional_reservation_validation
中进行验证时效果很好。
导致 SystemStackError
stack level too deep
的示例代码
已按照此示例构建基本流程:
Building Partial Objects Step by Step
我知道这需要重构/清理。
来自模型的代码段:
validate :conditional_reservation_validation
def conditional_reservation_validation
if created_by_admin?
validates_presence_of :vehicle_location
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers
else
if active_or_parking?
validates_presence_of :vehicle_location
# SystemStackError occurs when validate :parking_agreement_if_location fires
validate :parking_agreement_if_location
end
if active_or_pickup?
# additional validations
end
end
# ...
end
def parking_agreement_if_location
if vehicle_in_special_parking_location(vehicle_location)
if self.parking_agreement == true
# ok
else
self.errors.add :base, "Must read and understand parking instructions."
end
end
end
def vehicle_in_special_parking_location(vehicle_location)
parking_locations = Location.where(require_parking: true)
if parking_locations.include?(vehicle_location)
return true
else
return false
end
end
# methods to check the step in process
def active_or_parking?
status.include?('parking') || active?
end
调用验证:parking_agreement_if_location 触发 SystemStackError
停止错误的示例代码:
只需将代码从 :parking_agreement_if_location 方法中取出并直接内联即可停止 SystemStackError.
validate :conditional_reservation_validation
def conditional_reservation_validation
if created_by_admin?
validates_presence_of :vehicle_location
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers
else
if active_or_parking?
validates_presence_of :vehicle_location
if vehicle_location
locations = Location.where(require_parking: true)
if locations.include?(vehicle_location)
if parking_agreement == true
# ok
else
self.errors.add :base, "Must read and understand parking instructions."
end
# validate :parking_agreement_if_location
end
end
end
if active_or_pickup?
# These methods cause SystemStackError as well...
validate :pickup_date_in_range
validate :pickup_date_in_future
end
end
end
控制器更新动作:
def update
params[:reservation][:status] = step.to_s
params[:reservation][:status] = 'active' if step == steps.last
case step
when :parking
@reservation.assign_attributes(reservation_params)
when :pickup
@reservation.assign_attributes(reservation_params)
when :billing
@reservation.assign_attributes(reservation_params)
end
render_wizard @reservation
end
您使用验证的方式有误。它们需要在 class 级别调用。
您需要改用条件验证:
validates_presence_of :vehicle_location, if: :created_by_admin?
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers, if: :created_by_admin?
validates_presence_of :vehicle_location, unless: :created_by_admin?, if: :active_or_parking?
validate :parking_agreement_if_location, unless: :created_by_admin?, if: :active_or_parking?
调用 validate :method_name
导致无限循环 SystemStackError
。
直接内联进行验证允许验证无错误地通过。
一定是我忽略了或做错了什么...
直接在模型中而不是在 conditional_reservation_validation
中进行验证时效果很好。
导致 SystemStackError
stack level too deep
已按照此示例构建基本流程: Building Partial Objects Step by Step
我知道这需要重构/清理。
来自模型的代码段:
validate :conditional_reservation_validation
def conditional_reservation_validation
if created_by_admin?
validates_presence_of :vehicle_location
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers
else
if active_or_parking?
validates_presence_of :vehicle_location
# SystemStackError occurs when validate :parking_agreement_if_location fires
validate :parking_agreement_if_location
end
if active_or_pickup?
# additional validations
end
end
# ...
end
def parking_agreement_if_location
if vehicle_in_special_parking_location(vehicle_location)
if self.parking_agreement == true
# ok
else
self.errors.add :base, "Must read and understand parking instructions."
end
end
end
def vehicle_in_special_parking_location(vehicle_location)
parking_locations = Location.where(require_parking: true)
if parking_locations.include?(vehicle_location)
return true
else
return false
end
end
# methods to check the step in process
def active_or_parking?
status.include?('parking') || active?
end
调用验证:parking_agreement_if_location 触发 SystemStackError
停止错误的示例代码: 只需将代码从 :parking_agreement_if_location 方法中取出并直接内联即可停止 SystemStackError.
validate :conditional_reservation_validation
def conditional_reservation_validation
if created_by_admin?
validates_presence_of :vehicle_location
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers
else
if active_or_parking?
validates_presence_of :vehicle_location
if vehicle_location
locations = Location.where(require_parking: true)
if locations.include?(vehicle_location)
if parking_agreement == true
# ok
else
self.errors.add :base, "Must read and understand parking instructions."
end
# validate :parking_agreement_if_location
end
end
end
if active_or_pickup?
# These methods cause SystemStackError as well...
validate :pickup_date_in_range
validate :pickup_date_in_future
end
end
end
控制器更新动作:
def update
params[:reservation][:status] = step.to_s
params[:reservation][:status] = 'active' if step == steps.last
case step
when :parking
@reservation.assign_attributes(reservation_params)
when :pickup
@reservation.assign_attributes(reservation_params)
when :billing
@reservation.assign_attributes(reservation_params)
end
render_wizard @reservation
end
您使用验证的方式有误。它们需要在 class 级别调用。
您需要改用条件验证:
validates_presence_of :vehicle_location, if: :created_by_admin?
validates_presence_of :pickup, :dropoff, :departure_date, :departure_time, :passengers, if: :created_by_admin?
validates_presence_of :vehicle_location, unless: :created_by_admin?, if: :active_or_parking?
validate :parking_agreement_if_location, unless: :created_by_admin?, if: :active_or_parking?