act_with_booleans 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []