SimpleBuilder
Dead-simple base class to build create/update service objects from. I got tired of reinventing something like this is every ruby/rails/sinatra app I write, so here's a gem, cruel world :).
Installation
Add this line to your application's Gemfile:
gem 'simple_builder'
And then execute:
$ bundle
Or install it yourself as:
$ gem install simple_builder
Usage
It's quite simple. Your implementing class has to implement two methods:
#new_instance
#set_attributes
Hopefully, it is obvious what those two methods should do. #build!
and it's alias #update!
both call #save
on the instance to persist the changes, so you should implement or alias that as appropriate.
The initializer optionally takes a block (to which we yield self
) so you can do interesting things like support additional parameters or set stuff up for later.
Here are some examples, both from the world of Rails, though this does not depend on anything rails-y:
# The simplest possible builder
class ChapterBuilder < SimpleBuilder
def new_instance
Chapter.new
end
def set_attributes
self.object.attributes = {
name: params[:name]
}
end
end
c = ChapterBuilder.build({ name: 'foo' }) # => #<Chapter id: 9, name: "foo">
ChapterBuilder.update(c, { name: 'bar' }) # => #<Chapter id: 9, name: "bar">
# A more complex example, illustrating the point of the block *and* new_instance
# Assume rails and a normal, nested-resource style controller scheme
class EventBuilder < SimpleBuilder
attr_accessor :league
def new_instance
league.events.build
end
def set_attributes
self.object.attributes = {
name: params[:name],
date: params[:date],
category: params[:category]
}
end
end
event = EventBuilder.build(params[:event]) { |eb| eb.league = @league }
EventBuilder.update(event, params[:event])
Why do this?
I don't like the hassle of strong_parameters
, but I like object security. I like explicit constructors and updates in order to ensure I can write solid, comprehensive unit tests for any business logic around updating and creating business objects.
This approach lets me have strong tests, confidence that I am only accepting parameters I explicitly told it too, and lets me keep my controllers super-tidy.
It's a win-win-win.
Contributing
- Fork it ( http://github.com/
/simple_builder/fork ) - Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Add some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request