bitwise_attribute 0.2.2 → 0.3.4
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/.github/workflows/ci.yml +41 -0
- data/.rspec +1 -1
- data/.rubocop.yml +22 -9
- data/.ruby-version +1 -1
- data/Gemfile.lock +88 -59
- data/README.md +87 -9
- data/bin/console +2 -2
- data/bitwise_attribute.gemspec +10 -7
- data/lib/bitwise_attribute.rb +21 -94
- data/lib/bitwise_attribute/active_record_methods.rb +79 -0
- data/lib/bitwise_attribute/values_list.rb +2 -2
- data/lib/bitwise_attribute/version.rb +1 -1
- metadata +77 -35
- data/.travis.yml +0 -5
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: a19184eaf7a73f44c929b1aa3cb0794d2d4be1f54a5c15802e1cd1eb0edf1641
|
|
4
|
+
data.tar.gz: 03edbbb6992ec20733a349a7eefc7b776a4fa91c74e1373222b8949298bbc07f
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
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
data/.rubocop.yml
CHANGED
|
@@ -1,21 +1,34 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
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
|
-
|
|
6
|
-
- 'spec/**/*'
|
|
7
|
-
- 'test/**/*'
|
|
8
|
-
- 'lib/bitwise_attribute.rb'
|
|
9
|
-
- 'lib/bitwise_attribute/values_list.rb'
|
|
13
|
+
Enabled: false
|
|
10
14
|
|
|
11
|
-
|
|
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:
|
|
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.
|
|
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.
|
|
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
|
-
|
|
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 (
|
|
13
|
-
minitest (
|
|
14
|
-
tzinfo (~>
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
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
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
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 (
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
rspec-
|
|
42
|
-
|
|
43
|
-
rspec-
|
|
44
|
-
rspec-
|
|
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.
|
|
47
|
-
rspec-mocks (3.
|
|
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.
|
|
50
|
-
rspec-support (3.
|
|
51
|
-
rubocop (
|
|
59
|
+
rspec-support (~> 3.10.0)
|
|
60
|
+
rspec-support (3.10.2)
|
|
61
|
+
rubocop (1.15.0)
|
|
52
62
|
parallel (~> 1.10)
|
|
53
|
-
parser (>=
|
|
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 (
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
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
|
-
|
|
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
|
|
100
|
+
bundler
|
|
75
101
|
pry-byebug
|
|
76
|
-
rake
|
|
77
|
-
rspec
|
|
78
|
-
rubocop
|
|
79
|
-
|
|
102
|
+
rake
|
|
103
|
+
rspec
|
|
104
|
+
rubocop
|
|
105
|
+
rubocop-rake
|
|
106
|
+
rubocop-rspec
|
|
107
|
+
simplecov
|
|
108
|
+
sqlite3
|
|
80
109
|
|
|
81
110
|
BUNDLED WITH
|
|
82
|
-
|
|
111
|
+
2.2.16
|
data/README.md
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
[](https://gemnasium.com/rikas/bitwise_attribute)
|
|
2
|
-
[](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
|
-
|
|
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
|
-
|
|
49
|
-
user
|
|
50
|
-
|
|
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
data/bitwise_attribute.gemspec
CHANGED
|
@@ -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.
|
|
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'
|
|
32
|
-
spec.add_development_dependency 'rspec'
|
|
33
|
-
spec.add_development_dependency 'rubocop'
|
|
34
|
-
spec.add_development_dependency '
|
|
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
|
data/lib/bitwise_attribute.rb
CHANGED
|
@@ -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
|
-
|
|
12
|
+
def self.included(base)
|
|
13
|
+
base.extend ClassMethods
|
|
14
|
+
end
|
|
11
15
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
column_name ||= "#{name.to_s.singularize}_mask"
|
|
16
|
+
module ClassMethods
|
|
17
|
+
include BitwiseAttribute::ActiveRecordMethods
|
|
15
18
|
|
|
16
|
-
|
|
17
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
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.
|
|
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
|
-
|
|
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
|
|
151
|
-
raise(ArgumentError, "Unknown value #{value}!") unless mapping[value]
|
|
81
|
+
values = values.map(&:to_sym).compact.uniq
|
|
152
82
|
|
|
153
|
-
|
|
154
|
-
|
|
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
|
|
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
|
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.
|
|
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:
|
|
11
|
+
date: 2021-05-29 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
|
-
name:
|
|
14
|
+
name: activerecord
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
18
|
- !ruby/object:Gem::Version
|
|
19
|
-
version:
|
|
20
|
-
type: :
|
|
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:
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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: '
|
|
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
|
|
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
|
|
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
|
|
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
|
|
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:
|
|
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
|
-
|
|
154
|
-
|
|
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: []
|