4

I'm trying to substitute ActiveRecord validations with Dry-validations, but I've been unable to find any in-app implementation examples to follow.

Dry-validation docs: http://dry-rb.org/gems/dry-validation/

I've added below to the form object, but I don't understand how to actually implement it so the validation fails if title is not inputted in the UI's form.

schema = Dry::Validation.Schema do
  required(:title).filled
end

Form Object (setup with Virtus):

class PositionForm
  include Virtus.model
  include ActiveModel::Model
  require 'dry-validation'
  require 'dry/validation/schema/form'

  # ATTRIBUTES
  attribute :id, Integer
  attribute :title, String
  ...

  # OLD ACTIVE RECORD VALIDATIONS
  #validates :title, presence: true

  # NEW DRY VALIDATIONS
  schema = Dry::Validation.Schema do
    required(:title).filled
  end

  def save
    if valid?
      persist!
      true
    else
      false
    end
  end

  def persist!
    @position = Position.create!(title: title...)
  end
end

I've never used dry-validation before - any guidance would be super appreciated!


UPDATE

I've been able to "make it work" but it still doesn't feel like the correct design pattern.

Updated save method

def save
  schema = Dry::Validation.Schema do
    required(:title).filled
  end

  errors = schema.(title: title)

  if valid? && errors.messages.empty?
    persist!
    true
  else
    false
  end
end

If anyone could share guidance on the appropriate design pattern to implement dry-validation into a virtus-style form object it would be super appreciated!

tim_xyz
  • 11,573
  • 17
  • 52
  • 97

1 Answers1

4

I would try to keep validation at the model level.

Have a ModelValidations model in your initializers, each method named after the model it validates.

config/initialize/model_validations.rb

module ModelValidations
  def position_form
    Dry::Validation.Schema do
      required(:title).filled
    end
  end
end

In the model, call the dry_validation module for that model.

app/models/position_form.rb

class PositionForm
  validates :dry_validation

  def dry_validation
    ModelValidations.position_form(attributes).each do |field, message|
      errors.add(field, message)
    end
  end

end
SteveTurczyn
  • 36,057
  • 6
  • 41
  • 53
  • Is `/initializers` preferable to regular `/models`? – tim_xyz Sep 27 '16 at 17:46
  • We're using regular models, of course, but we need to define the module somewhere and initializers is one place to do it. The `class PositionForm` is in `/models` but happens to use a dry validation defined in initializers. I'll modify the answer to make clear that `PositionForm` is still in model directory. – SteveTurczyn Sep 27 '16 at 21:37