# 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.update! owner: 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 } 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