class Torque::PostgreSQL::Attributes::EnumSet
Public Class Methods
The original Enum
implementation, for individual values
# File lib/torque/postgresql/attributes/enum_set.rb, line 40 def enum_source const_get('EnumSource') end
Fetch a value from the list see github.com/rails/rails/blob/v5.0.0/activerecord/lib/active_record/fixtures.rb#L656 see github.com/rails/rails/blob/v5.0.0/activerecord/lib/active_record/validations/uniqueness.rb#L101
# File lib/torque/postgresql/attributes/enum_set.rb, line 63 def fetch(value, *) new(value.to_s) if values.include?(value) end
Provide a method on the given class to setup which enum sets will be manually initialized
# File lib/torque/postgresql/attributes/enum_set.rb, line 32 def include_on(klass, method_name = nil) method_name ||= Torque::PostgreSQL.config.enum.set_method Builder.include_on(klass, method_name, Builder::Enum, set_features: true) do |builder| defined_enums[builder.attribute.to_s] = builder.subtype end end
Find or create the class that will handle the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 19 def lookup(name, enum_klass) const = name.to_s.camelize + 'Set' namespace = Torque::PostgreSQL.config.enum.namespace return namespace.const_get(const) if namespace.const_defined?(const) klass = Class.new(EnumSet) klass.const_set('EnumSource', enum_klass) namespace.const_set(const, klass) end
Overpass new so blank values return only nil
# File lib/torque/postgresql/attributes/enum_set.rb, line 50 def new(*values) return Lazy.new(self, []) if values.compact.blank? super end
Override string initializer to check for a valid value
# File lib/torque/postgresql/attributes/enum_set.rb, line 99 def initialize(*values) items = if values.size === 1 && values.first.is_a?(Numeric) transform_power(values.first) else transform_values(values) end @hash = items.zip(Array.new(items.size, true)).to_h end
Get the power, 2 ** index, of each element
# File lib/torque/postgresql/attributes/enum_set.rb, line 69 def power(*values) values.flatten.map do |item| item = item.to_i if item.is_a?(Enum) item = values.index(item) unless item.is_a?(Numeric) next 0 if item.nil? || item >= size 2 ** item end.reduce(:+) end
Use the power to get a sample of the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 45 def sample new(rand(0..((2 ** size) - 1))) end
Build an active record scope for a given atribute agains a value
# File lib/torque/postgresql/attributes/enum_set.rb, line 80 def scope(attribute, value) attribute.contains(::Arel.array(value, cast: enum_source.type_name)) end
Get the type name from its class name
# File lib/torque/postgresql/attributes/enum_set.rb, line 56 def type_name @type_name ||= enum_source.type_name + '[]' end
Private Class Methods
Allow fast creation of values
# File lib/torque/postgresql/attributes/enum_set.rb, line 92 def method_missing(method_name, *arguments) return super if self == Enum valid?(method_name) ? new(method_name.to_s) : super end
Allows checking value existance
# File lib/torque/postgresql/attributes/enum_set.rb, line 87 def respond_to_missing?(method_name, include_private = false) valid?(method_name) || super end
Public Instance Methods
Override bitwise & operator to ensure formatted values
# File lib/torque/postgresql/attributes/enum_set.rb, line 163 def &(other) other = other.entries.map(&method(:instantiate)) values = @hash.keys.select { |k| other.include?(k) } self.class.new(values) end
Allow comparison between values of the same enum
# File lib/torque/postgresql/attributes/enum_set.rb, line 111 def <=>(other) raise_comparison(other) if other.is_a?(EnumSet) && other.class != self.class to_i <=> case other when Numeric, EnumSet then other.to_i when String, Symbol then self.class.power(other.to_s) when Array, Set then self.class.power(*other) else raise_comparison(other) end end
Only allow value comparison with values of the same class
# File lib/torque/postgresql/attributes/enum_set.rb, line 124 def ==(other) (self <=> other) == 0 rescue EnumSetError false end
Replace the setter by instantiating the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 153 def []=(key, value) super(key, instantiate(value)) end
Change the inspection to show the enum name
# File lib/torque/postgresql/attributes/enum_set.rb, line 148 def inspect "[#{map(&:inspect).join(', ')}]" end
Override the merge method to ensure formatted values
# File lib/torque/postgresql/attributes/enum_set.rb, line 158 def merge(other) super other.map(&method(:instantiate)) end
It only accepts if the other value is valid
# File lib/torque/postgresql/attributes/enum_set.rb, line 132 def replace(*values) super(transform_values(values)) end
Get a translated version of the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 137 def text(attr = nil, model = nil) map { |item| item.text(attr, model) }.to_sentence end
Get the index of the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 143 def to_i self.class.power(@hash.keys) end
Private Instance Methods
Create a new enum instance of the value
# File lib/torque/postgresql/attributes/enum_set.rb, line 188 def instantiate(value) value.is_a?(self.class.enum_source) ? value : self.class.enum_source.new(value) end
Allow '_' to be associated to '-'
# File lib/torque/postgresql/attributes/enum_set.rb, line 217 def method_missing(method_name, *arguments) name = method_name.to_s if name.chomp!('?') include?(name) elsif name.chomp!('!') add(name) unless include?(name) else super end end
Throw an exception for comparasion between different enums
# File lib/torque/postgresql/attributes/enum_set.rb, line 239 def raise_comparison(other) raise EnumSetError, "Comparison of #{self.class.name} with #{self.inspect} failed" end
Throw an exception for invalid valus
# File lib/torque/postgresql/attributes/enum_set.rb, line 230 def raise_invalid(value) if value.is_a?(Numeric) raise EnumSetError, "#{value.inspect} is out of bounds of #{self.class.name}" else raise EnumSetError, "#{value.inspect} is not valid for #{self.class.name}" end end
Check for valid '?' and '!' methods
# File lib/torque/postgresql/attributes/enum_set.rb, line 209 def respond_to_missing?(method_name, include_private = false) name = method_name.to_s return true if name.chomp!('?') name.chomp!('!') && self.class.valid?(name) end
Turn a binary (power) definition into real values
# File lib/torque/postgresql/attributes/enum_set.rb, line 193 def transform_power(value) list = value.to_s(2).reverse.chars.map.with_index do |item, idx| next idx if item.eql?('1') end raise raise_invalid(value) if list.size > self.class.size self.class.members.values_at(*list.compact) end
Turn all the values into their respective Enum
representations
# File lib/torque/postgresql/attributes/enum_set.rb, line 203 def transform_values(values) values = values.first if values.size.eql?(1) && values.first.is_a?(::Enumerable) values.map(&method(:instantiate)).reject(&:nil?) end