Class: ActWithFlags::Admin

Inherits:
Object
  • Object
show all
Defined in:
lib/act_with_flags/define.rb,
lib/act_with_flags/utils.rb,
lib/act_with_flags/print.rb,
lib/act_with_flags/admin.rb

Overview

rubocop:disable all frozen_string_literal: true

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model) ⇒ Admin

Returns a new instance of Admin.



10
11
12
13
14
15
16
17
18
19
# 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

Instance Attribute Details

#delete_maskObject (readonly)

Returns the value of attribute delete_mask.



8
9
10
# File 'lib/act_with_flags/admin.rb', line 8

def delete_mask
  @delete_mask
end

#modelObject (readonly)

Returns the value of attribute model.



6
7
8
# File 'lib/act_with_flags/admin.rb', line 6

def model
  @model
end

#originObject

Returns the value of attribute origin.



7
8
9
# File 'lib/act_with_flags/admin.rb', line 7

def origin
  @origin
end

Instance Method Details

#add(name, pos) ⇒ Object



55
56
57
58
59
60
61
62
# 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) ⇒ Object



5
6
7
8
9
10
11
12
13
14
# 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) ⇒ Object



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# 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) ⇒ Object



16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# 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) ⇒ Object



64
65
66
# File 'lib/act_with_flags/admin.rb', line 64

def add_to_delete_mask(name)
  @delete_mask |= mask(name)
end

#before_saveObject



71
72
73
74
75
76
77
# 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_allObject



39
40
41
# 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) ⇒ Object



51
52
53
# 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) ⇒ Object



60
61
62
63
64
65
66
67
68
69
# 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

#namesObject



25
26
27
# File 'lib/act_with_flags/admin.rb', line 25

def names
  @map.keys.sort
end

#position(name) ⇒ Object



41
42
43
44
45
46
47
48
49
# 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) ⇒ Object



50
51
52
# File 'lib/act_with_flags/define.rb', line 50

def remove_accessor(accessor)
  my_undef model, accessor, "#{accessor}?", "#{accessor}="
end

#resetObject



43
44
45
46
47
48
49
# 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) ⇒ Object



21
22
23
# File 'lib/act_with_flags/admin.rb', line 21

def reset_model(model)
  initialize model
end

#to_boolean(value) ⇒ Object



29
30
31
32
33
34
# 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_sObject



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
# 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) ⇒ Object



54
55
56
57
58
# 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