Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
PayRoll application, embedded in Rails, borrowing from Use Case Driven Architecture and DCI
## PayRoll gem
# lib/pay_roll.rb
module PayRoll
class << self
attr_accessor :employee_directory
def config
yield self
end
end
end
end
# lib/pay_roll/services/pay_day_service.rb
class PayRoll::PayDayService
def initialize(date=Date.now)
@date = date
@employees = PayRoll.employee_directory.active
@employees.each { |e| e.extend(Payable) }
end
def execute
@employees.each do |e|
if e.pay_date?(@date)
pc = PayCheck.new(e.calculate_pay(@date))
e.send_pay(pc)
end
end
end
end
# lib/pay_roll/roles/payable.rb
module PayRoll::Payable
def pay_date?(date)
# ...
end
def send_pay(pay_check)
# ...
end
end
## Rails application
# app/controllers/pay_day_controller.rb
# Yes, this would make more sense to be run in a scheduled job, but wanted to show
# an example of services used in a Rails controlle
class PayDayController < ApplicationController
def create
PayRoll::PayDayService.new.execute
redirect_to :back, :notice => "Pay day has been successfully completed"
end
end
# config/initializers/pay_roll.rb
PayRoll.config do |config|
employee_directory = Employee
end
# models/employee.rb
class Employee < ActiveRecord::Base
scope :active, where(:active => true)
end
@judofyr

This comment has been minimized.

Copy link

judofyr commented Oct 23, 2011

Dude…

Let's look at this line: options[:employees] ||= PayRoll.employee_directory.active and see how many levels there are to actually understand the code:

Level 1:

module PayRoll
  class << self
    attr_accessor :employee_directory
  end
end

Level 2:

PayRoll.config do |config|
  employee_directory = EmployeeDirectory.new # alternatively just use Employee model
end

Level 3:

class EmployeeDirectory
  def active
    Employee.active
  end
end

Level 4:

class Employee < ActiveRecord::Base
  scope :active, where(:active => true)
end

Four levels?! What have you really gained by all these levels?

@josegonzalez

This comment has been minimized.

Copy link

josegonzalez commented Oct 23, 2011

He's gained Indirection.

@judofyr

This comment has been minimized.

Copy link

judofyr commented Oct 23, 2011

I N D I R E C T I O N

@nicholasjhenry

This comment has been minimized.

Copy link
Owner Author

nicholasjhenry commented Oct 26, 2011

@judofyr Yes, your quite right. In this example, a database gateway class is unnecessary. In Martin's example from Agile Software Development it makes sense when creating Entity objects, but with my DCI interpretation, it does not.

@codesnik

This comment has been minimized.

Copy link

codesnik commented Oct 27, 2011

how do you PayRoll::PayDayService.new if it's a module?

@nicholasjhenry

This comment has been minimized.

Copy link
Owner Author

nicholasjhenry commented Oct 27, 2011

@codesnik good catch, thank you. Fixed.

@nicholasjhenry

This comment has been minimized.

Copy link
Owner Author

nicholasjhenry commented Apr 6, 2012

@mankind Not sure where you're comment went, but I'm a big fan of using engines to break up a complex rails application. Pivotal has a good blog post on this approach which I'm currently using:

http://pivotallabs.com/users/mbarinek/blog/articles/2022-unbuilt-rails-dependencies-how-to-design-for-loosely-coupled-highly-cohesive-components-within-a-rails-application

@elgalu

This comment has been minimized.

Copy link

elgalu commented Jul 12, 2013

👍

@shime

This comment has been minimized.

Copy link

shime commented Sep 2, 2013

🍻

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.