bitwise_attribute 0.2.2 → 0.3.4

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 728afc2714df27029947e0f98b2c542ad8835bf44e052f720c588d22f2bcb821
4
- data.tar.gz: 5e8fe818d69624b1888f954416a15f9cf938039067a5f67fea12eef73bf76e31
3
+ metadata.gz: a19184eaf7a73f44c929b1aa3cb0794d2d4be1f54a5c15802e1cd1eb0edf1641
4
+ data.tar.gz: 03edbbb6992ec20733a349a7eefc7b776a4fa91c74e1373222b8949298bbc07f
5
5
  SHA512:
6
- metadata.gz: 257fb003a2eb0421a5ca03b5b6cd32a2b4317c7172cb26a204e2516bc9b7aeb07989a99867bb5f33bbb6ccc6667f7bd88d5e1c116b18f6d782eee9dd469c5ece
7
- data.tar.gz: 58b7153d9e3b51898d387252a1a91ed6f1514c778eff46f1941ed78cb4ff88b9d933131e493b4dbb184aaa27720d430335df741ba9a5ea103a66305b15d73a8e
6
+ metadata.gz: 9159f1439b717c6f4954ed5582d8811d4da7b37b3375ca1cfe4899760d94e5ca189f889180a5465a4b2dc18f7073aed55cfafb852acfce6c93d628088729c784
7
+ data.tar.gz: 2a2c1f64d74e7184c23d403f48b76566e34db91b2d1e081c70effad74394d4fb7e328c058cdadf6ec4945f4180ce6bedf7c2d2ffcabec69ef2890aee3b28ff10
@@ -0,0 +1,41 @@
1
+
2
+ name: CI
3
+
4
+ on: [push, pull_request]
5
+
6
+ jobs:
7
+ lint:
8
+ runs-on: ubuntu-latest
9
+ steps:
10
+ - uses: actions/checkout@v2
11
+ - uses: ruby/setup-ruby@v1
12
+ with:
13
+ ruby-version: "2.5"
14
+ bundler-cache: true
15
+ - name: rubocop version
16
+ timeout-minutes: 1
17
+ run: bundle exec rubocop --version
18
+ - name: rubocop
19
+ timeout-minutes: 5
20
+ run: bundle exec rubocop -c .rubocop.yml
21
+
22
+ test:
23
+ runs-on: ubuntu-latest
24
+ continue-on-error: ${{ matrix.experimental }}
25
+ strategy:
26
+ fail-fast: false
27
+ matrix:
28
+ ruby: ["2.5", "2.6", "2.7", "3.0"]
29
+ experimental: [false]
30
+ include:
31
+ - ruby: "truffleruby"
32
+ experimental: true
33
+ steps:
34
+ - uses: actions/checkout@v2
35
+ - uses: ruby/setup-ruby@v1
36
+ with:
37
+ ruby-version: ${{matrix.ruby}}
38
+ bundler-cache: true
39
+ - name: Run tests
40
+ timeout-minutes: 5
41
+ run: ${{matrix.env}} bundle exec rspec
data/.rspec CHANGED
@@ -1,4 +1,4 @@
1
1
  --format documentation
2
2
  --color
3
3
  --require spec_helper
4
- --order random
4
+ --order rand
data/.rubocop.yml CHANGED
@@ -1,21 +1,34 @@
1
- Metrics/AbcSize:
2
- Max: 30
1
+ require:
2
+ - rubocop-rake
3
+ - rubocop-rspec
4
+
5
+ AllCops:
6
+ NewCops: enable
7
+ TargetRubyVersion: 2.5
8
+
9
+ RSpec/MultipleMemoizedHelpers:
10
+ Max: 10
3
11
 
4
12
  Style/Documentation:
5
- Exclude:
6
- - 'spec/**/*'
7
- - 'test/**/*'
8
- - 'lib/bitwise_attribute.rb'
9
- - 'lib/bitwise_attribute/values_list.rb'
13
+ Enabled: false
10
14
 
11
- Metrics/LineLength:
15
+ Layout/LineLength:
12
16
  Max: 100
13
17
 
18
+ Metrics/CyclomaticComplexity:
19
+ Max: 15
20
+
21
+ Metrics/PerceivedComplexity:
22
+ Max: 15
23
+
14
24
  Metrics/MethodLength:
15
- Max: 30
25
+ Max: 50
16
26
 
17
27
  Metrics/BlockLength:
18
28
  Max: 150
19
29
 
20
30
  Metrics/ModuleLength:
21
31
  Max: 200
32
+
33
+ Metrics/AbcSize:
34
+ Max: 70
data/.ruby-version CHANGED
@@ -1 +1 @@
1
- 2.5.0
1
+ 2.7.2
data/Gemfile.lock CHANGED
@@ -1,82 +1,111 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- bitwise_attribute (0.2.2)
5
- activesupport (~> 5.1.5)
4
+ bitwise_attribute (0.3.4)
6
5
 
7
6
  GEM
8
7
  remote: https://rubygems.org/
9
8
  specs:
10
- activesupport (5.1.5)
9
+ activemodel (6.1.3.2)
10
+ activesupport (= 6.1.3.2)
11
+ activerecord (6.1.3.2)
12
+ activemodel (= 6.1.3.2)
13
+ activesupport (= 6.1.3.2)
14
+ activesupport (6.1.3.2)
11
15
  concurrent-ruby (~> 1.0, >= 1.0.2)
12
- i18n (~> 0.7)
13
- minitest (~> 5.1)
14
- tzinfo (~> 1.1)
15
- ast (2.4.0)
16
- byebug (10.0.1)
17
- coderay (1.1.2)
18
- concurrent-ruby (1.0.5)
19
- diff-lcs (1.3)
20
- docile (1.1.5)
21
- i18n (0.9.5)
16
+ i18n (>= 1.6, < 2)
17
+ minitest (>= 5.1)
18
+ tzinfo (~> 2.0)
19
+ zeitwerk (~> 2.3)
20
+ ast (2.4.2)
21
+ byebug (11.1.3)
22
+ coderay (1.1.3)
23
+ concurrent-ruby (1.1.8)
24
+ diff-lcs (1.4.4)
25
+ docile (1.4.0)
26
+ ffi (1.15.1-java)
27
+ i18n (1.8.10)
22
28
  concurrent-ruby (~> 1.0)
23
- json (2.1.0)
24
- method_source (0.9.0)
25
- minitest (5.11.3)
26
- parallel (1.12.1)
27
- parser (2.5.0.5)
28
- ast (~> 2.4.0)
29
- powerpack (0.1.1)
30
- pry (0.11.3)
31
- coderay (~> 1.1.0)
32
- method_source (~> 0.9.0)
33
- pry-byebug (3.6.0)
34
- byebug (~> 10.0)
35
- pry (~> 0.10)
29
+ method_source (1.0.0)
30
+ minitest (5.14.4)
31
+ parallel (1.20.1)
32
+ parser (3.0.1.1)
33
+ ast (~> 2.4.1)
34
+ pry (0.13.1)
35
+ coderay (~> 1.1)
36
+ method_source (~> 1.0)
37
+ pry (0.13.1-java)
38
+ coderay (~> 1.1)
39
+ method_source (~> 1.0)
40
+ spoon (~> 0.0)
41
+ pry-byebug (3.9.0)
42
+ byebug (~> 11.0)
43
+ pry (~> 0.13.0)
36
44
  rainbow (3.0.0)
37
- rake (10.5.0)
38
- rspec (3.7.0)
39
- rspec-core (~> 3.7.0)
40
- rspec-expectations (~> 3.7.0)
41
- rspec-mocks (~> 3.7.0)
42
- rspec-core (3.7.1)
43
- rspec-support (~> 3.7.0)
44
- rspec-expectations (3.7.0)
45
+ rake (13.0.3)
46
+ regexp_parser (2.1.1)
47
+ rexml (3.2.5)
48
+ rspec (3.10.0)
49
+ rspec-core (~> 3.10.0)
50
+ rspec-expectations (~> 3.10.0)
51
+ rspec-mocks (~> 3.10.0)
52
+ rspec-core (3.10.1)
53
+ rspec-support (~> 3.10.0)
54
+ rspec-expectations (3.10.1)
45
55
  diff-lcs (>= 1.2.0, < 2.0)
46
- rspec-support (~> 3.7.0)
47
- rspec-mocks (3.7.0)
56
+ rspec-support (~> 3.10.0)
57
+ rspec-mocks (3.10.2)
48
58
  diff-lcs (>= 1.2.0, < 2.0)
49
- rspec-support (~> 3.7.0)
50
- rspec-support (3.7.1)
51
- rubocop (0.54.0)
59
+ rspec-support (~> 3.10.0)
60
+ rspec-support (3.10.2)
61
+ rubocop (1.15.0)
52
62
  parallel (~> 1.10)
53
- parser (>= 2.5)
54
- powerpack (~> 0.1)
63
+ parser (>= 3.0.0.0)
55
64
  rainbow (>= 2.2.2, < 4.0)
65
+ regexp_parser (>= 1.8, < 3.0)
66
+ rexml
67
+ rubocop-ast (>= 1.5.0, < 2.0)
56
68
  ruby-progressbar (~> 1.7)
57
- unicode-display_width (~> 1.0, >= 1.0.1)
58
- ruby-progressbar (1.9.0)
59
- simplecov (0.15.1)
60
- docile (~> 1.1.0)
61
- json (>= 1.8, < 3)
62
- simplecov-html (~> 0.10.0)
63
- simplecov-html (0.10.2)
64
- thread_safe (0.3.6)
65
- tzinfo (1.2.5)
66
- thread_safe (~> 0.1)
67
- unicode-display_width (1.3.0)
69
+ unicode-display_width (>= 1.4.0, < 3.0)
70
+ rubocop-ast (1.7.0)
71
+ parser (>= 3.0.1.1)
72
+ rubocop-rake (0.5.1)
73
+ rubocop
74
+ rubocop-rspec (2.3.0)
75
+ rubocop (~> 1.0)
76
+ rubocop-ast (>= 1.1.0)
77
+ ruby-progressbar (1.11.0)
78
+ simplecov (0.21.2)
79
+ docile (~> 1.1)
80
+ simplecov-html (~> 0.11)
81
+ simplecov_json_formatter (~> 0.1)
82
+ simplecov-html (0.12.3)
83
+ simplecov_json_formatter (0.1.3)
84
+ spoon (0.0.6)
85
+ ffi
86
+ sqlite3 (1.4.2)
87
+ tzinfo (2.0.4)
88
+ concurrent-ruby (~> 1.0)
89
+ unicode-display_width (2.0.0)
90
+ zeitwerk (2.4.2)
68
91
 
69
92
  PLATFORMS
70
- ruby
93
+ universal-java-11
94
+ x86_64-darwin-19
95
+ x86_64-linux
71
96
 
72
97
  DEPENDENCIES
98
+ activerecord (>= 3)
73
99
  bitwise_attribute!
74
- bundler (~> 1.16)
100
+ bundler
75
101
  pry-byebug
76
- rake (~> 10.0)
77
- rspec (~> 3.0)
78
- rubocop (~> 0.54.0)
79
- simplecov (~> 0.15.1)
102
+ rake
103
+ rspec
104
+ rubocop
105
+ rubocop-rake
106
+ rubocop-rspec
107
+ simplecov
108
+ sqlite3
80
109
 
81
110
  BUNDLED WITH
82
- 1.16.1
111
+ 2.2.16
data/README.md CHANGED
@@ -1,7 +1,7 @@
1
- [![Dependency Status](https://gemnasium.com/rikas/bitwise_attribute.svg)](https://gemnasium.com/rikas/bitwise_attribute)
2
- [![Build Status](https://travis-ci.org/rikas/bitwise_attribute.svg?branch=master)](https://travis-ci.org/rikas/bitwise_attribute)
3
-
4
1
  # BitwiseAttribute
2
+ Manipulation of bitmask attributes in your classes (typically ActiveRecord models). You can have multiple values mapped to the same column — for example when you need a User with multiple roles.
3
+
4
+ It adds a lot of helper methods so you don't have to deal with the underlying mask.
5
5
 
6
6
  ## Installation
7
7
 
@@ -24,6 +24,10 @@ Or install it yourself as:
24
24
  Include `BitwiseAttribute` and then define your attribute with `attr_bitwise`. By default it will
25
25
  use the singularized name with `_mask`.
26
26
 
27
+ Check the example below to see how to use the helpers and methods created automatically in your classes.
28
+
29
+ ## Examples
30
+
27
31
  For the `roles` attribute you need to have `role_mask` column in your model, so add the migration:
28
32
 
29
33
  ```ruby
@@ -38,18 +42,92 @@ end
38
42
  class User < ActiveRecord::Base
39
43
  include BitwiseAttribute
40
44
 
45
+ # This line will do all the magic!
46
+ #
47
+ # By default we assume that your column will be called `role_mask`.
48
+ # You can send the `column_name` option if your column has another name.
49
+ #
41
50
  attr_bitwise :roles, values: %i[user moderator admin]
42
51
  end
43
52
  ```
44
53
 
45
- You can then use
54
+ ### Instance manipulation
55
+
56
+ You can then access the `roles` field without having to know the underlying value of `role_mask`.
57
+
58
+ ```ruby
59
+ user = User.new(roles: [:user, :admin])
60
+
61
+ user.roles
62
+ #=> [:user, :admin]
63
+
64
+ user.role_mask
65
+ #=> 5
66
+
67
+ user.roles << :moderator
68
+ user.roles
69
+ #=> [:user, :admin, :moderator]
70
+ ```
71
+
72
+ You can see if a particular record has a given value:
73
+
74
+ ```ruby
75
+ user.admin?
76
+ #=> true
77
+ ```
78
+
79
+ ### Class methods
80
+
81
+ You can get all available values and correspondent mask value:
82
+
83
+ ```ruby
84
+ User.roles
85
+ #=> { :user => 1, :moderator => 2, :admin => 4 }
86
+ ```
87
+
88
+ So if you need all the keys just use:
89
+
90
+ ```ruby
91
+ User.roles.keys
92
+ #=> [:user, :moderator, :admin]
93
+ ```
94
+
95
+ ### ActiveRecord named scopes
96
+
97
+ BitwiseAttribte will add some methods for easier queries on the database:
98
+
99
+ ```ruby
100
+ User.with_roles
101
+ #=> Users that have at least one role
102
+
103
+ User.with_roles(:admin)
104
+ #=> Users that have the :admin role
105
+
106
+ User.with_roles(:admin, :moderator)
107
+ #=> Users that have the admin role AND the moderator role
108
+
109
+ User.with_any_roles(:admin, :moderator)
110
+ #=> Users that have the admin role OR the moderator role
111
+
112
+ User.with_exact_roles(:moderator)
113
+ #=> Users that have ONLY the moderator role
114
+
115
+ User.with_exact_roles(:moderator, :admin)
116
+ #=> Users that have ONLY the moderator AND admin roles
117
+
118
+ User.without_roles(:admin)
119
+ #=> Users without the admin role
120
+
121
+ User.without_roles(:admin, :moderator)
122
+ #=> Users without the admin role AND without the moderator role
123
+ ```
124
+
125
+ These are the same as using `with_roles`:
46
126
 
47
127
  ```ruby
48
- user = User.first
49
- user.roles #=> []
50
- user.roles = [:user, :admin] #=> [:user, :admin]
51
- user.save
52
- user.role_mask #=> 5
128
+ User.admin
129
+ User.user
130
+ User.admin.moderator
53
131
  ```
54
132
 
55
133
  ## Development
data/bin/console CHANGED
@@ -1,7 +1,7 @@
1
- # frozen_string_literal: true
2
-
3
1
  #!/usr/bin/env ruby
4
2
 
3
+ # frozen_string_literal: true
4
+
5
5
  require 'bundler/setup'
6
6
  require 'bitwise_attribute'
7
7
 
@@ -7,6 +7,7 @@ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
7
7
  require 'bitwise_attribute/version'
8
8
 
9
9
  Gem::Specification.new do |spec|
10
+ spec.required_ruby_version = '>= 2.5.0'
10
11
  spec.name = 'bitwise_attribute'
11
12
  spec.version = BitwiseAttribute::VERSION
12
13
  spec.authors = ['Ricardo Otero']
@@ -24,12 +25,14 @@ Gem::Specification.new do |spec|
24
25
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
25
26
  spec.require_paths = %w[lib]
26
27
 
27
- spec.add_dependency 'activesupport', '~> 5.1.5'
28
-
29
- spec.add_development_dependency 'bundler', '~> 1.16'
28
+ spec.add_development_dependency 'activerecord', '>= 3'
29
+ spec.add_development_dependency 'bundler'
30
30
  spec.add_development_dependency 'pry-byebug'
31
- spec.add_development_dependency 'rake', '~> 10.0'
32
- spec.add_development_dependency 'rspec', '~> 3.0'
33
- spec.add_development_dependency 'rubocop', '~> 0.54.0'
34
- spec.add_development_dependency 'simplecov', '~> 0.15.1'
31
+ spec.add_development_dependency 'rake'
32
+ spec.add_development_dependency 'rspec'
33
+ spec.add_development_dependency 'rubocop'
34
+ spec.add_development_dependency 'rubocop-rake'
35
+ spec.add_development_dependency 'rubocop-rspec'
36
+ spec.add_development_dependency 'simplecov'
37
+ spec.add_development_dependency 'sqlite3'
35
38
  end
@@ -3,52 +3,39 @@
3
3
  require 'active_support'
4
4
  require 'active_support/concern'
5
5
  require 'active_support/core_ext'
6
+
6
7
  require 'bitwise_attribute/version'
7
8
  require 'bitwise_attribute/values_list'
9
+ require 'bitwise_attribute/active_record_methods'
8
10
 
9
11
  module BitwiseAttribute
10
- extend ActiveSupport::Concern
12
+ def self.included(base)
13
+ base.extend ClassMethods
14
+ end
11
15
 
12
- class_methods do
13
- def attr_bitwise(name, column_name: nil, values:)
14
- column_name ||= "#{name.to_s.singularize}_mask"
16
+ module ClassMethods
17
+ include BitwiseAttribute::ActiveRecordMethods
15
18
 
16
- # Check if the values is an array or hash with valid values. Raise ArgumentError otherwise.
17
- validate_values!(values)
19
+ def attr_bitwise(name, values:, column_name: nil)
20
+ column_name ||= "#{name.to_s.singularize}_mask"
18
21
 
19
22
  mapping = build_mapping(values)
20
23
 
21
- @mapping ||= {}
22
- @mapping[name] = mapping
23
-
24
24
  define_class_methods(name, column_name, mapping)
25
- define_instante_methods(name, column_name, mapping)
25
+ define_instance_methods(name, column_name, mapping)
26
26
  end
27
27
 
28
+ private
29
+
28
30
  def define_class_methods(name, column_name, mapping)
29
- # Class methods
30
31
  define_singleton_method(name) do
31
32
  mapping
32
33
  end
33
34
 
34
- define_singleton_method("with_#{name}") do |*keys|
35
- where(column_name => bitwise_union(keys, name))
36
- end
37
-
38
- define_singleton_method("with_all_#{name}") do |*keys|
39
- where(column_name => bitwise_intersection(keys, name))
40
- end
41
-
42
- # Defines a class method for each key of the mapping, returning records that have *at least*
43
- # the corresponding value.
44
- mapping.keys.each do |key|
45
- define_singleton_method(key) do
46
- send("with_#{key}")
47
- end
48
- end
35
+ define_named_scopes(name, column_name, mapping) if defined?(ActiveRecord)
49
36
  end
50
37
 
51
- def define_instante_methods(name, column_name, mapping)
38
+ def define_instance_methods(name, column_name, mapping)
52
39
  define_method(name) do
53
40
  roles = value_getter(column_name, mapping)
54
41
 
@@ -61,7 +48,7 @@ module BitwiseAttribute
61
48
  end
62
49
 
63
50
  # Adds a boolean method for each key (ex: admin?)
64
- mapping.keys.each do |key|
51
+ mapping.each_key do |key|
65
52
  define_method("#{key}?") do
66
53
  value?(column_name, mapping[key])
67
54
  end
@@ -72,64 +59,8 @@ module BitwiseAttribute
72
59
  # Each sym get a power of 2 value
73
60
  def build_mapping(values)
74
61
  {}.tap do |hash|
75
- if values.is_a?(Hash)
76
- hash.merge!(values.sort_by { |_, value| value }.to_h)
77
- else
78
- values.each_with_index { |key, index| hash[key] = 2**index }
79
- end
80
- end
81
- end
82
-
83
- # Validates the numeric values for each key. If it's not a power of 2 then raise ArgumentError.
84
- def validate_values!(values)
85
- return true if values.is_a?(Array)
86
-
87
- values.reject { |_, value| (Math.log2(value) % 1.0).zero? }.tap do |invalid_options|
88
- if invalid_options.any?
89
- raise(ArgumentError, "Values should be a power of 2 (#{invalid_options})")
90
- end
91
- end
92
- end
93
-
94
- def mapping_for_name(name)
95
- @mapping[name.to_sym]
96
- end
97
-
98
- def values_for_column(name)
99
- mapping_for_name(name).values
100
- end
101
-
102
- def map_to_values(name, keys)
103
- mapping = mapping_for_name(name)
104
-
105
- keys.map { |key| mapping[key.to_sym] }.compact
106
- end
107
-
108
- def bitwise_union(keys, name)
109
- mask = []
110
-
111
- mapped = map_to_values(name, keys)
112
-
113
- mapped.each do |mv|
114
- values_for_column(name).each do |value|
115
- mask << (mv | value)
116
- end
62
+ values.each_with_index { |key, index| hash[key] = (0b1 << index) }
117
63
  end
118
-
119
- mask.uniq
120
- end
121
-
122
- def bitwise_intersection(keys, name)
123
- mask = []
124
-
125
- mapped = map_to_values(name, keys)
126
- mapped = mapped.reduce(&:|)
127
-
128
- values_for_column(name).each do |value|
129
- mask << (value | mapped)
130
- end
131
-
132
- mask.uniq
133
64
  end
134
65
  end
135
66
 
@@ -147,19 +78,15 @@ module BitwiseAttribute
147
78
  def value_setter(mask_column, values, mapping)
148
79
  send("#{mask_column}=", 0)
149
80
 
150
- values.each do |value|
151
- raise(ArgumentError, "Unknown value #{value}!") unless mapping[value]
81
+ values = values.map(&:to_sym).compact.uniq
152
82
 
153
- add_value(mask_column, mapping[value])
154
- end
83
+ values &= mapping.keys
84
+
85
+ values.each { |value| send("#{mask_column}=", send(mask_column) | mapping[value]) }
155
86
  end
156
87
 
157
- # Return if value presents in mask (raw value)
88
+ # Return if value is present in mask (raw value)
158
89
  def value?(mask_column, val)
159
90
  send(mask_column) & val != 0
160
91
  end
161
-
162
- def add_value(mask_column, val)
163
- send("#{mask_column}=", send(mask_column) | val)
164
- end
165
92
  end
@@ -0,0 +1,79 @@
1
+ # frozen_string_literal: true
2
+
3
+ module BitwiseAttribute
4
+ module ActiveRecordMethods
5
+ def define_named_scopes(name, column_name, mapping)
6
+ define_singleton_method("with_#{name}") do |*keys|
7
+ keys = cleanup_keys(keys, mapping)
8
+
9
+ return [] unless keys&.any?
10
+
11
+ records = where("#{column_name} & #{mapping[keys.first]} = #{mapping[keys.first]}")
12
+
13
+ keys[1..-1].each do |key|
14
+ records = records.where("#{column_name} & #{mapping[key]} = #{mapping[key]}")
15
+ end
16
+
17
+ records
18
+ end
19
+
20
+ define_singleton_method("with_any_#{name}") do |*keys|
21
+ keys = cleanup_keys(keys, mapping)
22
+
23
+ return where.not(column_name => nil) unless keys&.any?
24
+
25
+ records = where("#{column_name} & #{mapping[keys.first]} = #{mapping[keys.first]}")
26
+
27
+ keys[1..-1].each do |key|
28
+ records = records.or(where("#{column_name} & #{mapping[key]} = #{mapping[key]}"))
29
+ end
30
+
31
+ records
32
+ end
33
+
34
+ define_singleton_method("with_exact_#{name}") do |*keys|
35
+ keys = cleanup_keys(keys, mapping)
36
+
37
+ return [] unless keys&.any?
38
+
39
+ records = send("with_#{name}", keys)
40
+
41
+ (mapping.keys - keys).each do |key|
42
+ records = records.where("#{column_name} & #{mapping[key]} != #{mapping[key]}")
43
+ end
44
+
45
+ records
46
+ end
47
+
48
+ define_singleton_method("without_#{name}") do |*keys|
49
+ keys = cleanup_keys(keys, mapping)
50
+
51
+ return where(column_name => nil).or(where(column_name => 0)) unless keys&.any?
52
+
53
+ records = where("#{column_name} & #{mapping[keys.first]} != #{mapping[keys.first]}")
54
+
55
+ keys[1..-1].each do |key|
56
+ records = records.where("#{column_name} & #{mapping[key]} != #{mapping[key]}")
57
+ end
58
+
59
+ records
60
+ end
61
+
62
+ # Defines a class method for each key of the mapping, returning records that have *at least*
63
+ # the corresponding value.
64
+ mapping.each_key do |key|
65
+ define_singleton_method(key) do
66
+ send("with_#{name}", key)
67
+ end
68
+ end
69
+ end
70
+
71
+ def cleanup_keys(keys, mapping)
72
+ return [] unless keys
73
+
74
+ clean = keys.flatten.map(&:to_sym).compact.uniq
75
+
76
+ clean & mapping.keys # only roles that we know about
77
+ end
78
+ end
79
+ end
@@ -3,10 +3,10 @@
3
3
  module BitwiseAttribute
4
4
  class ValuesList < Array
5
5
  def initialize(field, record, values)
6
+ super(concat(values))
7
+
6
8
  @field = field
7
9
  @record = record
8
-
9
- concat(values)
10
10
  end
11
11
 
12
12
  def <<(value)
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module BitwiseAttribute
4
- VERSION = '0.2.2'
4
+ VERSION = '0.3.4'
5
5
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: bitwise_attribute
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.2
4
+ version: 0.3.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Ricardo Otero
8
- autorequire:
8
+ autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2018-03-28 00:00:00.000000000 Z
11
+ date: 2021-05-29 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activesupport
14
+ name: activerecord
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 5.1.5
20
- type: :runtime
19
+ version: '3'
20
+ type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - "~>"
24
+ - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 5.1.5
26
+ version: '3'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: bundler
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">="
32
32
  - !ruby/object:Gem::Version
33
- version: '1.16'
33
+ version: '0'
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">="
39
39
  - !ruby/object:Gem::Version
40
- version: '1.16'
40
+ version: '0'
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: pry-byebug
43
43
  requirement: !ruby/object:Gem::Requirement
@@ -56,58 +56,100 @@ dependencies:
56
56
  name: rake
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - "~>"
59
+ - - ">="
60
60
  - !ruby/object:Gem::Version
61
- version: '10.0'
61
+ version: '0'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - "~>"
66
+ - - ">="
67
67
  - !ruby/object:Gem::Version
68
- version: '10.0'
68
+ version: '0'
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: rspec
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '3.0'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '3.0'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: rubocop
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: rubocop-rake
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
88
102
  - !ruby/object:Gem::Version
89
- version: 0.54.0
103
+ version: '0'
90
104
  type: :development
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - "~>"
108
+ - - ">="
95
109
  - !ruby/object:Gem::Version
96
- version: 0.54.0
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: rubocop-rspec
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
97
125
  - !ruby/object:Gem::Dependency
98
126
  name: simplecov
99
127
  requirement: !ruby/object:Gem::Requirement
100
128
  requirements:
101
- - - "~>"
129
+ - - ">="
102
130
  - !ruby/object:Gem::Version
103
- version: 0.15.1
131
+ version: '0'
104
132
  type: :development
105
133
  prerelease: false
106
134
  version_requirements: !ruby/object:Gem::Requirement
107
135
  requirements:
108
- - - "~>"
136
+ - - ">="
109
137
  - !ruby/object:Gem::Version
110
- version: 0.15.1
138
+ version: '0'
139
+ - !ruby/object:Gem::Dependency
140
+ name: sqlite3
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :development
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - ">="
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
111
153
  description: Bitwise attribute for ruby class and Rails model.
112
154
  email:
113
155
  - oterosantos@gmail.com
@@ -115,11 +157,11 @@ executables: []
115
157
  extensions: []
116
158
  extra_rdoc_files: []
117
159
  files:
160
+ - ".github/workflows/ci.yml"
118
161
  - ".gitignore"
119
162
  - ".rspec"
120
163
  - ".rubocop.yml"
121
164
  - ".ruby-version"
122
- - ".travis.yml"
123
165
  - Gemfile
124
166
  - Gemfile.lock
125
167
  - LICENSE.txt
@@ -129,13 +171,14 @@ files:
129
171
  - bin/setup
130
172
  - bitwise_attribute.gemspec
131
173
  - lib/bitwise_attribute.rb
174
+ - lib/bitwise_attribute/active_record_methods.rb
132
175
  - lib/bitwise_attribute/values_list.rb
133
176
  - lib/bitwise_attribute/version.rb
134
177
  homepage: https://github.com/rikas/bitwise_attribute
135
178
  licenses:
136
179
  - MIT
137
180
  metadata: {}
138
- post_install_message:
181
+ post_install_message:
139
182
  rdoc_options: []
140
183
  require_paths:
141
184
  - lib
@@ -143,16 +186,15 @@ required_ruby_version: !ruby/object:Gem::Requirement
143
186
  requirements:
144
187
  - - ">="
145
188
  - !ruby/object:Gem::Version
146
- version: '0'
189
+ version: 2.5.0
147
190
  required_rubygems_version: !ruby/object:Gem::Requirement
148
191
  requirements:
149
192
  - - ">="
150
193
  - !ruby/object:Gem::Version
151
194
  version: '0'
152
195
  requirements: []
153
- rubyforge_project:
154
- rubygems_version: 2.7.3
155
- signing_key:
196
+ rubygems_version: 3.1.4
197
+ signing_key:
156
198
  specification_version: 4
157
199
  summary: Bitwise attribute for ruby class and Rails model.
158
200
  test_files: []
data/.travis.yml DELETED
@@ -1,5 +0,0 @@
1
- sudo: false
2
- language: ruby
3
- rvm:
4
- - 2.5.0
5
- before_install: gem install bundler -v 1.16.1