-
Notifications
You must be signed in to change notification settings - Fork 2
Responsibility objects
cavalle edited this page Jan 7, 2013
·
2 revisions
http://jamesgolick.com/2010/3/14/crazy-heretical-and-awesome-the-way-i-write-rails-apps.html
class UserCreationService
def initialize(user_klass = User, log_klass = Log)
@user_klass = user_klass
@log_klass = log_klass
end
def create(params)
@user_klass.create(params).tap do |u|
@log_klass.new_user(u)
end
end
enddescribe UserCreationService do
before do
@user = stub("User")
@user_klass = stub("Class:User", :create => @user)
@log_klass = stub("Class:Log", :new_user => nil)
@service = UserCreationService.new(@user_klass, @log_klass)
@params = {:name => "Matz", :hobby => "Being Nice"}
@service.create(@params)
end
it "creates the user with the supplied parameters" do
@user_klass.should have_received(:create).with(@params)
end
it "logs the creation of the user" do
@log_klass.should have_received(:new_user).with(@user)
end
endclass User < ActiveRecord::Base
after_create :log_creation
protected
def log_creation
Log.new_user(self)
end
endhttp://www.naildrivin5.com/blog/2012/06/10/single-responsibility-principle-and-rails.html
class ApplicationUserCreator
def initialize(welcome_mailer=nil)
@welcome_mailer = welcome_mailer
end
def create_new_user(params)
User.create(params).tap { |new_user|
if new_user.valid?
self.welcome_mailer.deliver_welcome_email(new_user)
end
}
end
private
def welcome_mailer
@welcome_mailer ||= UserMailer
end
endclass AdminUsersController < ApplicationController
def create
@user = ApplicationUserCreator.new(AdminUserMailer).create_new_user(params[:user])
end
endclass UsersController < ApplicationController
def create
@user = User.new(params[:user])
respond_to do |format|
if @user.save
UserMailer.deliver_welcome_email(@user)
end
end
end
endhttp://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/
class UserAuthenticator
def initialize(user)
@user = user
end
def authenticate(unencrypted_password)
return false unless @user
if BCrypt::Password.new(@user.password_digest) == unencrypted_password
@user
else
false
end
end
endclass SessionsController < ApplicationController
def create
user = User.where(email: params[:email]).first
if UserAuthenticator.new(user).authenticate(params[:password])
self.current_user = user
redirect_to dashboard_path
else
flash[:alert] = "Login failed."
render "new"
end
end
end- https://speakerdeck.com/seenmyfate/4-steps-to-faster-rails-tests
- http://confreaks.com/videos/641-gogaruco2011-fast-rails-tests
class DiscountCalculator
def total_discount(items)
items.collect(&:discount).inject(:+)
end
endclass Basket < ActiveRecord::Base
has_many :basket_items
def total_discount
DiscountCalculator.new.total_discount(basket_items)
end
end- http://railscasts.com/episodes/398-service-objects
- https://github.com/railscasts/398-service-objects
# app/services/authentication.rb
class Authentication
def initialize(params, omniauth = nil)
@params = params
@omniauth = omniauth
end
def user
@user ||= @omniauth ? user_from_omniauth : user_with_password
end
def authenticated?
user.present?
end
private
def user_from_omniauth
User.where(@omniauth.slice(:provider, :uid)).first_or_initialize.tap do |user|
user.provider = @omniauth[:provider]
user.uid = @omniauth[:uid]
user.username = @omniauth[:info][:nickname]
user.save!
end
end
def user_with_password
user = User.find_by_username(@params[:username])
user && user.authenticate(@params[:password])
end
endclass User < ActiveRecord::Base
attr_accessible :email, :username, :password, :password_confirmation
validates_presence_of :username, :email
validates_uniqueness_of :username
validates_confirmation_of :password
has_secure_password
endclass SessionsController < ApplicationController
#...
def create
auth = Authentication.new(params, env["omniauth.auth"])
if auth.authenticated?
session[:user_id] = auth.user.id
redirect_to root_url, notice: "Logged in!"
else
flash.now.alert = "Username or password is invalid"
render "new"
end
endhttp://blog.firsthand.ca/2011/12/your-rails-application-is-missing.html
class PayDayService
def initialize(date=Date.now)
@date = date
end
def call
Employee.active.each do |e|
if e.pay_date?(@date)
pc = PayCheck.new(e.calculate_pay(@date))
e.send_pay(pc)
end
end
end
end- http://rails-vs-oo.heroku.com/
- http://confreaks.com/videos/1393-rubymanor3-rails-vs-object-oriented-design
class OrdersController < ActionController::Base
def close
#retrieval
payment_handler = Payment.for(params[:method], params[:card])
process = OrderProcess.new(order, payment_handler)
process.close
#rendering
end
endclass Payment
def self.for(method, card_details=nil)
if method == "card"
CardPayment.new(card_details)
else
new
end
end
def handle_payment
#default payment handling code
end
endclass CardPayment
#...
def handle_payment
ExternalPaymentService.new.charge(@card_details)
end
endclass OrderProcess
#...
def close
@payment_handler.handle_payment
Delivery.create! :status => :pending, :order => @order
@order.close!
end
endclass Order < ActiveRecord::Base
#...
def close!
self.closed = true
self.save!
end
end