繁体   English   中英

Ruby on 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示例代码

按照以下示例构建了基本过程: 逐步构建部分对象

我知道这需要重构/清理。

来自模型的摘录:

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

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

您需要使用条件验证:

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?

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM