Calling validate :method_name
causes an infinite loop SystemStackError
.
Doing the validation directly inline allows the validation to pass without error.
There must be something I'm overlooking or doing wrong...
The validations worked fine when doing them directly in the model instead of within the conditional_reservation_validation
.
Example code that causes SystemStackError
stack level too deep
The basic process has been built following this example: Building Partial Objects Step by Step
I know this needs to be refactored / cleaned up.
Snippet from model:
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
Calling validate :parking_agreement_if_location triggers a SystemStackError
Example code that stops the error: Just taking the code out of the :parking_agreement_if_location method and putting it directly inline stops the 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
Controller update action:
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
You are using validations wrong way. They need to be invoked on class level.
You need to use conditional validations instead:
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?