act_with_flags 0.2.4 → 3.1.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 +133 -105
- data/MIT-LICENSE +1 -1
- data/README.md +118 -9
- data/Rakefile +5 -5
- 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 +7 -49
- 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 +65 -0
- data/lib/act_with_flags/print.rb +23 -28
- data/lib/act_with_flags/utils.rb +41 -13
- data/lib/act_with_flags/version.rb +10 -7
- data/lib/act_with_flags.rb +63 -31
- 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/range2_test.rb +59 -0
- data/test/range3_test.rb +37 -0
- data/test/range_test.rb +89 -0
- data/test/remove_from_test.rb +3 -4
- data/test/test_helper.rb +8 -8
- metadata +23 -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/act_with_flags.gemspec
CHANGED
@@ -1,28 +1,28 @@
|
|
1
|
-
lib = File.expand_path(
|
1
|
+
lib = File.expand_path("lib", __dir__)
|
2
2
|
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
3
|
-
require
|
3
|
+
require "act_with_flags/version"
|
4
4
|
|
5
5
|
Gem::Specification.new do |s|
|
6
|
-
s.name
|
7
|
-
s.version
|
8
|
-
s.summary
|
9
|
-
s.description = %(Handles flags in a Rails model instance)
|
10
|
-
s.authors
|
11
|
-
s.email
|
12
|
-
s.homepage
|
6
|
+
s.name = "act_with_flags"
|
7
|
+
s.version = ActWithFlags::VERSION
|
8
|
+
s.summary = %(act_with_flags gem)
|
9
|
+
s.description = %(Handles flags/booleans in a Rails model instance)
|
10
|
+
s.authors = ["Dittmar Krall"]
|
11
|
+
s.email = ["dittmar.krall@matiq.com"]
|
12
|
+
s.homepage = "http://matiq.com"
|
13
13
|
|
14
|
-
s.license
|
15
|
-
s.platform
|
14
|
+
s.license = "MIT"
|
15
|
+
s.platform = Gem::Platform::RUBY
|
16
|
+
s.metadata["source_code_uri"] = "https://github.com/matique/act_with_flags"
|
16
17
|
|
17
|
-
s.files
|
18
|
-
s.
|
19
|
-
s.require_paths = ['lib']
|
18
|
+
s.files = `git ls-files -z`.split("\x0")
|
19
|
+
s.require_paths = ["lib"]
|
20
20
|
|
21
|
-
s.add_development_dependency
|
22
|
-
s.add_development_dependency
|
23
|
-
s.add_development_dependency
|
24
|
-
s.add_development_dependency
|
21
|
+
s.add_development_dependency "bundler"
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
s.add_development_dependency "appraisal"
|
24
|
+
s.add_development_dependency "combustion"
|
25
25
|
|
26
|
-
s.add_development_dependency
|
27
|
-
s.add_development_dependency
|
26
|
+
s.add_development_dependency "minitest"
|
27
|
+
s.add_development_dependency "sqlite3"
|
28
28
|
end
|
data/gemfiles/rails_6.0.gemfile
CHANGED
@@ -0,0 +1,15 @@
|
|
1
|
+
# This file was generated by Appraisal
|
2
|
+
|
3
|
+
source "https://rubygems.org"
|
4
|
+
|
5
|
+
gem "rails", "~> 7.0"
|
6
|
+
|
7
|
+
group :test do
|
8
|
+
gem "observr"
|
9
|
+
gem "rubocop", require: false
|
10
|
+
gem "simplecov", require: false
|
11
|
+
gem "benchmark-ips", require: false
|
12
|
+
gem "ricecream", require: false
|
13
|
+
end
|
14
|
+
|
15
|
+
gemspec path: "../"
|
data/lib/act_with_flags/admin.rb
CHANGED
@@ -1,68 +1,26 @@
|
|
1
|
-
# rubocop:disable all
|
2
1
|
# frozen_string_literal: true
|
3
2
|
|
4
3
|
class ActWithFlags::Admin
|
5
|
-
|
6
|
-
attr_reader :model
|
7
|
-
attr_reader :origin
|
8
|
-
attr_reader :delete_mask
|
4
|
+
attr_reader :model, :ranges
|
9
5
|
|
10
6
|
def initialize(model)
|
7
|
+
@locations = {}
|
8
|
+
@clears = {}
|
9
|
+
@ranges = {}
|
11
10
|
@model = model
|
12
|
-
@origin = :flags
|
13
|
-
@map = {}
|
14
|
-
@delete_mask = 0
|
15
|
-
@max_position = 512 - 1
|
16
11
|
@boolean_hash = {}
|
17
|
-
[true,
|
18
|
-
[false,
|
12
|
+
[true, "true", 1, "1"].each { |x| @boolean_hash[x] = true }
|
13
|
+
[false, "false", 0, "0"].each { |x| @boolean_hash[x] = false }
|
19
14
|
end
|
20
15
|
|
21
16
|
def reset_model(model)
|
22
17
|
initialize model
|
23
18
|
end
|
24
19
|
|
25
|
-
def names
|
26
|
-
@map.keys.sort
|
27
|
-
end
|
28
|
-
|
29
20
|
def to_boolean(value)
|
30
21
|
res = @boolean_hash[value]
|
31
|
-
return res
|
22
|
+
return res unless res.nil?
|
32
23
|
|
33
24
|
raise "invalid boolean <#{value}>"
|
34
25
|
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
26
|
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,65 @@
|
|
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
|
+
who = "<#{flag}: #{location.origin}@#{location.position}>"
|
46
|
+
raise "name already used #{who}" if @locations.key?(flag)
|
47
|
+
bool = @locations.has_value?(location)
|
48
|
+
raise "position already used #{who}" if bool
|
49
|
+
@locations[flag] = location
|
50
|
+
end
|
51
|
+
|
52
|
+
def check_pos(model, origin, pos)
|
53
|
+
return pos if pos
|
54
|
+
|
55
|
+
max_position = -1
|
56
|
+
@locations.each { |name, location|
|
57
|
+
model2, orig2, pos2 = location.values
|
58
|
+
next unless model == model2 && origin == orig2
|
59
|
+
|
60
|
+
max_position = pos2 if pos2 > max_position
|
61
|
+
}
|
62
|
+
|
63
|
+
max_position + 1
|
64
|
+
end
|
65
|
+
end
|
data/lib/act_with_flags/print.rb
CHANGED
@@ -1,44 +1,40 @@
|
|
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(:
|
10
|
-
res << variables(:delete_mask)
|
11
|
-
|
12
|
-
res << title('Flags sorted alfabetically')
|
13
|
-
@map.sort.each { |key, pos| res << "#{key} #{position(key)}" }
|
6
|
+
res << title("Variables")
|
7
|
+
res << variables(:boolean_hash)
|
14
8
|
|
15
|
-
res <<
|
16
|
-
|
17
|
-
res << "#{key} #{position(key)}"
|
9
|
+
res << blk("Flags sorted alfabetically") { |key, loc|
|
10
|
+
"#{key} #{loc}"
|
18
11
|
}
|
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))}"
|
12
|
+
res << blk("Flags and mask; sorted alfabetically") { |key, loc|
|
13
|
+
"#{key} #{sprintf("0x%08X", mask(key))}"
|
28
14
|
}
|
29
|
-
|
30
|
-
|
31
|
-
@map.sort.sort_by(&:last).each { |key, pos|
|
32
|
-
res << "FLAG_#{key.upcase} = #{sprintf('0x%08X', mask(key))}"
|
15
|
+
res << blk("FLAG assignment; sorted alfabetically") { |key, loc|
|
16
|
+
"FLAG_#{key.upcase} = #{sprintf("0x%08X", mask(key))}"
|
33
17
|
}
|
34
18
|
|
19
|
+
res << title("@ranges")
|
20
|
+
res << @ranges
|
21
|
+
res << title("@locations")
|
22
|
+
res << @locations
|
35
23
|
res.flatten.join("\n")
|
36
24
|
end
|
37
25
|
|
38
|
-
|
26
|
+
private
|
27
|
+
|
39
28
|
def title(msg)
|
40
|
-
sep =
|
41
|
-
[
|
29
|
+
sep = "#" * 10
|
30
|
+
["", "#{sep} #{msg} #{sep}"]
|
31
|
+
end
|
32
|
+
|
33
|
+
def blk(legend, &block)
|
34
|
+
res = [title(legend)]
|
35
|
+
sorted = @locations.sort
|
36
|
+
sorted.each { |key, loc| res << block.call(key, loc) }
|
37
|
+
res
|
42
38
|
end
|
43
39
|
|
44
40
|
def variables(*names)
|
@@ -47,5 +43,4 @@ class ActWithFlags::Admin
|
|
47
43
|
"#{name} #{value}"
|
48
44
|
}
|
49
45
|
end
|
50
|
-
|
51
46
|
end
|
data/lib/act_with_flags/utils.rb
CHANGED
@@ -1,16 +1,22 @@
|
|
1
|
-
#
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
class ActWithFlags::Admin
|
4
|
-
|
5
|
-
|
6
|
-
#p "** act_with_flags: add_accessor '#{name} @ #{pos}'"
|
4
|
+
def add_flag(name, pos, origin)
|
5
|
+
range = ranges[origin]
|
7
6
|
accessor = name.to_sym
|
8
7
|
validate_accessor accessor, "#{accessor}?", "#{accessor}="
|
9
8
|
|
10
|
-
|
9
|
+
pos = check_pos(model, origin, pos)
|
10
|
+
msg = "Invalid position <#{pos}>"
|
11
|
+
raise(ArgumentError, msg) unless pos.is_a?(Integer)
|
12
|
+
raise(ArgumentError, msg) unless pos >= 0
|
13
|
+
loc = Location.new(model, origin, pos)
|
14
|
+
add_to_locations accessor, loc
|
15
|
+
|
16
|
+
validate_position(range, pos)
|
17
|
+
|
11
18
|
mask = mask(accessor)
|
12
|
-
origin
|
13
|
-
add_accessors(origin, accessor, mask)
|
19
|
+
add_accessors(accessor, origin, mask)
|
14
20
|
end
|
15
21
|
|
16
22
|
def add_mask_et_all(origin)
|
@@ -33,19 +39,41 @@ class ActWithFlags::Admin
|
|
33
39
|
mask = self.class.act_with_flags.mask(*names)
|
34
40
|
( self.#{origin} & mask ).zero?
|
35
41
|
end
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
def delete_mask_et_all
|
40
|
-
my_undef :flags_mask, :flags_any?, :flags_all?, :flags_none?
|
42
|
+
), __FILE__, __LINE__ - 19
|
41
43
|
end
|
42
44
|
|
43
45
|
def reset
|
44
|
-
|
46
|
+
names = @locations.keys.sort
|
45
47
|
names.each { |name|
|
46
48
|
remove_accessor name
|
47
49
|
}
|
48
50
|
reset_model model
|
49
51
|
end
|
50
52
|
|
53
|
+
def validate_position(range, position)
|
54
|
+
return if range.nil?
|
55
|
+
return if range.cover?(position)
|
56
|
+
|
57
|
+
msg = "Position #{position} out of range #{range}"
|
58
|
+
raise RangeError, msg
|
59
|
+
end
|
60
|
+
|
61
|
+
private
|
62
|
+
|
63
|
+
def validate_accessor(*names)
|
64
|
+
names.each { |acc|
|
65
|
+
raise "redefining #{acc} rejected" if model.method_defined?(acc)
|
66
|
+
}
|
67
|
+
end
|
68
|
+
|
69
|
+
def my_undef(*names)
|
70
|
+
names.each { |name|
|
71
|
+
model.class_eval %(
|
72
|
+
begin
|
73
|
+
undef #{name}
|
74
|
+
rescue
|
75
|
+
end
|
76
|
+
), __FILE__, __LINE__ - 5
|
77
|
+
}
|
78
|
+
end
|
51
79
|
end
|
@@ -1,11 +1,14 @@
|
|
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.1.1" # 2022-09-01
|
5
|
+
# VERSION = "3.1.0" # 2022-08-29
|
6
|
+
# VERSION = "3.0.1" # 2022-08-07
|
7
|
+
# VERSION = "3.0.0" # 2022-07-27
|
8
|
+
# VERSION = "0.2.4" # 2021-06-21
|
9
|
+
# VERSION = "0.2.3" # 2020-07-14
|
10
|
+
# VERSION = "0.2.2" # 2020-04-27
|
11
|
+
# VERSION = "0.2.1" # 2020-03-01
|
12
|
+
# VERSION = "0.2.0" # 2019-10-04
|
13
|
+
# VERSION = "0.1.0" # 2019-04-07
|
11
14
|
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,80 @@
|
|
8
7
|
# POLS
|
9
8
|
# DEI
|
10
9
|
# TDD considered harmful
|
10
|
+
# TGCB
|
11
11
|
|
12
|
-
|
12
|
+
module ActWithFlags
|
13
|
+
module Base
|
14
|
+
attr_reader :act_with_flags
|
13
15
|
|
14
|
-
|
16
|
+
def add_to_flags(*flags, origin: :flags, range: nil, **hash)
|
17
|
+
origin = origin.to_sym
|
18
|
+
init(origin, range)
|
15
19
|
|
16
|
-
|
17
|
-
|
18
|
-
#p "act_with_flags: origin #{origin.inspect}"
|
19
|
-
#p "act_with_flags: hash #{hash.inspect}"
|
20
|
+
flags.each { |name| @act_with_flags.add_flag(name, nil, origin) }
|
21
|
+
hash.each { |name, pos| @act_with_flags.add_flag(name, pos, origin) }
|
20
22
|
|
21
|
-
|
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
|
27
|
-
@act_with_flags.add_mask_et_all origin
|
23
|
+
@act_with_flags
|
28
24
|
end
|
29
25
|
|
30
|
-
|
31
|
-
|
26
|
+
def remove_from_flags(*flags)
|
27
|
+
flags.each { |name| @act_with_flags.remove_accessor(name) }
|
28
|
+
end
|
32
29
|
|
33
|
-
|
34
|
-
|
30
|
+
def clear_flags_at_save(*flags)
|
31
|
+
@act_with_flags.clear_at_save(*flags)
|
32
|
+
end
|
35
33
|
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
34
|
+
private
|
35
|
+
|
36
|
+
def init(origin, range)
|
37
|
+
unless @act_with_flags
|
38
|
+
@act_with_flags ||= ActWithFlags::Admin.new self
|
39
|
+
@act_with_flags.add_mask_et_all origin
|
40
|
+
end
|
41
|
+
|
42
|
+
unless range.nil?
|
43
|
+
validate_range_value range.begin
|
44
|
+
validate_range_value range.end
|
45
|
+
end
|
46
|
+
|
47
|
+
rng = @act_with_flags.ranges[origin]
|
48
|
+
unless range.nil? || (range == rng)
|
49
|
+
msg = "incompatible ranges #{range} - #{rng}"
|
50
|
+
raise ArgumentError, msg unless rng.nil?
|
51
|
+
@act_with_flags.ranges[origin] = range if range
|
52
|
+
validate_previous_positions(origin, range)
|
53
|
+
end
|
54
|
+
end
|
40
55
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
56
|
+
def validate_previous_positions(origin, range)
|
57
|
+
return if range.nil?
|
58
|
+
|
59
|
+
@act_with_flags.locations.each do |name, location|
|
60
|
+
next unless location.origin == origin
|
61
|
+
|
62
|
+
@act_with_flags.validate_position(range, location.position)
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
def validate_range_value(range_value)
|
67
|
+
return if range_value.nil?
|
68
|
+
return if range_value.is_a?(Integer) && range_value >= 0
|
69
|
+
|
70
|
+
raise RangeError, "Invalid range value #{range_value}"
|
71
|
+
end
|
45
72
|
end
|
73
|
+
end
|
46
74
|
|
75
|
+
class ActiveRecord::Base
|
76
|
+
extend ActWithFlags::Base
|
47
77
|
end
|
48
78
|
|
49
79
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
|
50
|
-
require
|
51
|
-
require
|
52
|
-
require
|
53
|
-
require
|
54
|
-
require
|
80
|
+
require "act_with_flags/version"
|
81
|
+
require "act_with_flags/utils"
|
82
|
+
require "act_with_flags/define"
|
83
|
+
require "act_with_flags/admin"
|
84
|
+
require "act_with_flags/flags"
|
85
|
+
require "act_with_flags/clear"
|
86
|
+
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
|