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 +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: []
|