custom_fields 2.0.0.rc1 → 2.0.0.rc2

Sign up to get free protection for your applications and to get access to all the features.
@@ -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