class ActWithFlags::Admin

rubocop:disable all

rubocop:disable all

rubocop:disable all

rubocop: disable all

Attributes

delete_mask[R]
model[R]
origin[R]

Public Class Methods

new(model) click to toggle source
# File lib/act_with_flags/admin.rb, line 10
def initialize(model)
  @model = model
  @origin = :flags
  @map = {}
  @delete_mask = 0
  @max_position = 512 - 1
  @boolean_hash = {}
  [true,  'true',  1, '1'].each { |x| @boolean_hash[x] = true }
  [false, 'false', 0, '0'].each { |x| @boolean_hash[x] = false }
end

Public Instance Methods

add(name, pos) click to toggle source
# File lib/act_with_flags/admin.rb, line 55
def add(name, pos)
  values = @map.values
  pos ||= (0..@max_position).detect { |i| !values.include?(i) }
  raise "invalid position '#{name} @ #{pos}'"  unless pos
  raise "name in use '#{name} @ #{pos}'"       if @map.key?(name)
  raise "position in use '#{name} @ #{pos}'"   if @map.value?(pos)
  @map[name] = pos
end
add_accessor(name, pos) click to toggle source
# File lib/act_with_flags/utils.rb, line 5
  def add_accessor(name, pos)
#p "** act_with_flags: add_accessor '#{name} @ #{pos}'"
    accessor = name.to_sym
    validate_accessor accessor, "#{accessor}?", "#{accessor}="

    add accessor, pos
    mask = mask(accessor)
    origin = self.origin
    add_accessors(origin, accessor, mask)
  end
add_accessors(origin, accessor, mask) click to toggle source
# File lib/act_with_flags/define.rb, line 6
  def add_accessors(origin, accessor, mask)
#p ["act_with_flags#add_accessors:", model, origin, accessor, mask]
    unless model.method_defined?(:act_with_flags)
      model.class_eval %(
        def act_with_flags
          #{model}.act_with_flags
        end
      )
    end

    model.class_eval %(
      def #{accessor}
        #{accessor}?
      end

      def #{accessor}?
        raise "Uninitialized '#{model}.#{origin}'"  if #{origin}.nil?
        if #{origin}.is_a?(String)
          flags = self.#{origin}.to_i
          !( flags & #{mask} ).zero?
        else
          !( self.#{origin} & #{mask} ).zero?
        end
      end

      def #{accessor}=(value)
        raise "Uninitialized '#{model}.#{origin}'"  if #{origin}.nil?
        is_a_string = #{origin}.is_a?(String)
        flags = is_a_string ? self.#{origin}.to_i : self.#{origin}
        flags ||= 0

        result = self.act_with_flags.to_boolean(value)
        if result
          flags |= #{mask}
        else
          flags &= ~#{mask}
        end
        self.#{origin} = is_a_string ? flags.to_s : flags

        result
      end
    )
  end
add_mask_et_all(origin) click to toggle source
# File lib/act_with_flags/utils.rb, line 16
def add_mask_et_all(origin)
  model.class_eval %(
    def flags_mask(*names)
      self.class.act_with_flags.mask(*names)
    end

    def flags_any?(*names)
      mask = self.class.act_with_flags.mask(*names)
      !( self.#{origin} & mask ).zero?
    end

    def flags_all?(*names)
      mask = self.class.act_with_flags.mask(*names)
      ( self.#{origin} & mask ) == mask
    end

    def flags_none?(*names)
      mask = self.class.act_with_flags.mask(*names)
      ( self.#{origin} & mask ).zero?
    end
  )
end
add_to_delete_mask(name) click to toggle source
# File lib/act_with_flags/admin.rb, line 64
def add_to_delete_mask(name)
  @delete_mask |= mask(name)
end
before_save() click to toggle source
# File lib/act_with_flags/define.rb, line 71
def before_save
  model.class_eval %(
    before_save do |row|
      row.#{origin} &= ~row.class.act_with_flags.delete_mask
    end
  )
end
delete_mask_et_all() click to toggle source
# File lib/act_with_flags/utils.rb, line 39
def delete_mask_et_all
  my_undef :flags_mask, :flags_any?, :flags_all?, :flags_none?
end
mask(*names) click to toggle source
# File lib/act_with_flags/admin.rb, line 51
def mask(*names)
  names.inject(0) { |msk, name| msk | ( 1 << position(name) ) }
end
my_undef(*names) click to toggle source
# File lib/act_with_flags/define.rb, line 60
def my_undef(*names)
  names.each { |name|
    model.class_eval %(
      begin
        undef #{name}
      rescue
      end
    )
  }
end
names() click to toggle source
# File lib/act_with_flags/admin.rb, line 25
def names
  @map.keys.sort
end
origin=(name) click to toggle source
# File lib/act_with_flags/admin.rb, line 36
def origin=(name)
  raise 'invalid update of origin'  unless @map.empty? || (origin == name)
  @origin = name
end
position(name) click to toggle source
# File lib/act_with_flags/admin.rb, line 41
def position(name)
  pos = @map[name]
  return pos  if pos

  parent = self.model.superclass.act_with_flags
  return parent.position(name)  if parent

  raise "unknown flag '#{model}##{name}'"
end
remove_accessor(accessor) click to toggle source
# File lib/act_with_flags/define.rb, line 50
def remove_accessor(accessor)
  my_undef model, accessor, "#{accessor}?", "#{accessor}="
end
reset() click to toggle source
# File lib/act_with_flags/utils.rb, line 43
def reset
  delete_mask_et_all
  names.each { |name|
    remove_accessor name
  }
  reset_model model
end
reset_model(model) click to toggle source
# File lib/act_with_flags/admin.rb, line 21
def reset_model(model)
  initialize model
end
to_boolean(value) click to toggle source
# File lib/act_with_flags/admin.rb, line 29
def to_boolean(value)
  res = @boolean_hash[value]
  return res  unless res.nil?

  raise "invalid boolean <#{value}>"
end
to_s() click to toggle source
# File lib/act_with_flags/print.rb, line 6
def to_s
  res = []
  res << title('Variables')
  res << variables(:origin, :boolean_hash)
  res << variables(:delete_mask)

  res << title('Flags sorted alfabetically')
  @map.sort.each { |key, pos| res << "#{key}  #{position(key)}" }

  res << title('Flags sorted by position')
  @map.sort.sort_by(&:last).each { |key, pos|
    res << "#{key}  #{position(key)}"
  }

  res << title('Flags and mask; sorted alfabetically')
  @map.sort.each { |key, pos|
    res << "#{key}  #{sprintf('0x%08X', mask(key))}"
  }

  res << title('FLAG assignment; sorted alfabetically')
  @map.sort.each { |key, pos|
    res << "FLAG_#{key.upcase} = #{sprintf('0x%08X', mask(key))}"
  }

  res << title('FLAG assignment; sorted by position')
  @map.sort.sort_by(&:last).each { |key, pos|
    res << "FLAG_#{key.upcase} = #{sprintf('0x%08X', mask(key))}"
  }

  res.flatten.join("\n")
end
validate_accessor(*names) click to toggle source
# File lib/act_with_flags/define.rb, line 54
def validate_accessor(*names)
  names.each { |acc|
    raise "redefining #{acc} rejected"  if model.method_defined?(acc)
  }
end

Private Instance Methods

title(msg) click to toggle source
# File lib/act_with_flags/print.rb, line 39
def title(msg)
  sep = '#' * 10
  ['', "#{sep} #{msg} #{sep}"]
end
variables(*names) click to toggle source
# File lib/act_with_flags/print.rb, line 44
def variables(*names)
  names.collect { |name|
    value = instance_variable_get(:"@#{name}")
    "#{name} #{value}"
  }
end