act_with_booleans 0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: cce67ecde91a5e0dd84ce1788a04b4520ea256165da7a03b3cc56187b91660bd
4
+ data.tar.gz: 26ed16a60a9992e662b9660da9809e6d29f035901d5292bceae74d8eec0a6792
5
+ SHA512:
6
+ metadata.gz: c137960e5a9f0ff722c67102a0fb8dd9105c641e68bdf9c984eb2f852955264d406cd7a582b4c85d46fbc5cb8f6af1f7b6638ba30a347f5aa3a6e51523da0ad8
7
+ data.tar.gz: 895bdd627e055424d445152b0b462a83ed55f20d7551ef802ef5debf2d32da4fbe773891f8582d13f7040eec8213e70dca0dbbe942a55ef992ab4a29e94a93e9
@@ -0,0 +1,16 @@
1
+ name: Lint
2
+ on: push
3
+ jobs:
4
+ lint:
5
+ runs-on: ubuntu-latest
6
+ steps:
7
+ - name: Checkout code
8
+ uses: actions/checkout@v2
9
+ - name: Set up Ruby
10
+ uses: ruby/setup-ruby@v1
11
+ with:
12
+ bundler-cache: true
13
+ - name: Run Standard
14
+ run: bundle exec standardrb
15
+ # - name: Run erb-lint
16
+ # run: bundle exec erblint --lint-all
@@ -0,0 +1,27 @@
1
+ # see also https://github.com/whitequark/parser/blob/master/.github/workflows/test.yml
2
+ name: Rake
3
+
4
+ on: push
5
+
6
+ jobs:
7
+ test:
8
+ strategy:
9
+ fail-fast: false
10
+ matrix:
11
+ os: [ubuntu-latest]
12
+ # Due to https://github.com/actions/runner/issues/849, we have to use quotes for '3.0'
13
+ ruby: [3.0.0, 3.1.2]
14
+ test_command: ["bundle exec rake test"]
15
+ runs-on: ${{ matrix.os }}
16
+
17
+ steps:
18
+ - uses: actions/checkout@v2
19
+ - uses: ruby/setup-ruby@v1
20
+ with:
21
+ ruby-version: ${{ matrix.ruby }}
22
+ - name: Bundle install
23
+ run: |
24
+ bundle config path /home/runner/bundle
25
+ bundle install
26
+ bundle update
27
+ - run: ${{ matrix.test_command }}
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ .bundle/
2
+ coverage/
3
+
4
+ *.gem
5
+ *.log
6
+ *.lock
data/.ruby-gemset ADDED
@@ -0,0 +1 @@
1
+ rails-7.0
data/.ruby-version ADDED
@@ -0,0 +1 @@
1
+ ruby-3.1.2
data/.watchr ADDED
@@ -0,0 +1,61 @@
1
+ TESTING = %w[test]
2
+ HH = "#" * 22 unless defined?(HH)
3
+ H = "#" * 5 unless defined?(H)
4
+
5
+ def usage
6
+ puts <<-EOS
7
+ Ctrl-\\ or ctrl-4 Running all tests
8
+ Ctrl-C Exit
9
+ EOS
10
+ end
11
+
12
+ def run(cmd)
13
+ puts "#{HH} #{Time.now} #{HH}"
14
+ puts "#{H} #{cmd}"
15
+ system "/usr/bin/time --format '#{HH} Elapsed time %E' #{cmd}"
16
+ end
17
+
18
+ def run_it(type, files)
19
+ files.split(" ").flatten.each do |file|
20
+ case type
21
+ when "test" then run %(bundle exec ruby -I test #{file})
22
+ # when 'spec'; run %(rspec -X #{file})
23
+ else; puts "#{H} unknown type: #{type}, file: #{file}"
24
+ end
25
+ end
26
+ end
27
+
28
+ def run_all_tests
29
+ puts "\n#{HH} Running all tests #{HH}\n"
30
+ TESTING.each { |dir| run "bundle exec rake #{dir}" if File.exist?(dir) }
31
+ end
32
+
33
+ def run_matching_files(base)
34
+ base = base.split("_").first
35
+ TESTING.each { |type|
36
+ files = Dir["#{type}/**/*.rb"].select { |file| file =~ /#{base}_.*\.rb/ }
37
+ run_it type, files.join(" ") unless files.empty?
38
+ }
39
+ end
40
+
41
+ TESTING.each { |type|
42
+ watch("#{type}/#{type}_helper\.rb") { run_all_tests }
43
+ watch("lib/.*\.rb") { run_all_tests }
44
+ watch("#{type}/.*/*_#{type}\.rb") { |match| run_it type, match[0] }
45
+ watch("#{type}/data/(.*)\.rb") { |match|
46
+ m1 = match[1]
47
+ run_matching_files("#{type}/#{m1}/#{m1}_#{type}.rb")
48
+ }
49
+ }
50
+
51
+ %w[rb erb haml slim].each { |type|
52
+ watch("app/.*/(.*)\.#{type}") { |match|
53
+ run_matching_files(match[1])
54
+ }
55
+ }
56
+
57
+ # Ctrl-\ or ctrl-4
58
+ Signal.trap("QUIT") { run_all_tests }
59
+ # Ctrl-C
60
+ Signal.trap("INT") { abort("Interrupted\n") }
61
+ usage
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "https://rubygems.org"
2
+ gemspec
3
+
4
+ group :test do
5
+ gem "observr"
6
+ gem "standard", require: false
7
+ gem "simplecov", require: false
8
+ gem "benchmark-ips"
9
+ end
data/MIT-LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright 2022 Dittmar Krall - www.matiq.com
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,120 @@
1
+ # ActWithFlags
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/act_with_booleans.png)](http://badge.fury.io/rb/act_with_booleans)
4
+
5
+ A Ruby gem handling booleans placed in an integer.
6
+
7
+ Defines setters and getters to access the booleans.
8
+
9
+
10
+ ## Installation
11
+
12
+ As usual:
13
+ ```ruby
14
+ # Gemfile
15
+ gem "act_with_booleans"
16
+ ```
17
+
18
+ ## Examples
19
+
20
+ ### Simple Example
21
+
22
+ ```ruby
23
+ #require "act_with_booleans"
24
+
25
+ class Foo
26
+ include ActWithBooleans
27
+ attr_accessor :booleans
28
+
29
+ add_to_booleans :x, :y
30
+ end
31
+
32
+ foo = Foo.new
33
+ foo.x # --> false
34
+ foo.x = true
35
+ foo.x # --> true
36
+ foo.x? # --> true
37
+ Foo.booleans_mask(:x, :y) # 3 (0x03)
38
+ ```
39
+
40
+ ## Example Using Position
41
+
42
+ ```ruby
43
+ class Foo
44
+ add_to_booleans z: 10
45
+ end
46
+
47
+ Foo.booleans_mask(:z) # 1024 (0x400 or 2 ** 10)
48
+ ```
49
+
50
+ ### Additional Functions
51
+
52
+ ```ruby
53
+ foo.x = true
54
+ foo.y = false
55
+ foo.booleans_any?(:x, :y) # true
56
+ foo.booleans_all?(:x, :y) # false
57
+ foo.booleans_none?(:x, :y) # false
58
+ ```
59
+
60
+ ### Using a Non Default Origin
61
+
62
+ ```ruby
63
+ #require "act_with_booleans"
64
+
65
+ class Foo
66
+ include ActWithBooleans
67
+ attr_accessor :flags
68
+
69
+ add_to_booleans :x, :y, origin: :flags
70
+ end
71
+
72
+ foo = Foo.new
73
+ foo.x # --> false
74
+ ```
75
+ ### Internals
76
+
77
+ ```ruby
78
+ Foo.act_with_booleans.size # 11
79
+ Foo.act_with_booleans.position(:y) # 1
80
+ Foo.act_with_booleans.to_s
81
+ ```
82
+
83
+ ## Rails
84
+
85
+ ActWithBooleans is PORO,
86
+ i.e. it can and, usually, will be used in Rails.
87
+
88
+ The "origin" (default :booleans) is an integer containing the booleans.
89
+
90
+ Ruby supports pretty large integers,
91
+ but your database has limitations.
92
+ Therefore, it is strongly recommended to validate accordingly
93
+ the "origin" in the model.
94
+
95
+ ## Testing
96
+
97
+ As "Best Practice" a test coverage of 100% has been achieved
98
+ (and should be kept).
99
+
100
+ GitHub workflow enable tests for several configurations.
101
+ Please, feel free to inspect the corresponding file.
102
+
103
+ ## Links
104
+
105
+ Further reading:
106
+
107
+ - [gem bitmask_attributes](https://github.com/joelmoss/bitmask_attributes)
108
+ - [gem bitfields](https://github.com/grosser/bitfields)
109
+ - [gem active_flag](https://github.com/kenn/active_flag)
110
+ - [gem has-bit-field](https://github.com/pjb3/has-bit-field)
111
+ - [gem bitfield_attribute](https://github.com/gzigzigzeo/bitfield_attribute)
112
+ - [gem bitwise](https://github.com/kenn/bitwise)
113
+
114
+
115
+ ## License MIT
116
+
117
+ Copyright (c) 2022 [Dittmar Krall](matiq UG (haftungsbeschränkt))
118
+ and is released under the MIT license:
119
+
120
+ * https://opensource.org/licenses/MIT
data/Rakefile ADDED
@@ -0,0 +1,11 @@
1
+ require "rake/testtask"
2
+
3
+ desc "Run the tests."
4
+ Rake::TestTask.new do |t|
5
+ t.libs << "lib"
6
+ t.libs << "test"
7
+ t.pattern = "test/**/*_test.rb"
8
+ t.verbose = false
9
+ end
10
+
11
+ task default: :test
@@ -0,0 +1,24 @@
1
+ lib = File.expand_path("lib", __dir__)
2
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
3
+ require "act_with_booleans/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "act_with_booleans"
7
+ s.version = ActWithBooleans::VERSION
8
+ s.summary = %(Ruby gem act_with_booleans)
9
+ s.description = %(Handles booleans packed in an integer)
10
+ s.authors = ["Dittmar Krall"]
11
+ s.email = ["dittmar.krall@matiq.com"]
12
+ s.homepage = "http://matiq.com"
13
+
14
+ s.license = "MIT"
15
+ s.platform = Gem::Platform::RUBY
16
+ s.metadata["source_code_uri"] = "https://github.com/matique/act_with_booleans"
17
+
18
+ s.files = `git ls-files -z`.split("\x0")
19
+ s.require_paths = ["lib"]
20
+
21
+ s.add_development_dependency "bundler"
22
+ s.add_development_dependency "rake"
23
+ s.add_development_dependency "minitest"
24
+ end
@@ -0,0 +1,27 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActWithBooleans::Admin
4
+ attr_reader :model
5
+ attr_accessor :origin
6
+ attr_accessor :size
7
+
8
+ def initialize(model)
9
+ @locations = {}
10
+ @model = model
11
+ @size = 0
12
+ @boolean_hash = {}
13
+ [true, "true", 1, "1"].each { |x| @boolean_hash[x] = true }
14
+ [false, "false", 0, "0"].each { |x| @boolean_hash[x] = false }
15
+ end
16
+
17
+ def reset_model(model)
18
+ initialize model
19
+ end
20
+
21
+ def to_boolean(value)
22
+ res = @boolean_hash[value]
23
+ return res unless res.nil?
24
+
25
+ raise "invalid boolean <#{value}>"
26
+ end
27
+ end
@@ -0,0 +1,29 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActWithBooleans::Admin
4
+ Location = Struct.new(:model, :origin, :position)
5
+
6
+ attr_reader :locations
7
+
8
+ def position(name)
9
+ @locations[name].position
10
+ end
11
+
12
+ private
13
+
14
+ def add_to_locations(flag, location)
15
+ who = "<#{flag}: #{location.origin}@#{location.position}>"
16
+ raise "name already used #{who}" if @locations.key?(flag)
17
+ bool = @locations.has_value?(location)
18
+ raise "position already used #{who}" if bool
19
+ @locations[flag] = location
20
+ end
21
+
22
+ def check_pos(pos)
23
+ pos ||= @size
24
+
25
+ raise "Position already in use" if pos < @size
26
+ @size = pos + 1
27
+ pos
28
+ end
29
+ end
@@ -0,0 +1,41 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActWithBooleans::Admin
4
+ def add_accessors(accessor, origin, mask)
5
+ unless model.method_defined?(:act_with_booleans)
6
+ model.class_eval %(
7
+ def act_with_booleans
8
+ #{model}.act_with_booleans
9
+ end
10
+ ), __FILE__, __LINE__ - 4
11
+ end
12
+
13
+ model.class_eval %(
14
+ def #{accessor}
15
+ #{accessor}?
16
+ end
17
+
18
+ def #{accessor}?
19
+ !( self.#{origin}.to_i & #{mask} ).zero?
20
+ end
21
+
22
+ def #{accessor}=(value)
23
+ booleans = self.#{origin}.to_i
24
+
25
+ result = self.act_with_booleans.to_boolean(value)
26
+ if result
27
+ booleans |= #{mask}
28
+ else
29
+ booleans &= ~#{mask}
30
+ end
31
+ self.#{origin} = booleans
32
+
33
+ result
34
+ end
35
+ ), __FILE__, __LINE__ - 22
36
+ end
37
+
38
+ def remove_accessors(accessor)
39
+ my_undef model, accessor, "#{accessor}?", "#{accessor}="
40
+ end
41
+ end
@@ -0,0 +1,50 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActWithBooleans::Admin
4
+ def to_s
5
+ res = []
6
+ res << title("Variables")
7
+ res << variables(:origin)
8
+ res << variables(:size)
9
+ res << variables(:boolean_hash)
10
+
11
+ res << blk("Booleans sorted alfabetically") { |key, loc|
12
+ "#{key} #{loc}"
13
+ }
14
+ res << blk("Booleans and mask; sorted alfabetically") { |key, loc|
15
+ "#{key} #{hex(model.booleans_mask(key))}"
16
+ }
17
+ res << blk("BOOLEAN assignment; sorted alfabetically") { |key, loc|
18
+ "BOOLEAN_#{key.upcase} = #{hex(model.booleans_mask(key))}"
19
+ }
20
+
21
+ res << title("@locations")
22
+ res << @locations
23
+ res.flatten.join("\n")
24
+ end
25
+
26
+ private
27
+
28
+ def title(msg)
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
38
+ end
39
+
40
+ def variables(*names)
41
+ names.collect { |name|
42
+ value = instance_variable_get(:"@#{name}")
43
+ "#{name} #{value}"
44
+ }
45
+ end
46
+
47
+ def hex(value)
48
+ sprintf("0x%08X", value)
49
+ end
50
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ class ActWithBooleans::Admin
4
+ def add_flag(name, pos)
5
+ accessor = name.to_sym
6
+ validate_accessor accessor, "#{accessor}?", "#{accessor}="
7
+
8
+ pos = check_pos(pos)
9
+ loc = Location.new(model, origin, pos)
10
+ add_to_locations accessor, loc
11
+
12
+ mask = model.booleans_mask(accessor)
13
+ add_accessors(accessor, origin, mask)
14
+ end
15
+
16
+ def add_mask_et_all(origin)
17
+ model.class_eval %(
18
+ def booleans_mask(*names)
19
+ #{model}.booleans_mask(*names)
20
+ end
21
+
22
+ def booleans_any?(*names)
23
+ mask = #{model}.booleans_mask(*names)
24
+ booleans = self.#{origin} || 0
25
+ !(booleans & mask).zero?
26
+ end
27
+
28
+ def booleans_all?(*names)
29
+ mask = #{model}.booleans_mask(*names)
30
+ booleans = self.#{origin} || 0
31
+ (booleans & mask) == mask
32
+ end
33
+
34
+ def booleans_none?(*names)
35
+ mask = #{model}.booleans_mask(*names)
36
+ booleans = self.#{origin} || 0
37
+ (booleans & mask).zero?
38
+ end
39
+ ), __FILE__, __LINE__ - 22
40
+ end
41
+
42
+ def reset
43
+ names = @locations.keys.sort
44
+ names.each { |name|
45
+ remove_accessors name
46
+ }
47
+ reset_model model
48
+ end
49
+
50
+ private
51
+
52
+ def validate_accessor(*names)
53
+ names.each { |acc|
54
+ raise "redefining #{acc} rejected" if model.method_defined?(acc)
55
+ }
56
+ end
57
+
58
+ def my_undef(*names)
59
+ names.each { |name|
60
+ model.class_eval %(
61
+ begin
62
+ undef #{name}
63
+ rescue
64
+ end
65
+ ), __FILE__, __LINE__ - 5
66
+ }
67
+ end
68
+ end
@@ -0,0 +1,6 @@
1
+ # frozen_string_literal: true
2
+
3
+ module ActWithBooleans
4
+ VERSION = "0.0.1" # 2022-09-10
5
+ # VERSION = "3.1.0" # 2022-08-29
6
+ end
@@ -0,0 +1,57 @@
1
+ # frozen_string_literal: true
2
+
3
+ # Principles:
4
+ # POLA
5
+ # KISS
6
+ # YAGNI
7
+ # POLS
8
+ # DEI
9
+ # TDD is great
10
+ # TGCB
11
+ # TIOLI
12
+ # PORO
13
+
14
+ module ActWithBooleans
15
+ def self.included(base)
16
+ base.extend(ClassMethods)
17
+ end
18
+
19
+ module ClassMethods
20
+ attr_reader :act_with_booleans
21
+
22
+ def add_to_booleans(*booleans, origin: nil, **hash)
23
+ origin = origin&.to_sym
24
+ init(origin)
25
+
26
+ booleans.each { |name| act_with_booleans.add_flag(name, nil) }
27
+ hash.each { |name, pos| act_with_booleans.add_flag(name, pos) }
28
+ end
29
+
30
+ def booleans_mask(*booleans)
31
+ booleans.inject(0) { |memo, bool|
32
+ memo | 1 << act_with_booleans.position(bool)
33
+ }
34
+ end
35
+
36
+ private
37
+
38
+ def init(origin)
39
+ unless act_with_booleans
40
+ @act_with_booleans = ActWithBooleans::Admin.new self
41
+ origin ||= :booleans
42
+ act_with_booleans.origin = origin
43
+ act_with_booleans.add_mask_et_all origin
44
+ origin = nil
45
+ end
46
+ raise "ActWithBooleans: origin already defined" if origin
47
+ end
48
+ end
49
+ end
50
+
51
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__)))
52
+ require "act_with_booleans/version"
53
+ require "act_with_booleans/utils"
54
+ require "act_with_booleans/define"
55
+ require "act_with_booleans/admin"
56
+ require "act_with_booleans/booleans"
57
+ require "act_with_booleans/print"
@@ -0,0 +1,40 @@
1
+ require "test_helper"
2
+
3
+ describe "any? all? and none?" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans a: 1, c: 3, b: 7
9
+ end
10
+
11
+ it "checks any?" do
12
+ order.a = true
13
+ assert order.booleans_any?(:a, :b)
14
+ order.a = false
15
+ refute order.booleans_any?(:a, :b)
16
+ end
17
+
18
+ it "checks any? #2" do
19
+ order.b = true
20
+ assert order.booleans_any?(:a, :b)
21
+ order.b = false
22
+ refute order.booleans_any?(:a, :b)
23
+ end
24
+
25
+ it "checks all?" do
26
+ order.a = order.b = true
27
+ assert order.booleans_all?(:a, :b)
28
+ order.a = false
29
+ refute order.booleans_all?(:a, :b)
30
+ end
31
+
32
+ it "checks none? #2" do
33
+ order.a = order.b = true
34
+ refute order.booleans_none?(:a, :b)
35
+ order.a = false
36
+ refute order.booleans_none?(:a, :b)
37
+ order.b = false
38
+ assert order.booleans_none?(:a, :b)
39
+ end
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 boolean" do
10
+ let(:order) { Order.new }
11
+
12
+ def setup
13
+ reset_order
14
+ Order.add_to_booleans :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.new }
34
+ let(:admin) { Order.act_with_booleans }
35
+
36
+ def setup
37
+ reset_order
38
+ Order.add_to_booleans a: 1, c: 3, b: 7
39
+ # Order.add_to_booleans a: 1, c: 3, b: 60
40
+ # Order.add_to_booleans a: 1, c: 3, b: 1000
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): ") { Order.booleans_mask(:a, :b) }
48
+ x.report("any?(:a, :b): ") { order.booleans_any?(:a, :b) }
49
+ x.report("all?(:a, :b): ") { order.booleans_all?(:a, :b) }
50
+ x.report("none?(:a, :b): ") { order.booleans_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_booleans :blocked2
65
+ order = Order.new
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
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ describe "Internal check add boolean" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans a: 1, b: 7
9
+ end
10
+
11
+ it "skips reserved position" do
12
+ Order.add_to_booleans :xx
13
+ order.xx = true
14
+ assert_equal 0x100, order.booleans
15
+
16
+ Order.add_to_booleans :yy
17
+ order.yy = true
18
+ assert_equal 0x300, order.booleans
19
+ end
20
+
21
+ it "rejects redefinition" do
22
+ Order.add_to_booleans :z
23
+ assert_raises { Order.add_to_booleans :z }
24
+ end
25
+
26
+ it "rejects reuse of position" do
27
+ assert_raises { Order.add_to_booleans qq: 1 }
28
+ end
29
+ end
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+
3
+ describe "Coverage" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans a: 1, b: 7
9
+ end
10
+
11
+ it "coverage to_s" do
12
+ res = order.act_with_booleans.to_s
13
+ # puts res
14
+ puts res if ENV["MORE"]
15
+ end
16
+
17
+ it "coverage position" do
18
+ assert_equal 1, order.act_with_booleans.position(:a)
19
+ assert_equal 7, Order.act_with_booleans.position(:b)
20
+ assert_equal 7, order.act_with_booleans.position(:b)
21
+ assert_raises { order.act_with_booleans.position(:unknown) }
22
+ end
23
+ end
@@ -0,0 +1,29 @@
1
+ require "test_helper"
2
+
3
+ describe "Internal Null" do
4
+ let(:admin) { Order.act_with_booleans }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans
9
+ end
10
+
11
+ it "respond to act_with_booleans" do
12
+ assert Order.respond_to?(:act_with_booleans)
13
+ refute_nil Order.act_with_booleans
14
+ end
15
+
16
+ it "tests to_boolean" do
17
+ assert admin.to_boolean(true)
18
+ assert admin.to_boolean("true")
19
+ assert admin.to_boolean(1)
20
+ assert admin.to_boolean("1")
21
+ refute admin.to_boolean(false)
22
+ refute admin.to_boolean("false")
23
+ refute admin.to_boolean(0)
24
+ refute admin.to_boolean("0")
25
+ assert_raises { admin.to_boolean(nil) }
26
+ assert_raises { admin.to_boolean(2) }
27
+ assert_raises { admin.to_boolean("unknown") }
28
+ end
29
+ end
@@ -0,0 +1,26 @@
1
+ require "test_helper"
2
+
3
+ describe "Internal One Flag" do
4
+ let(:bool) { :blocked }
5
+ let(:admin) { Order.act_with_booleans }
6
+ let(:order) { Order.new }
7
+
8
+ def setup
9
+ reset_order
10
+ Order.add_to_booleans bool
11
+ end
12
+
13
+ it "test order.act_with_booleans" do
14
+ refute_nil admin
15
+ assert_equal admin, order.class.act_with_booleans
16
+ assert_equal admin, order.act_with_booleans
17
+ assert_equal admin, Order.act_with_booleans
18
+ end
19
+
20
+ it "checks definition of methods for bool" do
21
+ msg = "method '#{bool}' not defined"
22
+ assert order.respond_to?(bool.to_s), msg
23
+ assert order.respond_to?("#{bool}?"), msg
24
+ assert order.respond_to?("#{bool}="), msg
25
+ end
26
+ end
@@ -0,0 +1,18 @@
1
+ require "test_helper"
2
+
3
+ describe "Testing reset" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans :a
9
+ end
10
+
11
+ it "reset hard" do
12
+ empty = {}
13
+ refute_equal empty, Order.act_with_booleans.locations
14
+
15
+ Order.act_with_booleans&.reset
16
+ assert_equal empty, Order.act_with_booleans.locations
17
+ end
18
+ end
@@ -0,0 +1,53 @@
1
+ require "test_helper"
2
+
3
+ class A < Order
4
+ end
5
+
6
+ class B < Order
7
+ include ActWithBooleans
8
+
9
+ add_to_booleans y: 2
10
+ end
11
+
12
+ describe "inheritance" do
13
+ let(:order) { Order.new }
14
+ let(:a) { A.new }
15
+ let(:b) { B.new }
16
+
17
+ def setup
18
+ reset_order
19
+ Order.add_to_booleans x: 1
20
+ end
21
+
22
+ it "tests Order" do
23
+ refute order.x?
24
+ order.x = true
25
+ assert order.x?
26
+ end
27
+
28
+ it "tests A" do
29
+ refute a.x?
30
+ a.x = true
31
+ assert a.x?
32
+ end
33
+
34
+ it "tests B" do
35
+ refute b.x?
36
+ b.x = true
37
+ assert b.x?
38
+
39
+ refute b.y?
40
+ b.y = true
41
+ assert b.y?
42
+
43
+ assert_raises { order.y? }
44
+ end
45
+
46
+ it "tests booleans_mask" do
47
+ assert_equal 0x02, Order.booleans_mask(:x)
48
+ assert_raises { Order.booleans_mask(:y) }
49
+ assert_raises { B.booleans_mask(:x) }
50
+ assert_equal 0x04, B.booleans_mask(:y)
51
+ assert_raises { B.booleans_mask(:x, :y) }
52
+ end
53
+ end
@@ -0,0 +1,38 @@
1
+ require "test_helper"
2
+
3
+ describe "Legacy Flag" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans a: 1, c: 3, b: 7
9
+ end
10
+
11
+ it "set true" do
12
+ test3 true, true, true
13
+ end
14
+
15
+ it "set false" do
16
+ test3 false, false, false
17
+ end
18
+
19
+ it "set mixture" do
20
+ test3 false, true, false
21
+ end
22
+
23
+ it "set mixture #2" do
24
+ test3 true, false, true
25
+ end
26
+
27
+ private
28
+
29
+ def test3(a, b, c)
30
+ order.a = a
31
+ order.b = b
32
+ order.c = c
33
+
34
+ assert_equal a, order.a
35
+ assert_equal b, order.b
36
+ assert_equal c, order.c
37
+ end
38
+ end
data/test/mask_test.rb ADDED
@@ -0,0 +1,30 @@
1
+ require "test_helper"
2
+
3
+ describe "mask" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans a: 1, c: 3, b: 7
9
+ end
10
+
11
+ it "mask empty" do
12
+ assert_equal 0x00, order.booleans_mask
13
+ assert_equal 0x00, Order.booleans_mask
14
+ end
15
+
16
+ it "mask of one boolean" do
17
+ assert_equal 0x80, order.booleans_mask(:b)
18
+ assert_equal 0x80, Order.booleans_mask(:b)
19
+ end
20
+
21
+ it "mask of several booleans" do
22
+ assert_equal 0x8a, order.booleans_mask(:a, :b, :c)
23
+ assert_equal 0x8a, Order.booleans_mask(:a, :b, :c)
24
+ end
25
+
26
+ it "order is not relevant" do
27
+ mask = order.booleans_mask(:a, :b, :c)
28
+ assert_equal mask, Order.booleans_mask(:c, :b, :a)
29
+ end
30
+ end
data/test/null_test.rb ADDED
@@ -0,0 +1,23 @@
1
+ require "test_helper"
2
+
3
+ describe "Order: just include ActWithBooleans and :booleans" do
4
+ let(:order) { Order.new }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans
9
+ end
10
+
11
+ it "respond to ActWithBooleans API" do
12
+ assert Order.respond_to?(:add_to_booleans)
13
+ assert Order.respond_to?(:act_with_booleans)
14
+ assert Order.respond_to?(:booleans_mask)
15
+ end
16
+
17
+ it "checks mask et all; no parameters" do
18
+ assert_equal 0, order.booleans_mask
19
+ refute order.booleans_any?
20
+ assert order.booleans_all?
21
+ assert order.booleans_none?
22
+ end
23
+ end
data/test/one_test.rb ADDED
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+
3
+ describe "One Flag" do
4
+ let(:bool) { :blocked }
5
+ let(:order) { Order.new }
6
+
7
+ def setup
8
+ reset_order
9
+ Order.add_to_booleans bool
10
+ end
11
+
12
+ it "checks bool default" do
13
+ refute_equal true, order.blocked
14
+ assert_equal false, order.blocked
15
+ assert_equal false, order.blocked?
16
+ end
17
+
18
+ it "set bool (:blocked)" do
19
+ order.blocked = true
20
+ assert_equal true, order.blocked
21
+ assert_equal true, order.blocked?
22
+
23
+ order.blocked = "false"
24
+ assert_equal false, order.blocked
25
+ assert_equal false, order.blocked?
26
+ end
27
+
28
+ it "rejects redefining" do
29
+ assert_raises { Order.add_to_booleans bool }
30
+ end
31
+
32
+ it "rejects redefining #2" do
33
+ Order.add_to_booleans :berta
34
+ assert_raises { Order.add_to_booleans :berta }
35
+ end
36
+ end
@@ -0,0 +1,36 @@
1
+ require "test_helper"
2
+
3
+ # class A used elsewhere => use AA
4
+ class AA
5
+ include ActWithBooleans
6
+ end
7
+
8
+ # dito
9
+ class BB
10
+ include ActWithBooleans
11
+ end
12
+
13
+ # dito
14
+ class CC
15
+ include ActWithBooleans
16
+ end
17
+
18
+ describe "Testing origin" do
19
+ it "checks default origin :booleans" do
20
+ assert_raises { AA.act_with_booleans.origin }
21
+ AA.add_to_booleans
22
+ assert_equal :booleans, AA.act_with_booleans.origin
23
+ end
24
+
25
+ it "checks origin set to :origin" do
26
+ BB.add_to_booleans origin: :origin
27
+ assert_equal :origin, BB.act_with_booleans.origin
28
+ assert_raises { BB.act_with_booleans origin: :origin2 }
29
+ end
30
+
31
+ it "rejects a second origin" do
32
+ CC.add_to_booleans
33
+ assert_equal :booleans, CC.act_with_booleans.origin
34
+ assert_raises { CC.act_with_booleans origin: :origin2 }
35
+ end
36
+ end
data/test/size_test.rb ADDED
@@ -0,0 +1,33 @@
1
+ require "test_helper"
2
+
3
+ describe "size" do
4
+ let(:admin) { Order.act_with_booleans }
5
+
6
+ def setup
7
+ reset_order
8
+ Order.add_to_booleans
9
+ end
10
+
11
+ it "checks empty booleans" do
12
+ assert_equal 0, admin.size
13
+ order = Order.new
14
+ assert_equal 0, order.act_with_booleans.size
15
+ end
16
+
17
+ it "checks one boolean" do
18
+ Order.add_to_booleans :a
19
+ assert_equal 1, admin.size
20
+ end
21
+
22
+ it "checks size using postion" do
23
+ n = 123
24
+ Order.add_to_booleans a: n
25
+ assert_equal n + 1, admin.size
26
+ end
27
+
28
+ it "trying to overwrite" do
29
+ Order.add_to_booleans :a
30
+ assert_equal 1, admin.size
31
+ assert_raises { Order.add_to_booleans b: 0 }
32
+ end
33
+ end
@@ -0,0 +1,20 @@
1
+ if ENV["COVERAGE"]
2
+ require "simplecov"
3
+ SimpleCov.start do
4
+ add_filter "/test/"
5
+ end
6
+ end
7
+
8
+ require "minitest/autorun"
9
+ require "minitest/benchmark"
10
+ require "act_with_booleans"
11
+
12
+ class Order
13
+ include ActWithBooleans
14
+
15
+ attr_accessor :booleans
16
+ end
17
+
18
+ def reset_order
19
+ Order.act_with_booleans&.reset
20
+ end
metadata ADDED
@@ -0,0 +1,119 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: act_with_booleans
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Dittmar Krall
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-09-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: minitest
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - ">="
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ description: Handles booleans packed in an integer
56
+ email:
57
+ - dittmar.krall@matiq.com
58
+ executables: []
59
+ extensions: []
60
+ extra_rdoc_files: []
61
+ files:
62
+ - ".github/workflows/lint.yml"
63
+ - ".github/workflows/rake.yml"
64
+ - ".gitignore"
65
+ - ".ruby-gemset"
66
+ - ".ruby-version"
67
+ - ".watchr"
68
+ - Gemfile
69
+ - MIT-LICENSE
70
+ - README.md
71
+ - Rakefile
72
+ - act_with_booleans.gemspec
73
+ - lib/act_with_booleans.rb
74
+ - lib/act_with_booleans/admin.rb
75
+ - lib/act_with_booleans/booleans.rb
76
+ - lib/act_with_booleans/define.rb
77
+ - lib/act_with_booleans/print.rb
78
+ - lib/act_with_booleans/utils.rb
79
+ - lib/act_with_booleans/version.rb
80
+ - test/any_all_none_test.rb
81
+ - test/benchmark_test.rb
82
+ - test/coding_check_add_test.rb
83
+ - test/coding_coverage_test.rb
84
+ - test/coding_null_test.rb
85
+ - test/coding_one_test.rb
86
+ - test/coding_reset_test.rb
87
+ - test/inheritance_test.rb
88
+ - test/legacy_test.rb
89
+ - test/mask_test.rb
90
+ - test/null_test.rb
91
+ - test/one_test.rb
92
+ - test/origin_test.rb
93
+ - test/size_test.rb
94
+ - test/test_helper.rb
95
+ homepage: http://matiq.com
96
+ licenses:
97
+ - MIT
98
+ metadata:
99
+ source_code_uri: https://github.com/matique/act_with_booleans
100
+ post_install_message:
101
+ rdoc_options: []
102
+ require_paths:
103
+ - lib
104
+ required_ruby_version: !ruby/object:Gem::Requirement
105
+ requirements:
106
+ - - ">="
107
+ - !ruby/object:Gem::Version
108
+ version: '0'
109
+ required_rubygems_version: !ruby/object:Gem::Requirement
110
+ requirements:
111
+ - - ">="
112
+ - !ruby/object:Gem::Version
113
+ version: '0'
114
+ requirements: []
115
+ rubygems_version: 3.3.7
116
+ signing_key:
117
+ specification_version: 4
118
+ summary: Ruby gem act_with_booleans
119
+ test_files: []