Shout Out

Shout Out allows for the abstraction of complex ActiveRecord callbacks.

Installation

Add this line to your application's Gemfile:

gem 'shout_out' And then execute:

$ bundle

Or install it yourself as:

$ gem install shout_out

Then run the install generator

$ rails g shout_out:install

This will create ApplicationShout in /app/shouts/application_shout.rb

Usage

To generate a shout class for a model, just use the generator.

$ rails g shout_out:shout My::Model::Name

This will create the appropriate class in the /app/shouts directory, i.e. /app/shouts/my/model/name_shout.rb.

Now you can define methods for any callback.

before_validation
validate
after_validation
before_save
after_save
before_create
after_create
after_commit

Example

The below is an example of using shouts to handle cache invalidation on interdependent models.

# /app/shouts/invoice_shout.rb
class InvoiceShout < ApplicationShout

  def after_save
    touch_project
    touch_report_ffa_efficiency
    touch_report_ffa_hour_tracker
  end

  private

  def touch_report_ffa_efficiency
    if record.total_ffa_changed? && calculable? && !record.report_ffa_efficiency.new_record?
      record.report_ffa_efficiency.touch
    end
  end

  def touch_report_ffa_hour_tracker
    changed = record.total_ffa_changed? || work_type_changed?(WorkType.codes[:ffa])

    if changed && calculable? && record.report_ffa_hour_tracker
      record.report_ffa_hour_tracker.touch
    end
  end

  def touch_project
    changed = record.product_comp_changed? || record.product_cost_changed? || record.labor_comp_changed?

    if changed && calculable? && record.project
      record.project.touch
    end
  end

end

You can define common methods in ApplicationShout.

# /app/shouts/application_shout.rb
class ApplicationShout

  ...

  def calculable?
    record.calculable? || record.calculable_changed?
  end

  def work_type_changed?(codes)
    codes = [codes] unless code.is_a?(Array)
    record.work_type_code_changed? && ([record.work_type_code, record.work_type_code_was] & codes).any?
  end

end

Contributing

  • Fork it ( https://github.com/kpheasey/shout_out/fork )
  • Create your feature branch (git checkout -b my-new-feature)
  • Commit your changes (git commit -am 'Add some feature')
  • Push to the branch (git push origin my-new-feature)
  • Create a new Pull Request