module RailsStuff::Statusable

Basic helpers to work with `status`-like field.

For every status value it provides:

It also provides:

It supports mapped statuses, just provide a hash with `{status_name => interna_value}` instead of array of statuses.

Public Class Methods

fetch_statuses(model, field) click to toggle source

Fetches statuses list from model constants. See has_status_field.

# File lib/rails_stuff/statusable.rb, line 28
def fetch_statuses(model, field)
  const_name = "#{field.to_s.pluralize.upcase}_MAPPING"
  const_name = field.to_s.pluralize.upcase unless model.const_defined?(const_name)
  model.const_get(const_name)
end

Public Instance Methods

has_status_field(field = :status, statuses = nil, mapping: nil, **options) { |builder| ... } click to toggle source

Defines all helpers working with `field` (default to `status`). List of values can be given as second argument, otherwise it'll be read from consts using pluralized name of `field` (eg. default to `STATUSES_MAPPING`, `STATUSES`).

#### Options

  • `prefix` - used to prefix value-named helpers.

    # this defines #shipped?, #shipped! methods
    has_status_field :delivery_status, %i(shipped delivered)
    
    # this defines #delivery_shipped?, #delivery_shipped! methods
    has_status_field :delivery_status, %i(shipped delivered), prefix: :delivery_
    
  • `suffix` - similar to `prefix`.

  • `validate` - additional options for validatior. `false` to disable it.

  • `helper` - custom helper class.

  • `builder` - custom methods builder class.

  • `mapping` - shortcut for `statuses` param (see examples).

Pass block to customize methods generation process (see Builder for available methods):

# This will define only scope with status names, but no other methods.
has_status_field do |builder|
  builder.value_scopes
end

Examples:

# Setup #status field, take list from STATUSES or STATUSES_MAPPING constant.
has_status_field
# Custom field, take kist from KINDS or KINDS_MAPPING:
has_status_field :kind
# Inline statuses list and options:
has_status_field :status, %i(one two), prefix: :my_
has_status_field :status, {one: 1, two: 2}, prefix: :my_
has_status_field :status, mapping: {one: 1, two: 2}, prefix: :my_
# Mapped field without options:
has_status_field :status, {one: 1, two: 2}, {}
has_status_field :status, mapping: {one: 1, two: 2}
# File lib/rails_stuff/statusable.rb, line 81
def has_status_field(field = :status, statuses = nil, mapping: nil, **options)
  statuses ||= mapping || Statusable.fetch_statuses(self, field)
  is_mapped = statuses.is_a?(Hash)
  helper_class = options.fetch(:helper) { is_mapped ? MappedHelper : Helper }
  helper = helper_class.new(self, field, statuses)
  helper.attach
  builder_class = options.fetch(:builder) { is_mapped ? MappedBuilder : Builder }
  if builder_class
    builder = builder_class.new(helper, options)
    block_given? ? yield(builder) : builder.generate
  end
end
statusable_methods() click to toggle source

Module to hold generated methods. Single for all status fields in model.

# File lib/rails_stuff/statusable.rb, line 95
def statusable_methods
  # Include generated methods with a module, not right in class.
  @statusable_methods ||= Module.new.tap do |m|
    m.const_set :ClassMethods, Module.new
    include m
    extend m::ClassMethods
  end
end