act_with_flags 0.2.4 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/rake.yml +9 -3
- data/.ruby-gemset +1 -1
- data/.ruby-version +1 -1
- data/.watchr +29 -16
- data/Appraisals +10 -6
- data/Gemfile +7 -6
- data/Gemfile.lock +124 -104
- data/MIT-LICENSE +1 -1
- data/README.md +30 -3
- data/Rakefile +5 -5
- data/TODO +21 -0
- data/act_with_flags.gemspec +20 -20
- data/gemfiles/rails_6.0.gemfile +2 -1
- data/gemfiles/rails_7.0.gemfile +15 -0
- data/lib/act_with_flags/admin.rb +5 -48
- data/lib/act_with_flags/clear.rb +30 -0
- data/lib/act_with_flags/define.rb +6 -35
- data/lib/act_with_flags/flags.rb +67 -0
- data/lib/act_with_flags/print.rb +21 -27
- data/lib/act_with_flags/utils.rb +25 -13
- data/lib/act_with_flags/version.rb +8 -7
- data/lib/act_with_flags.rb +14 -25
- data/test/any_all_none_test.rb +6 -9
- data/test/benchmark_test.rb +73 -0
- data/test/clear_test.rb +5 -7
- data/test/coding_check_add_test.rb +29 -0
- data/test/coding_coverage_test.rb +19 -0
- data/test/coding_mask2d_test.rb +25 -0
- data/test/coding_null_test.rb +29 -0
- data/test/coding_one_test.rb +26 -0
- data/test/coding_reset_test.rb +18 -0
- data/test/inheritance_any_test.rb +9 -33
- data/test/inheritance_test.rb +7 -10
- data/test/internal/app/controllers/orders_controller.rb +1 -3
- data/test/internal/app/models/order.rb +1 -5
- data/test/internal/config/routes.rb +1 -1
- data/test/internal/db/schema.rb +6 -7
- data/test/legacy_test.rb +8 -9
- data/test/mask_test.rb +6 -7
- data/test/null_test.rb +3 -5
- data/test/one_test.rb +7 -9
- data/test/origin_test.rb +7 -26
- data/test/origins_test.rb +57 -0
- data/test/remove_from_test.rb +3 -4
- data/test/test_helper.rb +8 -8
- metadata +21 -41
- data/.rubocop.yml +0 -9
- data/test/internal_benchmark_test.rb +0 -52
- data/test/internal_check_add_test.rb +0 -36
- data/test/internal_null_test.rb +0 -29
- data/test/internal_one_test.rb +0 -27
- data/test/reset_test.rb +0 -17
data/lib/act_with_flags/admin.rb
CHANGED
@@ -1,68 +1,25 @@
|
|
1
|
-
# rubocop:disable all
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
class ActWithFlags::Admin
|
5
|
-
|
6
4
|
attr_reader :model
|
7
|
-
attr_reader :origin
|
8
|
-
attr_reader :delete_mask
|
9
5
|
|
10
6
|
def initialize(model)
|
7
|
+
@locations = {}
|
8
|
+
@clears = {}
|
11
9
|
@model = model
|
12
|
-
@origin = :flags
|
13
|
-
@map = {}
|
14
|
-
@delete_mask = 0
|
15
|
-
@max_position = 512 - 1
|
16
10
|
@boolean_hash = {}
|
17
|
-
[true,
|
18
|
-
[false,
|
11
|
+
[true, "true", 1, "1"].each { |x| @boolean_hash[x] = true }
|
12
|
+
[false, "false", 0, "0"].each { |x| @boolean_hash[x] = false }
|
19
13
|
end
|
20
14
|
|
21
15
|
def reset_model(model)
|
22
16
|
initialize model
|
23
17
|
end
|
24
18
|
|
25
|
-
def names
|
26
|
-
@map.keys.sort
|
27
|
-
end
|
28
|
-
|
29
19
|
def to_boolean(value)
|
30
20
|
res = @boolean_hash[value]
|
31
|
-
return res
|
21
|
+
return res unless res.nil?
|
32
22
|
|
33
23
|
raise "invalid boolean <#{value}>"
|
34
24
|
end
|
35
|
-
|
36
|
-
def origin=(name)
|
37
|
-
raise 'invalid update of origin' unless @map.empty? || (origin == name)
|
38
|
-
@origin = name
|
39
|
-
end
|
40
|
-
|
41
|
-
def position(name)
|
42
|
-
pos = @map[name]
|
43
|
-
return pos if pos
|
44
|
-
|
45
|
-
parent = self.model.superclass.act_with_flags
|
46
|
-
return parent.position(name) if parent
|
47
|
-
|
48
|
-
raise "unknown flag '#{model}##{name}'"
|
49
|
-
end
|
50
|
-
|
51
|
-
def mask(*names)
|
52
|
-
names.inject(0) { |msk, name| msk | ( 1 << position(name) ) }
|
53
|
-
end
|
54
|
-
|
55
|
-
def add(name, pos)
|
56
|
-
values = @map.values
|
57
|
-
pos ||= (0..@max_position).detect { |i| !values.include?(i) }
|
58
|
-
raise "invalid position '#{name} @ #{pos}'" unless pos
|
59
|
-
raise "name in use '#{name} @ #{pos}'" if @map.key?(name)
|
60
|
-
raise "position in use '#{name} @ #{pos}'" if @map.value?(pos)
|
61
|
-
@map[name] = pos
|
62
|
-
end
|
63
|
-
|
64
|
-
def add_to_delete_mask(name)
|
65
|
-
@delete_mask |= mask(name)
|
66
|
-
end
|
67
|
-
|
68
25
|
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActWithFlags::Admin
|
4
|
+
attr_reader :clears
|
5
|
+
|
6
|
+
def clear_at_save(*flags)
|
7
|
+
flags.each { |name| add_to_clear_mask(name) }
|
8
|
+
clears.each { |orig, mask|
|
9
|
+
before_save(orig, mask)
|
10
|
+
}
|
11
|
+
@clears = {}
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def add_to_clear_mask(name)
|
17
|
+
_model, orig, _pos = location(name).values
|
18
|
+
mask = @clears[orig] || 0
|
19
|
+
mask |= 1 << position(name)
|
20
|
+
@clears[orig] = mask
|
21
|
+
end
|
22
|
+
|
23
|
+
def before_save(orig, mask)
|
24
|
+
model.class_eval %(
|
25
|
+
before_save do |row|
|
26
|
+
row.#{orig} &= ~#{mask}
|
27
|
+
end
|
28
|
+
), __FILE__, __LINE__ - 4
|
29
|
+
end
|
30
|
+
end
|
@@ -1,16 +1,13 @@
|
|
1
|
-
# rubocop:disable all
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
class ActWithFlags::Admin
|
5
|
-
|
6
|
-
def add_accessors(origin, accessor, mask)
|
7
|
-
#p ["act_with_flags#add_accessors:", model, origin, accessor, mask]
|
4
|
+
def add_accessors(accessor, origin, mask)
|
8
5
|
unless model.method_defined?(:act_with_flags)
|
9
6
|
model.class_eval %(
|
10
7
|
def act_with_flags
|
11
8
|
#{model}.act_with_flags
|
12
9
|
end
|
13
|
-
)
|
10
|
+
), __FILE__, __LINE__ - 4
|
14
11
|
end
|
15
12
|
|
16
13
|
model.class_eval %(
|
@@ -19,7 +16,7 @@ class ActWithFlags::Admin
|
|
19
16
|
end
|
20
17
|
|
21
18
|
def #{accessor}?
|
22
|
-
raise "Uninitialized '#{model}.#{origin}'"
|
19
|
+
raise "Uninitialized '#{model}.#{origin}'" if #{origin}.nil?
|
23
20
|
if #{origin}.is_a?(String)
|
24
21
|
flags = self.#{origin}.to_i
|
25
22
|
!( flags & #{mask} ).zero?
|
@@ -29,9 +26,9 @@ class ActWithFlags::Admin
|
|
29
26
|
end
|
30
27
|
|
31
28
|
def #{accessor}=(value)
|
32
|
-
raise "Uninitialized '#{model}.#{origin}'"
|
29
|
+
raise "Uninitialized '#{model}.#{origin}'" if #{origin}.nil?
|
33
30
|
is_a_string = #{origin}.is_a?(String)
|
34
|
-
flags =
|
31
|
+
flags = self.#{origin}.to_i
|
35
32
|
flags ||= 0
|
36
33
|
|
37
34
|
result = self.act_with_flags.to_boolean(value)
|
@@ -44,36 +41,10 @@ class ActWithFlags::Admin
|
|
44
41
|
|
45
42
|
result
|
46
43
|
end
|
47
|
-
)
|
44
|
+
), __FILE__, __LINE__ - 31
|
48
45
|
end
|
49
46
|
|
50
47
|
def remove_accessor(accessor)
|
51
48
|
my_undef model, accessor, "#{accessor}?", "#{accessor}="
|
52
49
|
end
|
53
|
-
|
54
|
-
def validate_accessor(*names)
|
55
|
-
names.each { |acc|
|
56
|
-
raise "redefining #{acc} rejected" if model.method_defined?(acc)
|
57
|
-
}
|
58
|
-
end
|
59
|
-
|
60
|
-
def my_undef(*names)
|
61
|
-
names.each { |name|
|
62
|
-
model.class_eval %(
|
63
|
-
begin
|
64
|
-
undef #{name}
|
65
|
-
rescue
|
66
|
-
end
|
67
|
-
)
|
68
|
-
}
|
69
|
-
end
|
70
|
-
|
71
|
-
def before_save
|
72
|
-
model.class_eval %(
|
73
|
-
before_save do |row|
|
74
|
-
row.#{origin} &= ~row.class.act_with_flags.delete_mask
|
75
|
-
end
|
76
|
-
)
|
77
|
-
end
|
78
|
-
|
79
50
|
end
|
@@ -0,0 +1,67 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ActWithFlags::Admin
|
4
|
+
Location = Struct.new(:model, :origin, :position)
|
5
|
+
|
6
|
+
attr_reader :locations
|
7
|
+
|
8
|
+
def mask(*flags)
|
9
|
+
return 0 if flags.empty?
|
10
|
+
|
11
|
+
res = mask2d(*flags)
|
12
|
+
raise "Mixing origins fails: #{flags}" unless res.length == 1
|
13
|
+
|
14
|
+
res.values.first
|
15
|
+
end
|
16
|
+
|
17
|
+
def mask2d(*flags)
|
18
|
+
res = {}
|
19
|
+
flags.each { |flag|
|
20
|
+
model, orig, pos = location(flag).values
|
21
|
+
idx = "#{model}##{orig}"
|
22
|
+
mask = res[idx] || 0
|
23
|
+
res[idx] = mask | (1 << pos)
|
24
|
+
}
|
25
|
+
res
|
26
|
+
end
|
27
|
+
|
28
|
+
def location(name)
|
29
|
+
location = @locations[name]
|
30
|
+
return location if location
|
31
|
+
|
32
|
+
parent = model.superclass.act_with_flags
|
33
|
+
return parent.location(name) if parent
|
34
|
+
|
35
|
+
raise "unknown flag '#{model}##{name}'"
|
36
|
+
end
|
37
|
+
|
38
|
+
private
|
39
|
+
|
40
|
+
def position(name)
|
41
|
+
location(name).position
|
42
|
+
end
|
43
|
+
|
44
|
+
def add_to_locations(flag, location)
|
45
|
+
location = check_position(location)
|
46
|
+
who = "<#{flag}: #{location.origin}@#{location.position}>"
|
47
|
+
raise "name already used #{who}" if @locations.key?(flag)
|
48
|
+
bool = @locations.has_value?(location)
|
49
|
+
raise "position already used #{who}" if bool
|
50
|
+
@locations[flag] = location
|
51
|
+
end
|
52
|
+
|
53
|
+
def check_position(location)
|
54
|
+
model, orig, pos = location.values
|
55
|
+
return location if pos
|
56
|
+
|
57
|
+
max_position = -1
|
58
|
+
@locations.each { |name, location|
|
59
|
+
model2, orig2, pos2 = location.values
|
60
|
+
next unless model == model2 && orig == orig2
|
61
|
+
|
62
|
+
max_position = pos2 if pos2 > max_position
|
63
|
+
}
|
64
|
+
|
65
|
+
Location.new(model, orig, max_position + 1)
|
66
|
+
end
|
67
|
+
end
|
data/lib/act_with_flags/print.rb
CHANGED
@@ -1,44 +1,39 @@
|
|
1
|
-
# rubocop:disable all
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
class ActWithFlags::Admin
|
5
|
-
|
6
4
|
def to_s
|
7
5
|
res = []
|
8
|
-
res << title(
|
9
|
-
res << variables(:
|
6
|
+
res << title("Variables")
|
7
|
+
res << variables(:boolean_hash)
|
10
8
|
res << variables(:delete_mask)
|
11
9
|
|
12
|
-
res <<
|
13
|
-
|
14
|
-
|
15
|
-
res << title('Flags sorted by position')
|
16
|
-
@map.sort.sort_by(&:last).each { |key, pos|
|
17
|
-
res << "#{key} #{position(key)}"
|
10
|
+
res << blk("Flags sorted alfabetically") { |key, loc|
|
11
|
+
"#{key} #{loc}"
|
18
12
|
}
|
19
|
-
|
20
|
-
|
21
|
-
@map.sort.each { |key, pos|
|
22
|
-
res << "#{key} #{sprintf('0x%08X', mask(key))}"
|
23
|
-
}
|
24
|
-
|
25
|
-
res << title('FLAG assignment; sorted alfabetically')
|
26
|
-
@map.sort.each { |key, pos|
|
27
|
-
res << "FLAG_#{key.upcase} = #{sprintf('0x%08X', mask(key))}"
|
13
|
+
res << blk("Flags and mask; sorted alfabetically") { |key, loc|
|
14
|
+
"#{key} #{sprintf("0x%08X", mask(key))}"
|
28
15
|
}
|
29
|
-
|
30
|
-
|
31
|
-
@map.sort.sort_by(&:last).each { |key, pos|
|
32
|
-
res << "FLAG_#{key.upcase} = #{sprintf('0x%08X', mask(key))}"
|
16
|
+
res << blk("FLAG assignment; sorted alfabetically") { |key, loc|
|
17
|
+
"FLAG_#{key.upcase} = #{sprintf("0x%08X", mask(key))}"
|
33
18
|
}
|
34
19
|
|
20
|
+
res << title("@locations")
|
21
|
+
res << @locations
|
35
22
|
res.flatten.join("\n")
|
36
23
|
end
|
37
24
|
|
38
|
-
|
25
|
+
private
|
26
|
+
|
39
27
|
def title(msg)
|
40
|
-
sep =
|
41
|
-
[
|
28
|
+
sep = "#" * 10
|
29
|
+
["", "#{sep} #{msg} #{sep}"]
|
30
|
+
end
|
31
|
+
|
32
|
+
def blk(legend, &block)
|
33
|
+
res = [title(legend)]
|
34
|
+
sorted = @locations.sort
|
35
|
+
sorted.each { |key, loc| res << block.call(key, loc) }
|
36
|
+
res
|
42
37
|
end
|
43
38
|
|
44
39
|
def variables(*names)
|
@@ -47,5 +42,4 @@ class ActWithFlags::Admin
|
|
47
42
|
"#{name} #{value}"
|
48
43
|
}
|
49
44
|
end
|
50
|
-
|
51
45
|
end
|
data/lib/act_with_flags/utils.rb
CHANGED
@@ -1,16 +1,14 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ActWithFlags::Admin
|
4
|
-
|
5
|
-
def add_accessor(name, pos)
|
6
|
-
#p "** act_with_flags: add_accessor '#{name} @ #{pos}'"
|
4
|
+
def add_flag(name, origin, pos)
|
7
5
|
accessor = name.to_sym
|
8
6
|
validate_accessor accessor, "#{accessor}?", "#{accessor}="
|
9
7
|
|
10
|
-
|
8
|
+
loc = Location.new(model, origin, pos)
|
9
|
+
add_to_locations accessor, loc
|
11
10
|
mask = mask(accessor)
|
12
|
-
origin
|
13
|
-
add_accessors(origin, accessor, mask)
|
11
|
+
add_accessors(accessor, origin, mask)
|
14
12
|
end
|
15
13
|
|
16
14
|
def add_mask_et_all(origin)
|
@@ -33,19 +31,33 @@ class ActWithFlags::Admin
|
|
33
31
|
mask = self.class.act_with_flags.mask(*names)
|
34
32
|
( self.#{origin} & mask ).zero?
|
35
33
|
end
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
def delete_mask_et_all
|
40
|
-
my_undef :flags_mask, :flags_any?, :flags_all?, :flags_none?
|
34
|
+
), __FILE__, __LINE__ - 19
|
41
35
|
end
|
42
36
|
|
43
37
|
def reset
|
44
|
-
|
38
|
+
names = @locations.keys.sort
|
45
39
|
names.each { |name|
|
46
40
|
remove_accessor name
|
47
41
|
}
|
48
42
|
reset_model model
|
49
43
|
end
|
50
44
|
|
45
|
+
private
|
46
|
+
|
47
|
+
def validate_accessor(*names)
|
48
|
+
names.each { |acc|
|
49
|
+
raise "redefining #{acc} rejected" if model.method_defined?(acc)
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
def my_undef(*names)
|
54
|
+
names.each { |name|
|
55
|
+
model.class_eval %(
|
56
|
+
begin
|
57
|
+
undef #{name}
|
58
|
+
rescue
|
59
|
+
end
|
60
|
+
), __FILE__, __LINE__ - 5
|
61
|
+
}
|
62
|
+
end
|
51
63
|
end
|
@@ -1,11 +1,12 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
|
-
# rubocop: disable all
|
3
2
|
|
4
3
|
module ActWithFlags
|
5
|
-
VERSION =
|
6
|
-
# VERSION =
|
7
|
-
# VERSION =
|
8
|
-
# VERSION =
|
9
|
-
# VERSION =
|
10
|
-
# VERSION =
|
4
|
+
VERSION = "3.0.1" # 2022-08-07
|
5
|
+
# VERSION = "3.0.0" # 2022-07-27
|
6
|
+
# VERSION = "0.2.4" # 2021-06-21
|
7
|
+
# VERSION = "0.2.3" # 2020-07-14
|
8
|
+
# VERSION = "0.2.2" # 2020-04-27
|
9
|
+
# VERSION = "0.2.1" # 2020-03-01
|
10
|
+
# VERSION = "0.2.0" # 2019-10-04
|
11
|
+
# VERSION = "0.1.0" # 2019-04-07
|
11
12
|
end
|
data/lib/act_with_flags.rb
CHANGED
@@ -1,4 +1,3 @@
|
|
1
|
-
# rubocop:disable all
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
# Principles:
|
@@ -8,47 +7,37 @@
|
|
8
7
|
# POLS
|
9
8
|
# DEI
|
10
9
|
# TDD considered harmful
|
10
|
+
# TGCB
|
11
11
|
|
12
12
|
class << ActiveRecord::Base
|
13
|
-
|
14
|
-
attr_accessor :act_with_flags
|
13
|
+
attr_reader :act_with_flags
|
15
14
|
|
16
15
|
def add_to_flags(*flags, origin: :flags, **hash)
|
17
|
-
|
18
|
-
|
19
|
-
#p "act_with_flags: hash #{hash.inspect}"
|
20
|
-
|
21
|
-
@act_with_flags ||= ActWithFlags::Admin.new self
|
22
|
-
if origin.is_a?(Integer)
|
23
|
-
hash[:origin] = origin
|
24
|
-
else
|
25
|
-
@act_with_flags.origin = origin
|
26
|
-
@act_with_flags.delete_mask_et_all
|
16
|
+
unless @act_with_flags
|
17
|
+
@act_with_flags ||= ActWithFlags::Admin.new self
|
27
18
|
@act_with_flags.add_mask_et_all origin
|
28
19
|
end
|
29
20
|
|
30
|
-
flags.each { |name|
|
31
|
-
hash.each
|
21
|
+
flags.each { |name| @act_with_flags.add_flag(name, origin, nil) }
|
22
|
+
hash.each { |name, pos| @act_with_flags.add_flag(name, origin, pos) }
|
32
23
|
|
33
24
|
@act_with_flags
|
34
25
|
end
|
35
26
|
|
36
27
|
def remove_from_flags(*flags)
|
37
|
-
#p "remove_from_flags #{flags.inspect}"
|
38
28
|
flags.each { |name| @act_with_flags.remove_accessor(name) }
|
39
29
|
end
|
40
30
|
|
41
31
|
def clear_flags_at_save(*flags)
|
42
|
-
|
43
|
-
flags.each { |name| @act_with_flags.add_to_delete_mask(name) }
|
44
|
-
@act_with_flags.before_save
|
32
|
+
@act_with_flags.clear_at_save(*flags)
|
45
33
|
end
|
46
|
-
|
47
34
|
end
|
48
35
|
|
49
36
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
50
|
-
require
|
51
|
-
require
|
52
|
-
require
|
53
|
-
require
|
54
|
-
require
|
37
|
+
require "act_with_flags/version"
|
38
|
+
require "act_with_flags/utils"
|
39
|
+
require "act_with_flags/define"
|
40
|
+
require "act_with_flags/admin"
|
41
|
+
require "act_with_flags/flags"
|
42
|
+
require "act_with_flags/clear"
|
43
|
+
require "act_with_flags/print"
|
data/test/any_all_none_test.rb
CHANGED
@@ -1,8 +1,6 @@
|
|
1
|
-
|
1
|
+
require "test_helper"
|
2
2
|
|
3
|
-
|
4
|
-
|
5
|
-
describe 'any? all? and none?' do
|
3
|
+
describe "any? all? and none?" do
|
6
4
|
let(:order) { Order.create }
|
7
5
|
|
8
6
|
def setup
|
@@ -10,28 +8,28 @@ describe 'any? all? and none?' do
|
|
10
8
|
Order.add_to_flags a: 1, b: 7, c: 3
|
11
9
|
end
|
12
10
|
|
13
|
-
it
|
11
|
+
it "checks any?" do
|
14
12
|
order.a = true
|
15
13
|
assert order.flags_any?(:a, :b)
|
16
14
|
order.a = false
|
17
15
|
refute order.flags_any?(:a, :b)
|
18
16
|
end
|
19
17
|
|
20
|
-
it
|
18
|
+
it "checks any? #2" do
|
21
19
|
order.b = true
|
22
20
|
assert order.flags_any?(:a, :b)
|
23
21
|
order.b = false
|
24
22
|
refute order.flags_any?(:a, :b)
|
25
23
|
end
|
26
24
|
|
27
|
-
it
|
25
|
+
it "checks all?" do
|
28
26
|
order.a = order.b = true
|
29
27
|
assert order.flags_all?(:a, :b)
|
30
28
|
order.a = false
|
31
29
|
refute order.flags_all?(:a, :b)
|
32
30
|
end
|
33
31
|
|
34
|
-
it
|
32
|
+
it "checks none? #2" do
|
35
33
|
order.a = order.b = true
|
36
34
|
refute order.flags_none?(:a, :b)
|
37
35
|
order.a = false
|
@@ -39,5 +37,4 @@ describe 'any? all? and none?' do
|
|
39
37
|
order.b = false
|
40
38
|
assert order.flags_none?(:a, :b)
|
41
39
|
end
|
42
|
-
|
43
40
|
end
|
@@ -0,0 +1,73 @@
|
|
1
|
+
# For development purposes; do not waste your tine reading it!
|
2
|
+
# YAGNI
|
3
|
+
|
4
|
+
require "test_helper"
|
5
|
+
require "benchmark"
|
6
|
+
require "benchmark/ips"
|
7
|
+
# ENV["MORE"] = "true"
|
8
|
+
|
9
|
+
describe "Internal timings flag" do
|
10
|
+
let(:order) { Order.create }
|
11
|
+
|
12
|
+
def setup
|
13
|
+
reset_order
|
14
|
+
Order.add_to_flags :blocked
|
15
|
+
end
|
16
|
+
|
17
|
+
it "times ips" do
|
18
|
+
return unless ENV["MORE"]
|
19
|
+
|
20
|
+
Benchmark.ips do |x|
|
21
|
+
x.report("assign true : ") { order.blocked = true }
|
22
|
+
x.report("assign false: ") { order.blocked = false }
|
23
|
+
x.report("assign \"false\": ") { order.blocked = "false" }
|
24
|
+
x.report("x = order.blocked? ") { x = order.blocked? }
|
25
|
+
x.report("x = order.blocked ") { x = order.blocked }
|
26
|
+
|
27
|
+
x.compare!
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "Internal timings mask" do
|
33
|
+
let(:order) { Order.create }
|
34
|
+
let(:admin) { Order.act_with_flags }
|
35
|
+
|
36
|
+
def setup
|
37
|
+
reset_order
|
38
|
+
Order.add_to_flags a: 1, b: 7, c: 3
|
39
|
+
# Order.add_to_flags a: 1, b: 60, c: 3
|
40
|
+
# Order.add_to_flags a: 1, b: 1000, c: 3
|
41
|
+
end
|
42
|
+
|
43
|
+
it "times ips" do
|
44
|
+
return unless ENV["MORE"]
|
45
|
+
|
46
|
+
Benchmark.ips do |x|
|
47
|
+
x.report("mask(:a, :b): ") { admin.mask(:a, :b) }
|
48
|
+
x.report("any?(:a, :b): ") { order.flags_any?(:a, :b) }
|
49
|
+
x.report("all?(:a, :b): ") { order.flags_all?(:a, :b) }
|
50
|
+
x.report("none?(:a, :b): ") { order.flags_none?(:a, :b) }
|
51
|
+
|
52
|
+
x.compare!
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
class BenchFoo < Minitest::Benchmark
|
58
|
+
def bench_order_blocked
|
59
|
+
return unless ENV["MORE"]
|
60
|
+
|
61
|
+
n = 1_000_000
|
62
|
+
n = 100_000
|
63
|
+
n = 10_000
|
64
|
+
Order.add_to_flags :blocked2
|
65
|
+
order = Order.create
|
66
|
+
assert_performance_constant do |input|
|
67
|
+
n.times do
|
68
|
+
order.blocked2 = true
|
69
|
+
order.blocked2 = !order.blocked2
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/test/clear_test.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
|
-
require
|
1
|
+
require "test_helper"
|
2
2
|
|
3
|
-
describe
|
4
|
-
let(:admin) { Order.act_with_flags }
|
3
|
+
describe "Clear flags at save" do
|
5
4
|
let(:order) { Order.create }
|
6
5
|
|
7
6
|
def setup
|
@@ -10,21 +9,20 @@ describe 'Clear Flags at Save' do
|
|
10
9
|
order.a = order.b = order.c = true
|
11
10
|
end
|
12
11
|
|
13
|
-
it
|
12
|
+
it "checks sanity" do
|
14
13
|
assert_equal 0x8a, order.flags
|
15
14
|
assert order.b
|
16
15
|
end
|
17
16
|
|
18
|
-
it
|
17
|
+
it "clear flags during save" do
|
19
18
|
Order.clear_flags_at_save :b
|
20
19
|
order.save
|
21
20
|
order.reload
|
22
21
|
assert_equal 0x0a, order.flags
|
23
22
|
end
|
24
23
|
|
25
|
-
it
|
24
|
+
it "does not remove accessor" do
|
26
25
|
Order.clear_flags_at_save :b
|
27
26
|
Order.respond_to? :b
|
28
27
|
end
|
29
|
-
|
30
28
|
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe "Internal check add flag" do
|
4
|
+
let(:order) { Order.create }
|
5
|
+
|
6
|
+
def setup
|
7
|
+
reset_order
|
8
|
+
Order.add_to_flags a: 1, b: 7
|
9
|
+
end
|
10
|
+
|
11
|
+
it "skip reserved position" do
|
12
|
+
Order.add_to_flags :xx
|
13
|
+
order.xx = true
|
14
|
+
assert_equal 0x100, order.flags
|
15
|
+
|
16
|
+
Order.add_to_flags :yy
|
17
|
+
order.yy = true
|
18
|
+
assert_equal 0x300, order.flags
|
19
|
+
end
|
20
|
+
|
21
|
+
it "rejects redefinition" do
|
22
|
+
Order.add_to_flags :z
|
23
|
+
assert_raises { Order.add_to_flags :z }
|
24
|
+
end
|
25
|
+
|
26
|
+
it "rejects reuse of position" do
|
27
|
+
assert_raises { Order.add_to_flags qq: 1 }
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
describe "Coverage" do
|
4
|
+
let(:order) { Order.create }
|
5
|
+
|
6
|
+
def setup
|
7
|
+
reset_order
|
8
|
+
Order.add_to_flags a: 1, b: 7
|
9
|
+
end
|
10
|
+
|
11
|
+
it "coverage to_s" do
|
12
|
+
res = order.act_with_flags.to_s
|
13
|
+
puts res if ENV["MORE"]
|
14
|
+
end
|
15
|
+
|
16
|
+
it "coverage location raise" do
|
17
|
+
assert_raises { order.act_with_flags.location(:unknown) }
|
18
|
+
end
|
19
|
+
end
|