activesupport-binary-property 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 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: []