activesupport-binary-property 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: 3c69f84a750f659f2207e6f59f93cdfb0981661143a212f2216e75aae7a3a75d
4
+ data.tar.gz: 38504be19fb1e295fc2b7d779181a5ad59ba5bf109de4e93276ad74aac31442e
5
+ SHA512:
6
+ metadata.gz: 408919e85a6ebd42f24a23619dc21671ac0c61b577d600b49a3e306ba5efb93201381c69005f0efd900b78eec3d8561e56f2ce383adb2650269249d2def666b2
7
+ data.tar.gz: c7c00c47a1f112c93a8268721420e92408b26ea0bc17995233597347351ceee90ae076969f62c39211ff81a906a8422980d1936beb85ffb8317285f80ee9ffd1
@@ -0,0 +1,129 @@
1
+ module BinaryProperty
2
+ extend ActiveSupport::Concern
3
+
4
+ class NonUniqPropertyValueError < StandardError; end
5
+ class ValueUsesMultipleBitsError < StandardError; end
6
+
7
+ included do
8
+ def self.has_binary_property(attribute, property_table, _prefix: false, _suffix: false)
9
+ prefix = case _prefix
10
+ when true then "#{attribute.to_s.singularize}_"
11
+ when String then _prefix
12
+ else ''
13
+ end
14
+
15
+ suffix = case _suffix
16
+ when true then "_#{attribute.to_s.singularize}"
17
+ when String then _suffix
18
+ else ''
19
+ end
20
+
21
+ # validate property_table
22
+ #
23
+ # 1. Values schould be uniq
24
+ raise NonUniqPropertyValueError if property_table.values.length != property_table.values.uniq.length
25
+ # 2. Values should all be a single bit (e.g. 2, 4, 8, ..)
26
+ raise ValueUsesMultipleBitsError if property_table.values.any? { |value| value.to_s(2).count('1') != 1 }
27
+
28
+ # Examples using:
29
+ #
30
+ # has_binary_property :permission_grants, {
31
+ # manage_contact_people: 2,
32
+ # request_administrative_changes: 4,
33
+ # request_technical_changes: 6
34
+ # }
35
+
36
+ singleton_class.instance_eval do
37
+ define_method("#{attribute}") do # def self.permission_grants
38
+ property_table # {
39
+ # manage_contact_people: 2,
40
+ # request_administrative_changes: 4,
41
+ # request_technical_changes: 6
42
+ # }
43
+ end # end
44
+ end
45
+
46
+ define_method("#{attribute.to_s.singularize}_list") do # def permission_grant_list
47
+ current_value = send(attribute) # current_value = permission_grants
48
+ property_table # property_table
49
+ .select do |_key, value| # .select do |_key, value|
50
+ (current_value & value) == value # (current_value & value) == value
51
+ end # end
52
+ .map do |key, _value| # .map do |key, _value|
53
+ key # key
54
+ end # end
55
+ end # end
56
+
57
+ define_method("#{attribute.to_s.singularize}?") do |value| # def permission_grant?(value)
58
+ current_value = send(attribute) # current_value = permission_grants
59
+ search_value = property_table[value] # search_value = property_table[value]
60
+ #
61
+ (current_value & search_value) == search_value # (current_value & search_value) == search_value
62
+ end # end
63
+
64
+ property_table.each do |key, value|
65
+ attribute_name = "#{prefix}#{key}#{suffix}"
66
+
67
+ # This uses a boolean comparision
68
+ #
69
+ # Example:
70
+ #
71
+ # * permission_grants = 6
72
+ # * key = manage_contact_people
73
+ # * value = 2
74
+ #
75
+ # Query:
76
+ #
77
+ # (permission_grants & :value) = :value
78
+ #
79
+ # is transformed into:
80
+ #
81
+ # (6 & 2) = 2
82
+ #
83
+ # Is actually:
84
+ #
85
+ # 6: 0000 1010
86
+ # 2: 0000 0010
87
+ # ---------
88
+ # & 0000 0010
89
+ #
90
+ # An AND (&) comparision will either only result in
91
+ # our number (2) or none (0). It can only have one
92
+ # bit set since we use a single bit as part of our
93
+ # AND. The output is thus either our value or 0
94
+ scope attribute_name, -> { # scope request_administrative_changes, -> {
95
+ where( # where(
96
+ "(#{attribute} & :value) = :value", # '(permission_grants & :value) = :value',
97
+ value: value # value: 4
98
+ ) # )
99
+ } # }
100
+
101
+ define_method("#{attribute_name}?") do # def request_administrative_changes?
102
+ send("#{attribute.to_s.singularize}?", key) # permission_grant?(:request_administrative_changes)
103
+ end # end
104
+
105
+ # An example about binary OR and XOR:
106
+ #
107
+ # Given:
108
+ #
109
+ # a = 0011 1100
110
+ # b = 0000 1101
111
+ #
112
+ # Then:
113
+ #
114
+ # a | b = 0011 1101 (OR: copies a bit if it exists in either operand)
115
+ # a ^ b = 0011 0001 (XOR copies the bit if it is set in one operand but not both)
116
+ #
117
+ define_method("#{attribute_name}=") do |enable| # def request_administrative_changes=(enable)
118
+ enable = false if enable.in?(['0', 0]) # enable = false if enable.in?(['0', 0])
119
+ #
120
+ if enable # if enable
121
+ send("#{attribute}=", (send(attribute) || 0) | value) # self.permission_grants = (permission_grants || 0) | 4
122
+ elsif send("#{attribute_name}?") # elsif request_administrative_changes?
123
+ send("#{attribute}=", (send(attribute) || 0) ^ value) # self.permission_grants = (permission_grants || 0) ^ 4
124
+ end # end
125
+ end # end
126
+ end
127
+ end
128
+ end
129
+ end
@@ -0,0 +1 @@
1
+ require 'activesupport-binary-property/binary_property'
metadata ADDED
@@ -0,0 +1,74 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activesupport-binary-property
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Rene van Lieshout
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2022-07-21 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: rails
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: 5.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: 5.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: rspec-rails
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
+ description: ActiveSupport::Concern that provides an enum-like functionality that
42
+ for when multiple values are allowed in a method named `has_binary_property`
43
+ email: rene@lico.nl
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - lib/activesupport-binary-property.rb
49
+ - lib/activesupport-binary-property/binary_property.rb
50
+ homepage: https://github.com/rvanlieshout/activesupport-binary-property
51
+ licenses:
52
+ - MIT
53
+ metadata: {}
54
+ post_install_message:
55
+ rdoc_options: []
56
+ require_paths:
57
+ - lib
58
+ required_ruby_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: '0'
63
+ required_rubygems_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ requirements: []
69
+ rubygems_version: 3.1.6
70
+ signing_key:
71
+ specification_version: 4
72
+ summary: ActiveSupport::Concern that provides an enum-like functionality for multiple
73
+ values
74
+ test_files: []