Skip to content
cavalle edited this page Dec 23, 2012 · 28 revisions

Version #1

http://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
end
class 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

Version #2

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
end
describe 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
end

Before

class User < ActiveRecord::Base
  after_create :log_creation

  protected
    def log_creation
      Log.new_user(self)
    end
end

Clone this wiki locally