Build Robust & Production Quality Applications - Lesson 8: Beyond MVC - Service Objects
13 Jul 2015Service Objects
Just like we can extract domain logic into domain objects, we can extract business level logic into service objects. Currently, the below process is modeling the Credit Deduction Business Process. Let's extract that into a Service Object called CreditDeduction.
#apps/controllers/todos_controller.rb
def create
@todo = Todo.new(params[:todo)]
credit = Credit.new(current_user)
if @todo.save_with_tags
if UserLevelPoicy.new(ccurent_user).premium?
credit = credit - 1
else
credit = credit - 2
end
credit.save
if credit.depleted? < 0
AppMailer.notify.insufficient_funds
elsif credit.low_balance?
AppMailer.notify_low_balance
end
redirect_to root_path
else
render :new
endCreate the Service Policy called CreditDeduction
#app/services/credit_deduction.rb
Class CreditDeduction
endExtract business process related Code
#app/services/credit_deduction.rb
Class CreditDeduction
attr_accessor :user
def initialize(user)
@user = user
end
def deduct_credit
if UserLevelPoicy.new(ccurent_user).premium?
credit = credit - 1
else
credit = credit - 2
end
credit.save
if credit.depleted? < 0
AppMailer.notify.insufficient_funds
elsif credit.low_balance?
AppMailer.notify_low_balance
end
end
endUpdate the TodoController
#apps/controllers/todos_controller
def create
@todo = Todo.new(params[:todo)]
credit = Credit.new(current_user)
if @todo.save_with_tags
CreditDeduction.new(credit, current_user).deduct_credit
redirect_to root_path
else
render :new
end
end
endMove instatiating a new Credit Object to your Service Policy
#app/services/credit_deduction.rb
Class CreditDeduction
attr_accessor :credit, :user
def initialize(credit, user)
@credit = Credit.new(user)
@user = user
end
def deduct_credit
if UserLevelPoicy.new(ccurent_user).premium?
credit = credit - 1
else
credit = credit - 2
end
credit.save
if credit.depleted? < 0
AppMailer.notify.insufficient_funds
elsif credit.low_balance?
AppMailer.notify_low_balance
end
end
end#apps/controllers/todos_controller
def create
@todo = Todo.new(params[:todo)]
if @todo.save_with_tags
CreditDeduction.new(current_user).deduct_credit
redirect_to root_path
else
render :new
end
end
end