David Elner
David Elner

Reputation: 5201

Validating nested models with ActiveModel::Validations

My application uses plain Ruby classes with ActiveModel::Validations, without implementing ActiveRecord:

class Car
  include ::ActiveModel::Validations

  attr_accessor :engine
end

class Engine
  include ::ActiveModel::Validations

  attr_accessor :cylinders
  validates_presence_of :cylinders
end

I would like Car to check the nested attributes that are of ActiveModel::Validations, in this case engine.

car = Car.new
car.engine = Engine.new

car.engine.valid? # => false
car.valid?        # => true
                  # It should return 'false',
                  # because 'engine.cylinders' is 'nil'

What's the easiest way to get this behavior?

Upvotes: 7

Views: 2270

Answers (2)

Gorav Bhootra
Gorav Bhootra

Reputation: 29

I use Gem active_type in almost all my projects for similar requirements. Project statement - Make any Ruby object quack like ActiveRecord. Project github page provides good documentation as well.

in your Gemfile, add:
gem 'active_type'

Then,

class Car < ActiveType::Object  

    nests_one :engine
    validates :check_engine

    def check_engine
        return true if self.engine.valid?
        false
    end
end

class Engine < ActiveType::Object

    attribute :cylinders, :string
    validates :cylinders, presence: true
end

Now,

car = Car.new
car.engine = Engine.new

car.engine.valid? # => false
car.valid?        # => false

Upvotes: 0

Aguardientico
Aguardientico

Reputation: 7779

One option is creating your own validation method, something like

class Car
  include ::ActiveModel::Validations

  attr_accessor :engine

  validate :engine_must_be_valid

  def engine_must_be_valid
    errors.add(:base, "Engine is not valid") unless engine.valid?
  end
end

Upvotes: 3

Related Questions