class Torque::PostgreSQL::Attributes::Builder::Enum
Constants
- VALID_TYPES
Attributes
attribute[RW]
instance_module[RW]
klass[RW]
klass_module[RW]
options[RW]
subtype[RW]
values[RW]
Public Class Methods
new(klass, attribute, options)
click to toggle source
Start a new builder of methods for enum values on ActiveRecord::Base
# File lib/torque/postgresql/attributes/builder/enum.rb, line 14 def initialize(klass, attribute, options) @klass = klass @attribute = attribute.to_s @subtype = klass.attribute_types[@attribute] @options = options raise Interrupt unless subtype.respond_to?(:klass) @values = subtype.klass.values if @options[:only] @values &= Array(@options[:only]).map(&:to_s) end if @options[:except] @values -= Array(@options[:except]).map(&:to_s) end end
Public Instance Methods
build()
click to toggle source
Create all methods needed
# File lib/torque/postgresql/attributes/builder/enum.rb, line 91 def build @klass_module = Module.new @instance_module = Module.new plural stringify all_values set_scopes if set_features? klass.extend klass_module klass.include instance_module end
conflicting?()
click to toggle source
Check if any of the methods that will be created get in conflict with the base class methods
# File lib/torque/postgresql/attributes/builder/enum.rb, line 62 def conflicting? return if options[:force] == true attributes = attribute.pluralize dangerous?(attributes, true) dangerous?("#{attributes}_keys", true) dangerous?("#{attributes}_texts", true) dangerous?("#{attributes}_options", true) dangerous?("#{attribute}_text") if set_features? dangerous?("has_#{attributes}", true) dangerous?("has_any_#{attributes}", true) end values_methods.each do |attr, (scope, ask, bang, *)| dangerous?(scope, true) dangerous?(bang) dangerous?(ask) end rescue Interrupt => err raise ArgumentError, <<-MSG.squish Enum #{subtype.name} was not able to generate requested methods because the method #{err} already exists in #{klass.name}. MSG end
set_features?()
click to toggle source
Check if it's building the methods for sets
# File lib/torque/postgresql/attributes/builder/enum.rb, line 56 def set_features? options[:set_features].present? end
values_methods()
click to toggle source
Get the list of methods based on enum values
# File lib/torque/postgresql/attributes/builder/enum.rb, line 33 def values_methods return @values_methods if defined?(@values_methods) prefix = options.fetch(:prefix, nil) suffix = options.fetch(:suffix, nil) prefix = attribute if prefix == true suffix = attribute if suffix == true base = [prefix, '%s', suffix].compact.join('_') @values_methods = begin values.map do |val| key = val.downcase.tr('- ', '__') scope = base % key ask = scope + '?' bang = scope + '!' [key, [scope, ask, bang, val]] end.to_h end end
Private Instance Methods
all_values()
click to toggle source
Create all the methods that represent actions related to the attribute value
# File lib/torque/postgresql/attributes/builder/enum.rb, line 181 def all_values klass_content = '' instance_content = '' enum_klass = subtype.klass.name values_methods.each do |key, (scope, ask, bang, val)| klass_content += <<-RUBY def #{scope} # def admin attr = arel_table['#{attribute}'] # attr = arel_table['role'] where(::#{enum_klass}.scope(attr, '#{val}')) # where(Enum::Roles.scope(attr, 'admin')) end # end RUBY instance_content += <<-RUBY def #{ask} # def admin? #{attribute}.#{key}? # role.admin? end # end def #{bang} # admin! self.#{attribute} = '#{val}' # self.role = 'admin' return unless #{attribute}_changed? # return unless role_changed? return save! if Torque::PostgreSQL.config.enum.save_on_bang true # true end # end RUBY end klass_module.module_eval(klass_content) instance_module.module_eval(instance_content) end
dangerous?(method_name, class_method = false)
click to toggle source
Check if the method already exists in the reference class
# File lib/torque/postgresql/attributes/builder/enum.rb, line 107 def dangerous?(method_name, class_method = false) if class_method if klass.dangerous_class_method?(method_name) raise Interrupt, method_name.to_s end else if klass.dangerous_attribute_method?(method_name) raise Interrupt, method_name.to_s end end rescue Interrupt => e raise e if Torque::PostgreSQL.config.enum.raise_conflicting type = class_method ? 'class method' : 'instance method' indicator = class_method ? '.' : '#' Torque::PostgreSQL.logger.info(<<~MSG.squish) Creating #{class_method} :#{method_name} for enum. Overwriting existing method #{klass.name}#{indicator}#{method_name}. MSG end
plural()
click to toggle source
Create the method that allow access to the list of values
# File lib/torque/postgresql/attributes/builder/enum.rb, line 129 def plural enum_klass = subtype.klass.name klass_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{attribute.pluralize} # def roles ::#{enum_klass}.values # Enum::Roles.values end # end def #{attribute.pluralize}_keys # def roles_keys ::#{enum_klass}.keys # Enum::Roles.keys end # end def #{attribute.pluralize}_texts # def roles_texts ::#{enum_klass}.members.map do |member| # Enum::Roles.members do |member| member.text('#{attribute}', self) # member.text('role', self) end # end end # end def #{attribute.pluralize}_options # def roles_options #{attribute.pluralize}_texts.zip(::#{enum_klass}.values) # roles_texts.zip(Enum::Roles.values) end # end RUBY end
set_scopes()
click to toggle source
Create additional methods when the enum is a set, which needs better ways to check if values are present or not
# File lib/torque/postgresql/attributes/builder/enum.rb, line 154 def set_scopes cast_type = subtype.name.chomp('[]') klass_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def has_#{attribute.pluralize}(*values) # def has_roles(*values) attr = arel_table['#{attribute}'] # attr = arel_table['role'] where(attr.contains(::Arel.array(values, cast: '#{cast_type}'))) # where(attr.contains(::Arel.array(values, cast: 'roles'))) end # end def has_any_#{attribute.pluralize}(*values) # def has_roles(*values) attr = arel_table['#{attribute}'] # attr = arel_table['role'] where(attr.overlaps(::Arel.array(values, cast: '#{cast_type}'))) # where(attr.overlaps(::Arel.array(values, cast: 'roles'))) end # end RUBY end
stringify()
click to toggle source
Create the method that turn the attribute value into text using the model scope
# File lib/torque/postgresql/attributes/builder/enum.rb, line 171 def stringify instance_module.module_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{attribute}_text # def role_text #{attribute}.text('#{attribute}', self) # role.text('role', self) end # end RUBY end