custom_fields 2.0.0.rc1 → 2.0.0.rc2

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.
@@ -37,7 +37,7 @@ module Mongoid #:nodoc
37
37
  end
38
38
 
39
39
  def self.with_locale(new_locale = nil)
40
- if tmp_locale
40
+ if new_locale
41
41
  current_locale = self.locale
42
42
  self.locale = new_locale
43
43
  end
@@ -45,8 +45,9 @@ module Mongoid #:nodoc:
45
45
  return nil if object.nil?
46
46
 
47
47
  # puts "deserializing...#{locale.inspect} / #{object.inspect}" # DEBUG
48
-
49
- value = if I18n.fallbacks?
48
+ value = if !object.respond_to?(:keys) # if no translation hash is given, we return the object itself
49
+ object
50
+ elsif I18n.fallbacks?
50
51
  object[I18n.fallbacks[locale.to_sym].map(&:to_s).find { |loc| !object[loc].nil? }]
51
52
  else
52
53
  object[locale.to_s]
@@ -69,6 +70,7 @@ module Mongoid #:nodoc:
69
70
  # puts "serializing...#{locale} / #{object.inspect} / #{options.inspect}" # DEBUG
70
71
 
71
72
  value = self.original_field_type.serialize(object)
73
+
72
74
  { locale.to_s => value }
73
75
  end
74
76
 
@@ -18,8 +18,9 @@ module Mongoid #:nodoc
18
18
  #
19
19
  # @since 2.1.0
20
20
  def replace_field(name, type, localize = false)
21
+ # puts "fields[#{name}] = #{fields[name.to_s].inspect} / #{fields.keys.inspect}" # DEBUG
21
22
  defaults.delete_one(name)
22
- add_field(name, fields[name].options.merge(:type => type, :localize => localize))
23
+ add_field(name, fields[name.to_s].options.merge(:type => type, :localize => localize))
23
24
  end
24
25
 
25
26
  end
@@ -12,189 +12,185 @@ module CustomFields
12
12
  attr_accessor :_custom_field_localize_diff
13
13
  end
14
14
 
15
- module InstanceMethods
16
-
17
- # Determines if the relation is enhanced by the custom fields
18
- #
19
- # @example the Person class has somewhere in its code this: "custom_fields_for :addresses"
20
- # person.custom_fields_for?(:addresses)
21
- #
22
- # @param [ String, Symbol ] name The name of the relation.
23
- #
24
- # @return [ true, false ] True if enhanced, false if not.
25
- #
26
- def custom_fields_for?(name)
27
- self.class.custom_fields_for?(name)
28
- end
29
-
30
- # Returns the class enhanced by the custom fields.
31
- # Be careful, call this method only if the source class
32
- # has been saved with success.
33
- #
34
- # @param [ String, Symbol ] name The name of the relation.
35
- #
36
- # @return [ Class ] The modified class.
37
- #
38
- def klass_with_custom_fields(name)
39
- recipe = self.custom_fields_recipe_for(name)
40
- target = self.send(name).metadata.klass
41
- target.klass_with_custom_fields(recipe)
42
- end
15
+ # Determines if the relation is enhanced by the custom fields
16
+ #
17
+ # @example the Person class has somewhere in its code this: "custom_fields_for :addresses"
18
+ # person.custom_fields_for?(:addresses)
19
+ #
20
+ # @param [ String, Symbol ] name The name of the relation.
21
+ #
22
+ # @return [ true, false ] True if enhanced, false if not.
23
+ #
24
+ def custom_fields_for?(name)
25
+ self.class.custom_fields_for?(name)
26
+ end
43
27
 
44
- # Returns the ordered list of custom fields for a relation
45
- #
46
- # @example the Person class has somewhere in its code this: "custom_fields_for :addresses"
47
- # person.ordered_custom_fields(:addresses)
48
- #
49
- # @param [ String, Symbol ] name The name of the relation.
50
- #
51
- # @return [ Collection ] The ordered list.
52
- #
53
- def ordered_custom_fields(name)
54
- self.send(:"#{name}_custom_fields").sort { |a, b| (a.position || 0) <=> (b.position || 0) }
55
- end
28
+ # Returns the class enhanced by the custom fields.
29
+ # Be careful, call this method only if the source class
30
+ # has been saved with success.
31
+ #
32
+ # @param [ String, Symbol ] name The name of the relation.
33
+ #
34
+ # @return [ Class ] The modified class.
35
+ #
36
+ def klass_with_custom_fields(name)
37
+ recipe = self.custom_fields_recipe_for(name)
38
+ target = self.send(name).metadata.klass
39
+ target.klass_with_custom_fields(recipe)
40
+ end
56
41
 
57
- # Returns the recipe (meaning all the rules) needed to
58
- # build the custom klass
59
- #
60
- # @param [ String, Symbol ] name The name of the relation.
61
- #
62
- # @return [ Array ] An array of hashes
63
- #
64
- def custom_fields_recipe_for(name)
65
- {
66
- 'name' => "#{name.to_s.classify}#{self._id}",
67
- 'rules' => self.ordered_custom_fields(name).map(&:to_recipe),
68
- 'version' => self.custom_fields_version(name)
69
- }
70
- end
42
+ # Returns the ordered list of custom fields for a relation
43
+ #
44
+ # @example the Person class has somewhere in its code this: "custom_fields_for :addresses"
45
+ # person.ordered_custom_fields(:addresses)
46
+ #
47
+ # @param [ String, Symbol ] name The name of the relation.
48
+ #
49
+ # @return [ Collection ] The ordered list.
50
+ #
51
+ def ordered_custom_fields(name)
52
+ self.send(:"#{name}_custom_fields").sort { |a, b| (a.position || 0) <=> (b.position || 0) }
53
+ end
71
54
 
72
- # Returns the number of the version for relation with custom fields
73
- #
74
- # @param [ String, Symbol ] name The name of the relation.
75
- #
76
- # @return [ Integer ] The version number
77
- #
78
- def custom_fields_version(name)
79
- self.send(:"#{name}_custom_fields_version") || 0
80
- end
55
+ # Returns the recipe (meaning all the rules) needed to
56
+ # build the custom klass
57
+ #
58
+ # @param [ String, Symbol ] name The name of the relation.
59
+ #
60
+ # @return [ Array ] An array of hashes
61
+ #
62
+ def custom_fields_recipe_for(name)
63
+ {
64
+ 'name' => "#{name.to_s.classify}#{self._id}",
65
+ 'rules' => self.ordered_custom_fields(name).map(&:to_recipe),
66
+ 'version' => self.custom_fields_version(name)
67
+ }
68
+ end
81
69
 
82
- # When the fields have been modified and before the object is saved,
83
- # we bump the version.
84
- #
85
- # @param [ String, Symbol ] name The name of the relation.
86
- #
87
- def bump_custom_fields_version(name)
88
- version = self.custom_fields_version(name) + 1
89
- self.send(:"#{name}_custom_fields_version=", version)
90
- end
70
+ # Returns the number of the version for relation with custom fields
71
+ #
72
+ # @param [ String, Symbol ] name The name of the relation.
73
+ #
74
+ # @return [ Integer ] The version number
75
+ #
76
+ def custom_fields_version(name)
77
+ self.send(:"#{name}_custom_fields_version") || 0
78
+ end
91
79
 
92
- # Change the metadata of a relation enhanced by the custom fields.
93
- # In Mongoid, all the instances of a same document share the same metadata objects.
94
- #
95
- # @param [ String, Symbol ] name The name of the relation.
96
- #
97
- def refresh_metadata_with_custom_fields(name)
98
- return if !self.persisted? || self.send(:"#{name}_custom_fields").blank? # do not generate a klass without all the information
80
+ # When the fields have been modified and before the object is saved,
81
+ # we bump the version.
82
+ #
83
+ # @param [ String, Symbol ] name The name of the relation.
84
+ #
85
+ def bump_custom_fields_version(name)
86
+ version = self.custom_fields_version(name) + 1
87
+ self.send(:"#{name}_custom_fields_version=", version)
88
+ end
99
89
 
100
- old_metadata = self.send(name).metadata
90
+ # Change the metadata of a relation enhanced by the custom fields.
91
+ # In Mongoid, all the instances of a same document share the same metadata objects.
92
+ #
93
+ # @param [ String, Symbol ] name The name of the relation.
94
+ #
95
+ def refresh_metadata_with_custom_fields(name)
96
+ return if !self.persisted? || self.send(:"#{name}_custom_fields").blank? # do not generate a klass without all the information
101
97
 
102
- # puts "old_metadata = #{old_metadata.klass.inspect} / #{old_metadata.object_id.inspect}" # DEBUG
98
+ old_metadata = self.send(name).metadata
103
99
 
104
- self.send(name).metadata = old_metadata.clone.tap do |metadata|
105
- metadata.instance_variable_set(:@klass, self.klass_with_custom_fields(name))
106
- end
100
+ # puts "old_metadata = #{old_metadata.klass.inspect} / #{old_metadata.object_id.inspect}" # DEBUG
107
101
 
108
- # puts "new_metadata = #{self.send(name).metadata.klass.inspect} / #{self.send(name).metadata.object_id.inspect}" # DEBUG
102
+ self.send(name).metadata = old_metadata.clone.tap do |metadata|
103
+ metadata.instance_variable_set(:@klass, self.klass_with_custom_fields(name))
109
104
  end
110
105
 
111
- # Initializes the object tracking the modifications
112
- # of the custom fields
113
- #
114
- # @param [ String, Symbol ] name The name of the relation.
115
- #
116
- def initialize_custom_fields_diff(name)
117
- self._custom_field_localize_diff ||= Hash.new([])
106
+ # puts "new_metadata = #{self.send(name).metadata.klass.inspect} / #{self.send(name).metadata.object_id.inspect}" # DEBUG
107
+ end
118
108
 
119
- self._custom_fields_diff ||= {}
120
- self._custom_fields_diff[name] = { '$set' => {}, '$unset' => {}, '$rename' => {} }
121
- end
109
+ # Initializes the object tracking the modifications
110
+ # of the custom fields
111
+ #
112
+ # @param [ String, Symbol ] name The name of the relation.
113
+ #
114
+ def initialize_custom_fields_diff(name)
115
+ self._custom_field_localize_diff ||= Hash.new([])
122
116
 
123
- # Collects all the modifications of the custom fields
124
- #
125
- # @param [ String, Symbol ] name The name of the relation.
126
- #
127
- # @return [ Array ] An array of hashes storing the modifications
128
- #
129
- def collect_custom_fields_diff(name, fields)
130
- # puts "==> collect_custom_fields_diff for #{name}, #{fields.size}" # DEBUG
117
+ self._custom_fields_diff ||= {}
118
+ self._custom_fields_diff[name] = { '$set' => {}, '$unset' => {}, '$rename' => {} }
119
+ end
131
120
 
132
- memo = self.initialize_custom_fields_diff(name)
121
+ # Collects all the modifications of the custom fields
122
+ #
123
+ # @param [ String, Symbol ] name The name of the relation.
124
+ #
125
+ # @return [ Array ] An array of hashes storing the modifications
126
+ #
127
+ def collect_custom_fields_diff(name, fields)
128
+ # puts "==> collect_custom_fields_diff for #{name}, #{fields.size}" # DEBUG
133
129
 
134
- fields.map do |field|
135
- field.collect_diff(memo)
136
- end
130
+ memo = self.initialize_custom_fields_diff(name)
137
131
 
138
- # collect fields with a modified localized field
139
- fields.each do |field|
140
- if field.localized_changed? && field.persisted?
141
- self._custom_field_localize_diff[name] << { :field => field.name, :localized => field.localized? }
142
- end
132
+ fields.map do |field|
133
+ field.collect_diff(memo)
134
+ end
135
+
136
+ # collect fields with a modified localized field
137
+ fields.each do |field|
138
+ if field.localized_changed? && field.persisted?
139
+ self._custom_field_localize_diff[name] << { :field => field.name, :localized => field.localized? }
143
140
  end
144
141
  end
142
+ end
145
143
 
146
- # Apply the modifications collected from the custom fields by
147
- # updating all the documents of the relation.
148
- # The update uses the power of mongodb to make it fully optimized.
149
- #
150
- # @param [ String, Symbol ] name The name of the relation.
151
- #
152
- def apply_custom_fields_diff(name)
153
- # puts "==> apply_custom_fields_recipes for #{name}, #{self._custom_fields_diff[name].inspect}" # DEBUG
144
+ # Apply the modifications collected from the custom fields by
145
+ # updating all the documents of the relation.
146
+ # The update uses the power of mongodb to make it fully optimized.
147
+ #
148
+ # @param [ String, Symbol ] name The name of the relation.
149
+ #
150
+ def apply_custom_fields_diff(name)
151
+ # puts "==> apply_custom_fields_recipes for #{name}, #{self._custom_fields_diff[name].inspect}" # DEBUG
154
152
 
155
- operations = self._custom_fields_diff[name]
156
- operations['$set'].merge!({ 'custom_fields_recipe.version' => self.custom_fields_version(name) })
157
- collection, selector = self.send(name).collection, self.send(name).criteria.selector
153
+ operations = self._custom_fields_diff[name]
154
+ operations['$set'].merge!({ 'custom_fields_recipe.version' => self.custom_fields_version(name) })
155
+ collection, selector = self.send(name).collection, self.send(name).criteria.selector
158
156
 
159
- # puts "selector = #{selector.inspect}, memo = #{attributes.inspect}" # DEBUG
157
+ # puts "selector = #{selector.inspect}, memo = #{attributes.inspect}" # DEBUG
160
158
 
161
- collection.update selector, operations, :multi => true
162
- end
159
+ collection.update selector, operations, :multi => true
160
+ end
163
161
 
164
- # If the localized attribute has been changed in at least one of the custom fields,
165
- # we have to upgrade all the records enhanced by custom_fields in order to make
166
- # the values consistent with the mongoid localize option.
167
- #
168
- # Ex: post.attributes[:name] = 'Hello world' => post.attributes[:name] = { :en => 'Hello world' }
169
- #
170
- # @param [ String, Symbol ] name The name of the relation.
171
- #
172
- def apply_custom_fields_localize_diff(name)
173
- return if self._custom_field_localize_diff[name].empty?
174
-
175
- self.send(name).all.each do |record|
176
- updates = {}
177
-
178
- # puts "[apply_custom_fields_localize_diff] processing: record #{record._id} / #{self._custom_field_localize_diff[name].inspect}" # DEBUG
179
- self._custom_field_localize_diff[name].each do |changes|
180
- if changes[:localized]
181
- value = record.read_attribute(changes[:field].to_sym)
182
- updates[changes[:field]] = { I18n.locale.to_s => value }
183
- else
184
- # the other way around
185
- value = record.read_attribute(changes[:field].to_sym)
186
- next if value.nil?
187
- updates[changes[:field]] = value[I18n.locale.to_s]
188
- end
162
+ # If the localized attribute has been changed in at least one of the custom fields,
163
+ # we have to upgrade all the records enhanced by custom_fields in order to make
164
+ # the values consistent with the mongoid localize option.
165
+ #
166
+ # Ex: post.attributes[:name] = 'Hello world' => post.attributes[:name] = { :en => 'Hello world' }
167
+ #
168
+ # @param [ String, Symbol ] name The name of the relation.
169
+ #
170
+ def apply_custom_fields_localize_diff(name)
171
+ return if self._custom_field_localize_diff[name].empty?
172
+
173
+ self.send(name).all.each do |record|
174
+ updates = {}
175
+
176
+ # puts "[apply_custom_fields_localize_diff] processing: record #{record._id} / #{self._custom_field_localize_diff[name].inspect}" # DEBUG
177
+ self._custom_field_localize_diff[name].each do |changes|
178
+ if changes[:localized]
179
+ value = record.read_attribute(changes[:field].to_sym)
180
+ updates[changes[:field]] = { I18n.locale.to_s => value }
181
+ else
182
+ # the other way around
183
+ value = record.read_attribute(changes[:field].to_sym)
184
+ next if value.nil?
185
+ updates[changes[:field]] = value[I18n.locale.to_s]
189
186
  end
187
+ end
190
188
 
191
- next if updates.empty?
189
+ next if updates.empty?
192
190
 
193
- collection = self.send(name).collection
194
- collection.update record.atomic_selector, { '$set' => updates }
195
- end
191
+ collection = self.send(name).collection
192
+ collection.update record.atomic_selector, { '$set' => updates }
196
193
  end
197
-
198
194
  end
199
195
 
200
196
  module ClassMethods
@@ -16,10 +16,6 @@ module CustomFields
16
16
 
17
17
  end
18
18
 
19
- module InstanceMethods
20
-
21
- end
22
-
23
19
  module ClassMethods
24
20
 
25
21
  # A document with custom fields always returns true.
@@ -45,7 +41,7 @@ module CustomFields
45
41
  klass.version = recipe['version']
46
42
 
47
43
  # copy scopes from the parent class (scopes does not inherit automatically from the parents in mongoid)
48
- klass.write_inheritable_attribute(:scopes, self.scopes)
44
+ # klass.write_inheritable_attribute(:scopes, self.scopes) # not needed it
49
45
 
50
46
  recipe['rules'].each do |rule|
51
47
  self.send(:"apply_#{rule['type']}_custom_field", klass, rule)
@@ -33,23 +33,19 @@ module CustomFields
33
33
 
34
34
  end
35
35
 
36
- module InstanceMethods
36
+ protected
37
37
 
38
- protected
39
-
40
- def _set_formatted_date(name, value)
41
- if value.is_a?(::String) && !value.blank?
42
- date = ::Date._strptime(value, I18n.t('date.formats.default'))
43
- value = ::Date.new(date[:year], date[:mon], date[:mday])
44
- end
45
-
46
- self.send(:"#{name}=", value)
38
+ def _set_formatted_date(name, value)
39
+ if value.is_a?(::String) && !value.blank?
40
+ date = ::Date._strptime(value, I18n.t('date.formats.default'))
41
+ value = ::Date.new(date[:year], date[:mon], date[:mday])
47
42
  end
48
43
 
49
- def _get_formatted_date(name)
50
- self.send(name.to_sym).strftime(I18n.t('date.formats.default')) rescue nil
51
- end
44
+ self.send(:"#{name}=", value)
45
+ end
52
46
 
47
+ def _get_formatted_date(name)
48
+ self.send(name.to_sym).strftime(I18n.t('date.formats.default')) rescue nil
53
49
  end
54
50
 
55
51
  end
@@ -35,24 +35,20 @@ module CustomFields
35
35
 
36
36
  end
37
37
 
38
- module InstanceMethods
39
-
40
- def ordered_select_options
41
- self.select_options.sort { |a, b| (a.position || 0) <=> (b.position || 0) }.to_a
42
- end
43
-
44
- def select_to_recipe
45
- {
46
- 'select_options' => self.ordered_select_options.map do |option|
47
- { '_id' => option._id, 'name' => option.name_translations }
48
- end
49
- }
50
- end
38
+ def ordered_select_options
39
+ self.select_options.sort { |a, b| (a.position || 0) <=> (b.position || 0) }.to_a
40
+ end
51
41
 
52
- def select_as_json(options = {})
53
- { 'select_options' => self.ordered_select_options.map(&:as_json) }
54
- end
42
+ def select_to_recipe
43
+ {
44
+ 'select_options' => self.ordered_select_options.map do |option|
45
+ { '_id' => option._id, 'name' => option.name_translations }
46
+ end
47
+ }
48
+ end
55
49
 
50
+ def select_as_json(options = {})
51
+ { 'select_options' => self.ordered_select_options.map(&:as_json) }
56
52
  end
57
53
 
58
54
  end
@@ -151,28 +147,24 @@ module CustomFields
151
147
 
152
148
  end
153
149
 
154
- module InstanceMethods
155
-
156
- def _select_option_id(name)
157
- self.send(:"#{name}_id")
158
- end
159
-
160
- def _find_select_option(name, id_or_name)
161
- self.class._select_options(name).detect do |option|
162
- option['name'] == id_or_name || option['_id'].to_s == id_or_name.to_s
163
- end
164
- end
150
+ def _select_option_id(name)
151
+ self.send(:"#{name}_id")
152
+ end
165
153
 
166
- def _get_select_option(name)
167
- option = self._find_select_option(name, self._select_option_id(name))
168
- option ? option['name'] : nil
154
+ def _find_select_option(name, id_or_name)
155
+ self.class._select_options(name).detect do |option|
156
+ option['name'] == id_or_name || option['_id'].to_s == id_or_name.to_s
169
157
  end
158
+ end
170
159
 
171
- def _set_select_option(name, value)
172
- option = self._find_select_option(name, value)
173
- self.send(:"#{name}_id=", option ? option['_id'] : nil)
174
- end
160
+ def _get_select_option(name)
161
+ option = self._find_select_option(name, self._select_option_id(name))
162
+ option ? option['name'] : nil
163
+ end
175
164
 
165
+ def _set_select_option(name, value)
166
+ option = self._find_select_option(name, value)
167
+ self.send(:"#{name}_id=", option ? option['_id'] : nil)
176
168
  end
177
169
 
178
170
  end
@@ -1,4 +1,6 @@
1
1
  # encoding: utf-8
2
2
  module CustomFields #:nodoc
3
- VERSION = "2.0.0.rc1"
3
+
4
+ VERSION = '2.0.0.rc2'
5
+
4
6
  end