Skip to content

Instantly share code, notes, and snippets.

@tylerdavis
Created December 31, 2014 21:50
Show Gist options
  • Save tylerdavis/61a5ab9851b1154fc6d5 to your computer and use it in GitHub Desktop.
Save tylerdavis/61a5ab9851b1154fc6d5 to your computer and use it in GitHub Desktop.
Service objects
class ServiceBase
attr_reader :model, :errors
class AbstractMethodError < Exception
end
def initialize(model)
@model = model
@errors = []
end
%w(create update destroy).each do |name|
define_method name do
raise AbstractMethodError, I18n.t('exceptions.abstract')
end
end
private
# The presence of errors decide whether we will update a model or not.
# If the final update fails, the service's errors are updated via our model and we return false.
def update_model(params)
false if @errors.any?
if @model.update(params)
true
else
@errors += @model.errors.full_messages
false
end
end
end
class UserService < ServiceBase
def update(params)
if params[:password].present?
update_password(params[:current_password], params[:password], params[:password_confirmation])
else
update_model(params)
end
end
def update_password(current_password, password, confirmation)
@errors << I18n.t('services.user.errors.password.update') if @model.nil? || current_password.nil? || password.nil? || confirmation.nil?
@errors << I18n.t('services.user.errors.password.match') if password != confirmation
@errors << I18n.t('services.user.errors.password.current') unless @model.try(:authenticate, current_password)
update_model({ password: password, password_confirmation: confirmation })
end
end
class UsersController < ApplicationController
def update
respond_to do |format|
@service = UserService.new(current_user)
if @service.update(user_params)
format.html { redirect_to my_path, notice: I18n.t('services.user.update') }
format.json { render json: @service.model.to_json, status: :ok }
else
format.html { redirect_to my_path, notice: @service.errors }
format.json { render json: { errors: @service.errors }, status: :unprocessable_entity }
end
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment