SimpleValue

A tiny Ruby gem for using value objects in your models. Create a plain Ruby class to represent the value object. Then easily use it in a model by extending SimpleValue::Model and using the value_object macro.

Installation

Add this line to your application's Gemfile:

gem 'simple_value'

And then execute:

$ bundle

Or install it yourself as:

$ gem install simple_value

Usage

Let's suppose that we have a User model with a phone attribute. Currently, User validates the format of the phone number, which is stored as a string in the database.

class User < ApplicationRecord
  before_validation :format_phone

  validate :phone_validation

  private

  def format_phone
    # logic for formatting the phone number
  end

  def phone_validation
    # complicated validation logic
  end
end

The rest of the application is already written to use a string when interacting with a User. We can still move the validation and whatever other logic related to the phone number into a separate class.

Moving the logic into its own class also prevents duplication in case another model needs to have a phone number. It can then simply use the same value object.

class Phone
  include ActiveModel::Validations

  attr_reader :value

  validate :validate_number

  def initialize(value)
    @value = format_number value
  end

  private

  def format_number(number)
    # logic for formatting the phone number
  end

  def validate_number
    # complicated validation logic
  end
end

We can use the same DSL for validations in any class just by including ActiveModel::Validations. This way it is possible to easily move the phone validation from the User model to the new Phone class.

Currently this gem works for value objects that take a single required argument in their initializer. The value object also needs an attr_reader for its value (value is the default name, but it can be sometihng else).

The only thing left to do is to make the User model use the new value object. It needs to extends SimpleValue::Model in order to get access to the value_object macro.

class User < ApplicationRecord
  extend SimpleValue::Model

  value_object :phone, Phone, validate: true
end

The first argument of value_object is a symbol with the name of the attribute used to initialize the value object. The second arument is the class used for the value object.

There are also two optional parameters for value_object. validate is set to false by default, if set to true, it will use whatever validations are in the value object and add the errors to the base of the model's errors.

The second optional parameter is the name of the attr_reader used to get the value from the value object. By default it is set to :value.

License

The gem is available as open source under the terms of the MIT License.