module DynamicAttributeDeclaration::ClassMethods

Public Instance Methods

add_dynamic_attrs(attrs) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 115
def add_dynamic_attrs attrs
  attrs.each do |attr|
    key, value = *attr.flatten
    if self._dynamic_attrs.keys.include? key
      self._dynamic_attrs[key].push process_attr(value)
    else
      self._dynamic_attrs[key] = [process_attr(value)]
    end
  end
end
attrs_for(state=nil, device=nil) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 69
def attrs_for state=nil, device=nil
  if state && state.to_sym != :all
    state = state.to_sym
    device = device ? device.to_sym : nil
    devices = [:all, device].compact.uniq

    _dynamic_attrs.select do |attr_name, definitions|
      on_attrs = attrs_on_for(attr_name)
      if on_attrs
        comparer = (devices & on_attrs.keys).map { |k| on_attrs[k] }.flatten.uniq
      end
      comparer.map(&:to_sym).include? state.to_sym
    end
  else
    _dynamic_attrs
  end
end
attrs_names_for(state=nil, device=nil) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 87
def attrs_names_for state=nil, device=nil
  attrs_for(state, device).map(&:first)
end
attrs_on_for(attr_name) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 49
def attrs_on_for attr_name
  attr = _dynamic_attrs[attr_name]
  if attr && !attr.empty?
    rtn = {}
    attr.each do |a|
      if a.key? :on
        obj = a[:on]
        obj.each do |key, value|
          if rtn.key? key
            rtn[key].push(value).flatten!.uniq!
          else
            rtn[key] = value
          end
        end
      end
    end
    rtn
  end
end
build_validations_from_dynamic_attrs(attrs) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 91
def build_validations_from_dynamic_attrs attrs
  # throw "No validation state if defined" unless _rdynamic_attr_state_if
  attrs.each do |attr|
    key, value = *attr.flatten
    if value.key?(:validates) && !value[:validates].empty?
      opts = value[:validates].deep_symbolize_keys

      # Check if validation should only be used in specific state
      if value.key?(:on) && _dynamic_attr_state_if && _dynamic_attr_state_if.class == Proc
        validates_on = value[:on]
        # If validates contains if statement, wrap that statement in state check
        if opts.key?(:if)
          original_if = opts.delete(:if)
          opts.merge! if: ->(model) { model.instance_exec(validates_on, &_dynamic_attr_state_if) && model.instance_eval(&original_if) }
        else
          opts.merge! if: ->(model) { model.instance_exec(validates_on, &_dynamic_attr_state_if) }
        end
      end

      validates key.to_sym, opts
    end
  end
end
clear_dynamic_attrs!() click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 34
def clear_dynamic_attrs!
  self._dynamic_attrs = {}
  self._dynamic_attr_state_if = nil
end
define_attr_state_if(proc) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 39
def define_attr_state_if proc
  throw "define_attr_state_if should be a proc" unless proc.class == Proc
  self._dynamic_attr_state_if = proc
end
define_attrs(args) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 44
def define_attrs args
  add_dynamic_attrs args
  build_validations_from_dynamic_attrs args
end
process_attr(attr) click to toggle source
# File lib/dynamic_attribute_declaration.rb, line 126
def process_attr attr
  rtn = {}
  attr.each do |key, value|
    if key == :on
      case value
      when Symbol
        new_value = { all: [value] }
      when Array
        new_value = { all: value }
      when Hash
        new_value = {}
        value.each { |k,v| new_value[k] = *v }
      else
        throw "Process attr #{value} cannot be of class #{value.class}"
      end
    else
      new_value = value
    end
    rtn[key] = new_value
  end
  rtn
end