act_with_flags 0.2.0 → 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (57) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/rake.yml +30 -0
  3. data/.ruby-gemset +1 -1
  4. data/.ruby-version +1 -1
  5. data/.watchr +27 -19
  6. data/Appraisals +12 -4
  7. data/Gemfile +7 -4
  8. data/Gemfile.lock +152 -110
  9. data/MIT-LICENSE +20 -0
  10. data/README.md +30 -4
  11. data/Rakefile +6 -7
  12. data/TODO +21 -0
  13. data/act_with_flags.gemspec +20 -21
  14. data/gemfiles/rails_6.0.gemfile +4 -1
  15. data/gemfiles/{rails_5.2.gemfile → rails_6.1.gemfile} +3 -1
  16. data/gemfiles/rails_7.0.gemfile +15 -0
  17. data/lib/act_with_flags/admin.rb +5 -48
  18. data/lib/act_with_flags/clear.rb +30 -0
  19. data/lib/act_with_flags/define.rb +6 -35
  20. data/lib/act_with_flags/flags.rb +67 -0
  21. data/lib/act_with_flags/print.rb +21 -27
  22. data/lib/act_with_flags/utils.rb +25 -13
  23. data/lib/act_with_flags/version.rb +8 -9
  24. data/lib/act_with_flags.rb +14 -25
  25. data/test/any_all_none_test.rb +6 -9
  26. data/test/benchmark_test.rb +73 -0
  27. data/test/clear_test.rb +5 -7
  28. data/test/coding_check_add_test.rb +29 -0
  29. data/test/coding_coverage_test.rb +19 -0
  30. data/test/coding_mask2d_test.rb +25 -0
  31. data/test/coding_null_test.rb +29 -0
  32. data/test/coding_one_test.rb +26 -0
  33. data/test/coding_reset_test.rb +18 -0
  34. data/test/inheritance_any_test.rb +9 -33
  35. data/test/inheritance_test.rb +7 -10
  36. data/test/internal/app/assets/config/manifest.js +1 -0
  37. data/test/internal/app/controllers/orders_controller.rb +1 -3
  38. data/test/internal/app/models/order.rb +1 -5
  39. data/test/internal/config/routes.rb +1 -1
  40. data/test/internal/db/schema.rb +6 -7
  41. data/test/legacy_test.rb +8 -9
  42. data/test/mask_test.rb +6 -7
  43. data/test/null_test.rb +3 -5
  44. data/test/one_test.rb +7 -9
  45. data/test/origin_test.rb +7 -26
  46. data/test/origins_test.rb +57 -0
  47. data/test/remove_from_test.rb +3 -4
  48. data/test/test_helper.rb +12 -9
  49. metadata +25 -57
  50. data/.rubocop.yml +0 -79
  51. data/.travis.yml +0 -21
  52. data/LICENSE +0 -21
  53. data/test/internal_benchmark_test.rb +0 -52
  54. data/test/internal_check_add_test.rb +0 -36
  55. data/test/internal_null_test.rb +0 -29
  56. data/test/internal_one_test.rb +0 -27
  57. data/test/reset_test.rb +0 -17
@@ -2,10 +2,12 @@
2
2
 
3
3
  source "https://rubygems.org"
4
4
 
5
- gem "rails", "~> 5.2.0"
5
+ gem "rails", "~> 6.0"
6
6
 
7
7
  group :test do
8
8
  gem "observr"
9
+ gem "rubocop", require: false
10
+ gem "simplecov", require: false
9
11
  gem "benchmark-ips"
10
12
  end
11
13
 
@@ -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: "../"
@@ -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, 'true', 1, '1'].each { |x| @boolean_hash[x] = true }
18
- [false, 'false', 0, '0'].each { |x| @boolean_hash[x] = 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 unless res.nil?
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}'" if #{origin}.nil?
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}'" if #{origin}.nil?
29
+ raise "Uninitialized '#{model}.#{origin}'" if #{origin}.nil?
33
30
  is_a_string = #{origin}.is_a?(String)
34
- flags = is_a_string ? self.#{origin}.to_i : self.#{origin}
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
@@ -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('Variables')
9
- res << variables(:origin, :boolean_hash)
6
+ res << title("Variables")
7
+ res << variables(:boolean_hash)
10
8
  res << variables(:delete_mask)
11
9
 
12
- res << title('Flags sorted alfabetically')
13
- @map.sort.each { |key, pos| res << "#{key} #{position(key)}" }
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
- res << title('Flags and mask; sorted alfabetically')
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
- res << title('FLAG assignment; sorted by position')
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
- private
25
+ private
26
+
39
27
  def title(msg)
40
- sep = '#' * 10
41
- ['', "#{sep} #{msg} #{sep}"]
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
@@ -1,16 +1,14 @@
1
- # rubocop: disable all
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
- add accessor, pos
8
+ loc = Location.new(model, origin, pos)
9
+ add_to_locations accessor, loc
11
10
  mask = mask(accessor)
12
- origin = self.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
- delete_mask_et_all
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,13 +1,12 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module ActWithFlags
4
- VERSION = '0.2.0' # 2019-10-04
5
- # VERSION = '0.1.0' # 2019-04-07
6
- # VERSION = '0.0.7' # 2019-03-23
7
- # VERSION = '0.0.6' # 2019-03-08
8
- # VERSION = '0.0.5' # 2019-03-05
9
- # VERSION = '0.0.4' # 2019-03-03
10
- # VERSION = '0.0.3' # 2019-03-01
11
- # VERSION = '0.0.2' # 2019-02-28
12
- # VERSION = '0.0.1' # 2019-02-24
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
13
12
  end
@@ -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
- #p "act_with_flags: add_to_flags #{flags.inspect}"
18
- #p "act_with_flags: origin #{origin.inspect}"
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| @act_with_flags.add_accessor(name, nil) }
31
- hash.each { |name, pos| @act_with_flags.add_accessor(name, pos) }
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
- #p "clear_flags_at_save #{flags.inspect}"
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 'act_with_flags/version'
51
- require 'act_with_flags/utils'
52
- require 'act_with_flags/define'
53
- require 'act_with_flags/admin'
54
- require 'act_with_flags/print'
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"
@@ -1,8 +1,6 @@
1
- # rubocop: disable all
1
+ require "test_helper"
2
2
 
3
- require 'test_helper'
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 'checks any?' do
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 'checks any? #2' do
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 'checks all?' do
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 'checks none? #2' do
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 'test_helper'
1
+ require "test_helper"
2
2
 
3
- describe 'Clear Flags at Save' do
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 'checks sanity' do
12
+ it "checks sanity" do
14
13
  assert_equal 0x8a, order.flags
15
14
  assert order.b
16
15
  end
17
16
 
18
- it 'clear flags during save' do
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 'does not remove accessor' do
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