PlainService
Installation
Add this line to your application's Gemfile:
gem 'plain_service'
And then execute:
$ bundle
Or install it yourself as:
$ gem install plain_service
Why?
To keep your controller and model thin.
Usage
Example (simple password change service):
- Define your service:
# app/services/user_service/change_password
module UserService
class ChangePassword < PlainService::Base
attribute :user
attribute :password
attribute :password_confirmation
validates :password, presence: true, confirmation: true
def process
user.password = password
user.save
end
end
end
- Use it in your controller:
def change_password
change_password = UserService::ChangePassword.new(params)
change_password.user = current_user
# you can also call UserService::ChangePassword.perform(params) as shortcut
if change_password.perform
render #good response
else
render #bad response, see change_password.errors to get standard rails Errors object
end
end
Advantages of such approach:
- Simple and readable controller code. All action-related logic will be in service object.
- Validations that are related with specific action also hidden in service to keep model clean and easy to use.
- Easy to test. No callback hell, just plain ruby object.
Passing errors from model to service
Sometimes you want to have some specific model errors in service object. For example you are saving model with uniqueness validation on some field. Then you can do the following:
def process
if user.save
true
else
pass_errors_from user
false
end
end
# usage
service.perform
service.errors # => will include all errors from user object
Contributing
- Fork it
- 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