2

I would like to write a custom validator for a given validates call:

class Worker
  include ActiveModel::Validations  

  def initialize(graph_object)
    @graph_object = graph_object
  end

  attr_accessor :graph_object

  validates :graph_object, graph_object_type: {inclusion: [:ready, :active]}
end

class GraphObject
  attr_accessor :state     
end

I would like to validate Worker#graph_object based on a GraphObject#state. So the Worker is valid when the passed in GrapObject is in a :ready or :active state. I would like to reuse as much of the ActiveModel as possible.

Validations documentation describes the process of setting up the custom validator but I can't figure out how to do it.

I think I have to start with this:

class GraphObjectTypeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
  end
end 
  • options[:inclusion] = [:ready, :active]
  • record is the instance of the Worker(i think...)
  • value I have no idea (is value = record.graph_object ?)
  • attribute same as for value - no idea

Maybe validates :graph_object, graph_object_type: {inclusion: [:ready, :active]} isn't defined right?

Kocur4d
  • 6,701
  • 8
  • 35
  • 53

1 Answers1

2

OK I think I figured it out - I love puts debugging! Who needs pry!

One way of doing it would be:

class GraphObjectTypeValidator < ActiveModel::EachValidator
  def validate_each(record, attribute, value)
    if options.key?(:inclusion) && not_included?(value.type)
      record.errors.add(attribute, "wrong graph object type")
    end
  end

private

  def not_included?(type)
    !options[:inclusion].include?(type)
  end
end
  • options[:inclusion]: [:ready, :active] array
  • record: instance of the Worker
  • value: instance of the GraphObject
  • attribute: :graph_object symbol
Kocur4d
  • 6,701
  • 8
  • 35
  • 53