0

调用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
4

1 回答 1

0

您以错误的方式使用验证。它们需要在类级别上调用。

您需要改用条件验证:

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?
于 2018-04-15T06:05:58.977 回答