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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e5b1904f990b0edf7d1a91f1ac6b703f9bddc428d280e031ae4daaa6983f6835
4
- data.tar.gz: cea92b99f11a508d543d9ff4f812e9326ae30aefa06e448619b19ab6dc1dbe02
3
+ metadata.gz: d4202c89da527945bdf58692cdd2c99c98090b130b674605ad4d97d6938b48f7
4
+ data.tar.gz: c1ce9e1690953791c8325405ce6fe398b251acc2095868e238146d5e560fc173
5
5
  SHA512:
6
- metadata.gz: bc1e1b4afd64f05275f2123fb05e9614009eb3ecfb4e8d4940fc74811300a15c2cd7dc13db75ec9d5883d66f81aa2ec4ae637e7039f10ffedbadcb198190c499
7
- data.tar.gz: 976d4c41225d97445c1c9ebf78b19d55d97465c1dce1731fb648d81b1d4e9a35b3446cbfb2e3a5491a6e63c3a1b7172c92533303cc239853c409cb558f951323
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 = Object.const_set(const_name, Class.new(ActiveRecord::Base))
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
- hash_opts = {:class_name => property_class.name, :autosave => true, :dependent => :destroy}.merge(options)
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
- silence_warnings do
46
+ unless exists then # makes has_many idempotent...
28
47
  has_many association, hash_opts do
29
- include PropertySets::ActiveRecordExtension::AssociationExtensions
30
-
31
- property_class.keys.each do |key|
32
- raise "Invalid property key #{key}" if self.respond_to?(key)
33
-
34
- # Reports the coerced truth value of the property
35
- define_method "#{key}?" do
36
- type = property_class.type(key)
37
- value = lookup_value(type, key)
38
- ![ "false", "0", "", "off", "n" ].member?(value.to_s.downcase)
39
- end
40
-
41
- # Returns the value of the property
42
- define_method "#{key}" do
43
- type = property_class.type(key)
44
- lookup_value(type, key)
45
- end
46
-
47
- # Assigns a new value to the property
48
- define_method "#{key}=" do |value|
49
- instance = lookup(key)
50
- instance.value = PropertySets::Casting.write(property_class.type(key), value)
51
- instance.value
52
- end
53
-
54
- define_method "#{key}_record" do
55
- lookup(key)
56
- end
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 :property_serialized? do |key|
60
- property_class.type(key) == :serialized
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) { send(setname).send(new_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 property(key, options = nil)
111
+ def properties
112
112
  @properties ||= HashWithIndifferentAccess.new
113
- @properties[key] = options
113
+ end
114
+
115
+ def property(key, options = nil)
116
+ properties[key] = options
114
117
  end
115
118
 
116
119
  def keys
117
- @properties.keys
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
- @properties[key].try(:[], :default)
128
+ properties[key].try(:[], :default)
126
129
  end
127
130
 
128
131
  def type(key)
129
- @properties[key].try(:[], :type) || :string
132
+ properties[key].try(:[], :type) || :string
130
133
  end
131
134
 
132
135
  def protected?(key)
133
- @properties[key].try(:[], :protected) || false
136
+ properties[key].try(:[], :protected) || false
134
137
  end
135
138
 
136
139
  def owner_class=(owner_class_name)
@@ -1,3 +1,3 @@
1
1
  module PropertySets
2
- VERSION = "3.5.3"
2
+ VERSION = "3.7.0"
3
3
  end
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.5.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: 2020-06-02 00:00:00.000000000 Z
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.1'
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.1'
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: []