调用validate :method_name
会导致无限循环SystemStackError
。
直接内联进行验证允许验证通过而不会出错。
一定有什么我忽略或做错了......
当直接在模型中而不是在conditional_reservation_validation
.
导致的示例代码SystemStackError
stack level too deep
基本过程已按照此示例构建: 逐步构建部分对象
我知道这需要重构/清理。
模型片段:
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
调用 validate :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