Skip to content

Instantly share code, notes, and snippets.

@dhh
Last active July 3, 2025 15:57
Show Gist options
  • Save dhh/9348053 to your computer and use it in GitHub Desktop.
Save dhh/9348053 to your computer and use it in GitHub Desktop.

Revisions

  1. dhh revised this gist Mar 6, 2014. 1 changed file with 1 addition and 5 deletions.
    6 changes: 1 addition & 5 deletions reshaping_the_command_approach.rb
    Original file line number Diff line number Diff line change
    @@ -23,7 +23,7 @@ def update_assigment_attributes(new_owner, details)
    end

    def transfer_open_tasks_to(new_owner)
    tasks.open.each { |task| task.assign_to new_owner }
    tasks.open.each { |task| task.update! owner: new_owner }
    end

    def create_initial_contact_task(details)
    @@ -39,10 +39,6 @@ class Task < ActiveRecord::Base
    belongs_to :case

    scope :open, -> { where.not status: :closed }

    def assign_to(new_owner)
    update! owner: new_owner
    end
    end

    class User
  2. dhh renamed this gist Mar 4, 2014. 1 changed file with 0 additions and 0 deletions.
  3. dhh created this gist Mar 4, 2014.
    153 changes: 153 additions & 0 deletions reshaping the command approach
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,153 @@
    # MODEL

    class Case < ActiveRecord::Base
    include Eventable

    has_many :tasks

    concerning :Assignment do
    def assign_to(new_owner:, details:)
    transaction do
    update_assigment_attributes new_owner, details

    transfer_open_tasks_to new_owner
    create_initial_contact_task details

    record_event :assigned, details[:comments]
    end
    end

    private
    def update_assigment_attributes(new_owner, details)
    update! details.slice(:distribute_at, :distribute_rule_name).merge(owner: new_owner)
    end

    def transfer_open_tasks_to(new_owner)
    tasks.open.each { |task| task.assign_to new_owner }
    end

    def create_initial_contact_task(details)
    if details[:require_initial] && owner.tasks.initials?
    tasks.create! kind: :initial, details[:comments]
    end
    end
    end
    end

    class Task < ActiveRecord::Base
    belongs_to :user
    belongs_to :case

    scope :open, -> { where.not status: :closed }

    def assign_to(new_owner)
    update! owner: new_owner
    end
    end

    class User
    has_many :tasks do
    def initials?
    where(kind: :initial).exist?
    end
    end
    end


    class Event < ActiveRecord::Base
    store :details, accessors: [ :activity, :creator, :comments ]

    cattr_accessor :creator, instance_accessor: false
    before_save :set_creator

    private
    def set_creator
    self.creator ||= self.class.creator
    end
    end

    module Eventable
    extend ActiveSupport::Concern

    included do
    has_many :events
    end

    private
    def record_event(activity, attributes = {})
    events.create! attributes.merge(activity: activity, eventable: self)
    end
    end


    # CONTROLLER

    class Cases::AssignmentController < ApplicationController
    before_action :set_case

    def create
    @case.assign_to new_owner: find_new_owner, details: assignment_params
    end

    private
    def set_case
    @case = @current_account.cases.find
    end

    def assignment_params
    params.require(:case).permit(:comments, :distribute_at, :distribute_rule_name, :require_initial)
    end

    def find_new_owner
    @current_account.users.find(params[:case][:owner_id])
    end
    end

    class ApplicationController < ActionController::Base
    include CurrentUser, CurrentAccount
    end

    module CurrentUser
    extend ActiveSupport::Concern

    included do
    before_action :set_current_user
    end

    private
    def set_current_user
    @current_user = authorize
    Event.creator = @current_user
    end
    end


    # VIEW

    class EventSummarizer
    def initialize(event)
    @event = event
    end

    def summary
    summarizer.new(@event).send(summary_method)
    end

    private
    def summarizer
    Object.const_get("#{@event.eventable.class}EventSummarizer")
    end

    def summary_method
    "#{@event.eventable.class.to_s.underscore}_#{@event.activity}_summary"
    end
    end


    class CaseEventSummarizer < EventSummarizer
    def case_assigned_summary
    "Case assigned to #{@event.eventable.owner.full_name}".tap do |summary|
    summary << "; #{@event.comments}" if @event.comments
    end
    end
    end