property_sets 3.5.3 → 3.7.0
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/lib/property_sets.rb +5 -2
- data/lib/property_sets/active_record_extension.rb +96 -33
- data/lib/property_sets/delegator.rb +25 -2
- data/lib/property_sets/property_set_model.rb +9 -6
- data/lib/property_sets/version.rb +1 -1
- metadata +7 -21
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d4202c89da527945bdf58692cdd2c99c98090b130b674605ad4d97d6938b48f7
|
|
4
|
+
data.tar.gz: c1ce9e1690953791c8325405ce6fe398b251acc2095868e238146d5e560fc173
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 6f62d70197d3fcb43434d5504187deb5667275f9a0a34d7884f2b57e23ab0e84122ed4f56c68f48a55ac74cd97ef9a7d59a042e9e1fa3e005592f09abe5c9bee
|
|
7
|
+
data.tar.gz: 3225b1bf41f59c63b43dd5ebce79f048b6933fc47345d2089a03bbcbf613b5e1c0877dbc508647a187f2ca999d88375263ec5e3bd9a660b469daf0fad669a027
|
data/lib/property_sets.rb
CHANGED
|
@@ -10,16 +10,19 @@ end
|
|
|
10
10
|
module PropertySets
|
|
11
11
|
def self.ensure_property_set_class(association, owner_class_name)
|
|
12
12
|
const_name = "#{owner_class_name}#{association.to_s.singularize.camelcase}".to_sym
|
|
13
|
+
|
|
13
14
|
unless Object.const_defined?(const_name)
|
|
14
|
-
property_class =
|
|
15
|
-
property_class.class_eval do
|
|
15
|
+
property_class = Class.new(ActiveRecord::Base) do
|
|
16
16
|
include PropertySets::PropertySetModel::InstanceMethods
|
|
17
17
|
extend PropertySets::PropertySetModel::ClassMethods
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
+
Object.const_set(const_name, property_class)
|
|
21
|
+
|
|
20
22
|
property_class.owner_class = owner_class_name
|
|
21
23
|
property_class.owner_assoc = association
|
|
22
24
|
end
|
|
25
|
+
|
|
23
26
|
Object.const_get(const_name)
|
|
24
27
|
end
|
|
25
28
|
end
|
|
@@ -6,6 +6,8 @@ module PropertySets
|
|
|
6
6
|
module ActiveRecordExtension
|
|
7
7
|
module ClassMethods
|
|
8
8
|
|
|
9
|
+
RAILS6 = ActiveRecord::VERSION::MAJOR >= 6
|
|
10
|
+
|
|
9
11
|
def property_set(association, options = {}, &block)
|
|
10
12
|
unless include?(PropertySets::ActiveRecordExtension::InstanceMethods)
|
|
11
13
|
self.send(:prepend, PropertySets::ActiveRecordExtension::InstanceMethods)
|
|
@@ -14,52 +16,84 @@ module PropertySets
|
|
|
14
16
|
end
|
|
15
17
|
|
|
16
18
|
raise "Invalid association name, letters only" unless association.to_s =~ /[a-z]+/
|
|
19
|
+
exists = property_set_index.include?(association)
|
|
20
|
+
|
|
17
21
|
self.property_set_index << association
|
|
18
22
|
|
|
23
|
+
# eg AccountSetting - this IS idempotent
|
|
19
24
|
property_class = PropertySets.ensure_property_set_class(
|
|
20
25
|
association,
|
|
21
26
|
options.delete(:owner_class_name) || self.name
|
|
22
27
|
)
|
|
23
|
-
property_class.instance_eval(&block)
|
|
24
28
|
|
|
25
|
-
|
|
29
|
+
# eg property :is_awesome
|
|
30
|
+
property_class.instance_eval(&block) if block
|
|
31
|
+
|
|
32
|
+
tb_name = options.delete :table_name
|
|
33
|
+
property_class.table_name = tb_name if tb_name
|
|
34
|
+
|
|
35
|
+
hash_opts = {
|
|
36
|
+
:class_name => property_class.name,
|
|
37
|
+
:autosave => true,
|
|
38
|
+
:dependent => :destroy,
|
|
39
|
+
:inverse_of => self.name.underscore.to_sym,
|
|
40
|
+
}.merge(options)
|
|
41
|
+
|
|
42
|
+
# TODO: should check options are compatible? warn? raise?
|
|
43
|
+
reflection = self.reflections[association.to_s] # => ActiveRecord::Reflection::HasManyReflection
|
|
44
|
+
reflection.options.merge! options if reflection && !options.empty?
|
|
26
45
|
|
|
27
|
-
|
|
46
|
+
unless exists then # makes has_many idempotent...
|
|
28
47
|
has_many association, hash_opts do
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
48
|
+
# keep this damn block! -- creates association_module below
|
|
49
|
+
end
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
# eg 5: AccountSettingsAssociationExtension
|
|
53
|
+
# eg 6: Account::SettingsAssociationExtension
|
|
54
|
+
|
|
55
|
+
# stolen/adapted from AR's collection_association.rb #define_extensions
|
|
56
|
+
|
|
57
|
+
module_name = "#{association.to_s.camelize}AssociationExtension"
|
|
58
|
+
module_name = name.demodulize + module_name unless RAILS6
|
|
59
|
+
|
|
60
|
+
target = RAILS6 ? self : self.parent
|
|
61
|
+
association_module = target.const_get module_name
|
|
62
|
+
|
|
63
|
+
association_module.module_eval do
|
|
64
|
+
include PropertySets::ActiveRecordExtension::AssociationExtensions
|
|
65
|
+
|
|
66
|
+
property_class.keys.each do |key|
|
|
67
|
+
raise "Invalid property key #{key}" if self.respond_to?(key)
|
|
68
|
+
|
|
69
|
+
# Reports the coerced truth value of the property
|
|
70
|
+
define_method "#{key}?" do
|
|
71
|
+
type = property_class.type(key)
|
|
72
|
+
value = lookup_value(type, key)
|
|
73
|
+
![ "false", "0", "", "off", "n" ].member?(value.to_s.downcase)
|
|
74
|
+
end
|
|
75
|
+
|
|
76
|
+
# Returns the value of the property
|
|
77
|
+
define_method "#{key}" do
|
|
78
|
+
type = property_class.type(key)
|
|
79
|
+
lookup_value(type, key)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Assigns a new value to the property
|
|
83
|
+
define_method "#{key}=" do |value|
|
|
84
|
+
instance = lookup(key)
|
|
85
|
+
instance.value = PropertySets::Casting.write(property_class.type(key), value)
|
|
86
|
+
instance.value
|
|
57
87
|
end
|
|
58
88
|
|
|
59
|
-
define_method
|
|
60
|
-
|
|
89
|
+
define_method "#{key}_record" do
|
|
90
|
+
lookup(key)
|
|
61
91
|
end
|
|
62
92
|
end
|
|
93
|
+
|
|
94
|
+
define_method :property_serialized? do |key|
|
|
95
|
+
property_class.type(key) == :serialized
|
|
96
|
+
end
|
|
63
97
|
end
|
|
64
98
|
end
|
|
65
99
|
end
|
|
@@ -184,6 +218,35 @@ module PropertySets
|
|
|
184
218
|
end
|
|
185
219
|
end
|
|
186
220
|
end
|
|
221
|
+
|
|
222
|
+
def update_columns(attributes)
|
|
223
|
+
if delegated_property_sets?
|
|
224
|
+
attributes = attributes.reject{|k,_| self.class.delegated_property_set_attributes.include?(k.to_s) }
|
|
225
|
+
end
|
|
226
|
+
|
|
227
|
+
super attributes
|
|
228
|
+
end
|
|
229
|
+
|
|
230
|
+
private
|
|
231
|
+
|
|
232
|
+
def delegated_property_sets?
|
|
233
|
+
self.class.respond_to?(:delegated_property_set_attributes)
|
|
234
|
+
end
|
|
235
|
+
|
|
236
|
+
def attributes_for_create(attribute_names)
|
|
237
|
+
super filter_delegated_property_set_attributes(attribute_names)
|
|
238
|
+
end
|
|
239
|
+
|
|
240
|
+
def attributes_for_update(attribute_names)
|
|
241
|
+
super filter_delegated_property_set_attributes(attribute_names)
|
|
242
|
+
end
|
|
243
|
+
|
|
244
|
+
def filter_delegated_property_set_attributes(attribute_names)
|
|
245
|
+
if delegated_property_sets?
|
|
246
|
+
return attribute_names - self.class.delegated_property_set_attributes.to_a
|
|
247
|
+
end
|
|
248
|
+
attribute_names
|
|
249
|
+
end
|
|
187
250
|
end
|
|
188
251
|
|
|
189
252
|
end
|
|
@@ -20,18 +20,35 @@ module PropertySets
|
|
|
20
20
|
def delegate_to_property_set(setname, mappings)
|
|
21
21
|
raise "Second argument must be a Hash" unless mappings.is_a?(Hash)
|
|
22
22
|
|
|
23
|
+
unless respond_to?(:delegated_property_set_attributes)
|
|
24
|
+
class_attribute :delegated_property_set_attributes
|
|
25
|
+
end
|
|
26
|
+
self.delegated_property_set_attributes ||= []
|
|
27
|
+
|
|
23
28
|
mappings.each do |old_attr, new_attr|
|
|
29
|
+
self.delegated_property_set_attributes << old_attr.to_s
|
|
24
30
|
if ActiveRecord.version < Gem::Version.new("5.0")
|
|
25
31
|
attribute old_attr, ActiveRecord::Type::Value.new
|
|
26
32
|
else
|
|
27
33
|
attribute old_attr, ActiveModel::Type::Value.new
|
|
28
34
|
end
|
|
29
|
-
define_method(old_attr) {
|
|
35
|
+
define_method(old_attr) {
|
|
36
|
+
association = send(setname)
|
|
37
|
+
type = association.association_class.type(new_attr)
|
|
38
|
+
association.lookup_value(type, new_attr)
|
|
39
|
+
}
|
|
30
40
|
alias_method "#{old_attr}_before_type_cast", old_attr
|
|
31
41
|
define_method("#{old_attr}?") { send(setname).send("#{new_attr}?") }
|
|
32
42
|
define_method("#{old_attr}=") do |value|
|
|
43
|
+
if send(old_attr) != value
|
|
44
|
+
send("#{old_attr}_will_change!")
|
|
45
|
+
end
|
|
33
46
|
send(setname).send("#{new_attr}=", value)
|
|
34
|
-
super(value)
|
|
47
|
+
super(value) if defined?(super) # Rails 4 does not define this
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
define_method("#{old_attr}_will_change!") do
|
|
51
|
+
attribute_will_change!(old_attr)
|
|
35
52
|
end
|
|
36
53
|
|
|
37
54
|
define_method("#{old_attr}_changed?") do
|
|
@@ -48,6 +65,12 @@ module PropertySets
|
|
|
48
65
|
end
|
|
49
66
|
end
|
|
50
67
|
end
|
|
68
|
+
|
|
69
|
+
# These are not database columns and should not be included in queries but
|
|
70
|
+
# using the attributes API is the only way to track changes in the main model
|
|
71
|
+
if respond_to?(:user_provided_columns)
|
|
72
|
+
self.user_provided_columns.reject!{|k,_| delegated_property_set_attributes.include?(k.to_s) }
|
|
73
|
+
end
|
|
51
74
|
end
|
|
52
75
|
end
|
|
53
76
|
end
|
|
@@ -108,13 +108,16 @@ module PropertySets
|
|
|
108
108
|
base.attr_accessible :name, :value if defined?(ProtectedAttributes)
|
|
109
109
|
end
|
|
110
110
|
|
|
111
|
-
def
|
|
111
|
+
def properties
|
|
112
112
|
@properties ||= HashWithIndifferentAccess.new
|
|
113
|
-
|
|
113
|
+
end
|
|
114
|
+
|
|
115
|
+
def property(key, options = nil)
|
|
116
|
+
properties[key] = options
|
|
114
117
|
end
|
|
115
118
|
|
|
116
119
|
def keys
|
|
117
|
-
|
|
120
|
+
properties.keys
|
|
118
121
|
end
|
|
119
122
|
|
|
120
123
|
def default(key)
|
|
@@ -122,15 +125,15 @@ module PropertySets
|
|
|
122
125
|
end
|
|
123
126
|
|
|
124
127
|
def raw_default(key)
|
|
125
|
-
|
|
128
|
+
properties[key].try(:[], :default)
|
|
126
129
|
end
|
|
127
130
|
|
|
128
131
|
def type(key)
|
|
129
|
-
|
|
132
|
+
properties[key].try(:[], :type) || :string
|
|
130
133
|
end
|
|
131
134
|
|
|
132
135
|
def protected?(key)
|
|
133
|
-
|
|
136
|
+
properties[key].try(:[], :protected) || false
|
|
134
137
|
end
|
|
135
138
|
|
|
136
139
|
def owner_class=(owner_class_name)
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: property_sets
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 3.
|
|
4
|
+
version: 3.7.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Morten Primdahl
|
|
8
|
-
autorequire:
|
|
8
|
+
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2021-02-26 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
@@ -19,7 +19,7 @@ dependencies:
|
|
|
19
19
|
version: '4.2'
|
|
20
20
|
- - "<"
|
|
21
21
|
- !ruby/object:Gem::Version
|
|
22
|
-
version: '6.
|
|
22
|
+
version: '6.2'
|
|
23
23
|
type: :runtime
|
|
24
24
|
prerelease: false
|
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
@@ -29,7 +29,7 @@ dependencies:
|
|
|
29
29
|
version: '4.2'
|
|
30
30
|
- - "<"
|
|
31
31
|
- !ruby/object:Gem::Version
|
|
32
|
-
version: '6.
|
|
32
|
+
version: '6.2'
|
|
33
33
|
- !ruby/object:Gem::Dependency
|
|
34
34
|
name: json
|
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -100,20 +100,6 @@ dependencies:
|
|
|
100
100
|
- - ">="
|
|
101
101
|
- !ruby/object:Gem::Version
|
|
102
102
|
version: '0'
|
|
103
|
-
- !ruby/object:Gem::Dependency
|
|
104
|
-
name: wwtd
|
|
105
|
-
requirement: !ruby/object:Gem::Requirement
|
|
106
|
-
requirements:
|
|
107
|
-
- - ">="
|
|
108
|
-
- !ruby/object:Gem::Version
|
|
109
|
-
version: 0.5.3
|
|
110
|
-
type: :development
|
|
111
|
-
prerelease: false
|
|
112
|
-
version_requirements: !ruby/object:Gem::Requirement
|
|
113
|
-
requirements:
|
|
114
|
-
- - ">="
|
|
115
|
-
- !ruby/object:Gem::Version
|
|
116
|
-
version: 0.5.3
|
|
117
103
|
- !ruby/object:Gem::Dependency
|
|
118
104
|
name: byebug
|
|
119
105
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -146,7 +132,7 @@ homepage: http://github.com/zendesk/property_sets
|
|
|
146
132
|
licenses:
|
|
147
133
|
- MIT
|
|
148
134
|
metadata: {}
|
|
149
|
-
post_install_message:
|
|
135
|
+
post_install_message:
|
|
150
136
|
rdoc_options: []
|
|
151
137
|
require_paths:
|
|
152
138
|
- lib
|
|
@@ -162,7 +148,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
162
148
|
version: '0'
|
|
163
149
|
requirements: []
|
|
164
150
|
rubygems_version: 3.0.3
|
|
165
|
-
signing_key:
|
|
151
|
+
signing_key:
|
|
166
152
|
specification_version: 4
|
|
167
153
|
summary: Property sets for ActiveRecord.
|
|
168
154
|
test_files: []
|