Robert
Robert is an implementation of the builder pattern that first runs the given arguments through a validation process.
Installation
gem install robert
Usage
Robert is helpful in creating form objects (validating Rack params), implementing business logic (service objects, if you will) and much more. Basically if you do not trust the data, run it through Robert.
class Post
attr_accessor :title, :body
def initialize(attributes)
attributes.each do |key, value|
send(:"#{key}=", value)
end
end
end
class PostBuilder < Robert
attr_accessor :title, :body
private
def validate
error :title, :is_empty { empty? }
error :body, :is_empty { empty? }
end
end
builder = PostBuilder.new(title: 'Title', body: '')
result = builder.build(Post)
result # false
builder.errors # { body: [:is_empty] }
builder.body = 'body'
result = builder.build(Post)
result.is_a?(Post) # true
Check out the tests for more examples.
API
::build
- Convenience for ::new(params).build(klass)
::build!
- Convenience for ::new(params).build!(klass)
#attributes
- Hash of attributes that have been validated (successfully) and "cleaned".
#errors
- Hash of errors.
#build
- Initializes the given class if valid or returns false.
#build!
- Initializes the given class if valid or raises.
#clean
- Template method for cleaning values before assigning them the attributes hash.
#error
- Bread and butter of the library. For a given attribute, adds error if the given block returns false. The block is evaluated in context of the attribute itself.
#validate
- Template method for implementing your validation logic.
#valid?
- Checks to see if the builder is valid.
Gotchas
Sending #errors
before #valid?
will return the default errors
(an empty Hash by default), which will give the appearance of a valid object.
The reason for this is that if you have an html view and are rendering
a form/builder's errors, you don't want to #errors
to trigger validation
on the initial page load.
Prior Art
Robert is inspired by the following libraries: