Dry-validation: extract method


#1

Hi there!

Is it possible to extract and reuse methods inside Form (Schema)?

DryRequestForm = Dry::Validation.Form do
  configure do
    option :time_zone, String

    def time_span(date, start_hour, end_hour, time_zone)
      TimeRange.new(
        date: date,
        start_hour: start_hour,
        end_hour: end_hour,
        time_zone: time_zone
      ).range
    end
  end

  #... other fields
  required(:user_id).filled
  required(:date).filled(:date?)
  required(:start).filled(:int?, included_in?: START_HOURS)
  required(:end).filled(:int?, included_in?: END_HOURS)

  validate(:range_is_valid: [:date, :start, :end, :time_zone]) do |date, start_hour, end_hour, tz|
    time = time_span(date, start_hour, end_hour, tz)

    (time.begin >= Time.current + 2.hours) && (time.end > time.begin)
  end

  validate(:user_is_available, [:date, :start, :end, :time_zone, :user_id]) do |date, start_hour, end_hour, tz, user_id|
    time = time_span(date, start_hour, end_hour, tz)

    User.find(user_id).available?(time)
  end
end

I’d like to extract this time range object. It’d be nice if I could just define a method which can access all needed fields.
Like so:

DryRequestForm = Dry::Validation.Form do
  configure do
    option :time_zone, String
  end

  # fields and validations

  validate(:user_is_available) { user.available?(time_span) }

  def user
    User.find(user_id)
  end

  def time_span
    TimeRange.new(
      date: date,
      start_hour: start_hour,
      end_hour: end_hour,
      time_zone: time_zone
    ).range
  end
end

Passing all params explicitly around is now way. (1-3 is ok, but no more)
Is it possible to write cleaner code for complex schemas?