module Enumbler::ClassMethods

Include these ClassMethods in your base ApplicationRecord model to bestow any of your models with the ability to be connected to an Enumbled relation in the same way you would use `belongs_to` now you use `enumbled_to`.

class ApplicationRecord > ActiveRecord::Base
  include Enumbler
  self.abstract_class = true
end

class House < ApplicationRecord
  enumbled_to :color
end

Public Instance Methods

enumbled_to(name, scope = nil, prefix: false, scope_prefix: nil, **options) click to toggle source

Defines the relationship between a model and the Enumbled class. Use this in lieu of `belongs_to` to establish that relationship. It requires a model that has defined one or more `Enumbles`.

# in your migration
create_table :houses, force: true do |t|
  t.references :color, foreign_key: true, null: false
end

class ApplicationRecord > ActiveRecord::Base
  include Enumbler
  self.abstract_class = true
end

class House < ApplicationRecord
  enumbled_to :color
end

@param name [Symbol] symbol representation of the class this belongs_to @param prefix [Boolean] default: false; prefix the instance method

attributes with the Enumble name, ex: `House.color_black?` instead of
`House.black?`

@param scope_prefix [string] optional, prefix the class scopes, for

example: `where_by` will make it `House.where_by_color(:black)`

@param **options [Hash] additional options passed to `belongs_to`

# File lib/enumbler.rb, line 59
def enumbled_to(name, scope = nil, prefix: false, scope_prefix: nil, **options)
  class_name = options.fetch(:class_name, name.to_s.classify)
  enumbled_model = class_name.constantize

  unless enumbled_model.respond_to?(:enumbles)
    raise Error, "The model #{class_name} does not have any enumbles defined."\
      " You can add them via `#{class_name}.enumble :blue, 1`."
  end

  belongs_to(name, scope, **options)

  define_helper_attributes(name)
  define_dynamic_methods_for_enumbled_to_models(name, enumbled_model, prefix: prefix, scope_prefix: scope_prefix)
rescue NameError
  raise Error, "The model #{class_name} cannot be found.  Uninitialized constant."
end

Private Instance Methods

define_dynamic_methods_for_enumbled_to_models(name, enumbled_model, prefix: false, scope_prefix: nil) click to toggle source

Define the dynamic methods for this relationship.

@todo - we should check for naming conflicts!

dangerous_attribute_method?(method_name)
method_defined_within?(method_name, self, Module)
# File lib/enumbler.rb, line 83
def define_dynamic_methods_for_enumbled_to_models(name, enumbled_model, prefix: false, scope_prefix: nil)
  column_name = "#{name}_id"

  cmethod = scope_prefix.blank? ? name : "#{scope_prefix}_#{name}"
  define_singleton_method(cmethod) do |*args|
    where(column_name => enumbled_model.ids_from_enumbler(args))
  end

  define_singleton_method("#{cmethod}!") do |*args|
    where(column_name => enumbled_model.ids_from_enumbler!(args))
  end

  enumbled_model.enumbles.each do |enumble|
    method_name = prefix ? "#{name}_#{enumble.enum}?" : "#{enumble.enum}?"
    not_method_name = prefix ? "#{name}_not_#{enumble.enum}?" : "not_#{enumble.enum}?"
    define_method(method_name) { self[column_name] == enumble.id }
    define_method(not_method_name) { self[column_name] != enumble.id }
  end
end
define_helper_attributes(name) click to toggle source

Add the attirbutes:

house.color_label #=> 'black'
house.color_enum  #=> :black
house.color_graphql_enum #=> 'BLACK'
# File lib/enumbler.rb, line 108
def define_helper_attributes(name)
  %i[label enum graphql_enum].each do |sym|
    define_method("#{name}_#{sym}") { send(name).enumble.send(sym) }
  end
end