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 +7 -0
- data/lib/activesupport-binary-property/binary_property.rb +129 -0
- data/lib/activesupport-binary-property.rb +1 -0
- metadata +74 -0
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: []
|