public
Description: Ruby on Rails
Homepage: http://rubyonrails.org
Clone URL: git://github.com/rails/rails.git
Added a :camelize option to ActiveRecord and Hash to_xml serialization and 
from_xml deserialization

Signed-off-by: Michael Koziarski <michael@koziarski.com>
Bruce Krysiak (author)
Mon Dec 08 16:38:04 -0800 2008
NZKoz (committer)
Wed Dec 10 11:28:05 -0800 2008
commit  aa5cdb0d47fb5484bfdde8244df7efeb2175bf3a
tree    b0b0309c7f6e700c70e2fbbe3185724479a7434f
parent  96b815d7e81b9cef912ef94c96dca923fe43b0ba
...
23
24
25
26
 
27
28
29
30
 
 
 
31
32
33
...
178
179
180
181
 
182
183
184
185
186
187
 
 
 
 
 
 
 
 
 
188
189
190
...
212
213
214
215
 
216
217
218
...
220
221
222
223
224
 
225
226
227
...
23
24
25
 
26
27
28
 
 
29
30
31
32
33
34
...
179
180
181
 
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
...
222
223
224
 
225
226
227
228
...
230
231
232
 
 
233
234
235
236
0
@@ -23,11 +23,12 @@ module ActiveRecord #:nodoc:
0
     #   </topic>
0
     #
0
     # This behavior can be controlled with <tt>:only</tt>, <tt>:except</tt>,
0
-    # <tt>:skip_instruct</tt>, <tt>:skip_types</tt> and <tt>:dasherize</tt>.
0
+    # <tt>:skip_instruct</tt>, <tt>:skip_types</tt>, <tt>:dasherize</tt> and <tt>:camelize</tt> .
0
     # The <tt>:only</tt> and <tt>:except</tt> options are the same as for the
0
     # +attributes+ method. The default is to dasherize all column names, but you
0
-    # can disable this setting <tt>:dasherize</tt> to +false+. To not have the
0
-    # column type included in the XML output set <tt>:skip_types</tt> to +true+.
0
+    # can disable this setting <tt>:dasherize</tt> to +false+. Setting <tt>:camelize</tt>
0
+    # to +true+ will camelize all column names - this also overrides <tt>:dasherize</tt>.
0
+    # To not have the column type included in the XML output set <tt>:skip_types</tt> to +true+.
0
     #
0
     # For instance:
0
     #
0
@@ -178,13 +179,22 @@ module ActiveRecord #:nodoc:
0
 
0
     def root
0
       root = (options[:root] || @record.class.to_s.underscore).to_s
0
-      dasherize? ? root.dasherize : root
0
+      reformat_name(root)
0
     end
0
 
0
     def dasherize?
0
       !options.has_key?(:dasherize) || options[:dasherize]
0
     end
0
 
0
+    def camelize?
0
+      options.has_key?(:camelize) && options[:camelize]
0
+    end
0
+
0
+    def reformat_name(name)
0
+      name = name.camelize if camelize?
0
+      dasherize? ? name.dasherize : name
0
+    end
0
+
0
     def serializable_attributes
0
       serializable_attribute_names.collect { |name| Attribute.new(name, @record) }
0
     end
0
@@ -212,7 +222,7 @@ module ActiveRecord #:nodoc:
0
 
0
     def add_tag(attribute)
0
       builder.tag!(
0
-        dasherize? ? attribute.name.dasherize : attribute.name,
0
+        reformat_name(attribute.name),
0
         attribute.value.to_s,
0
         attribute.decorations(!options[:skip_types])
0
       )
0
@@ -220,8 +230,7 @@ module ActiveRecord #:nodoc:
0
 
0
     def add_associations(association, records, opts)
0
       if records.is_a?(Enumerable)
0
-        tag = association.to_s
0
-        tag = tag.dasherize if dasherize?
0
+        tag = reformat_name(association.to_s)
0
         if records.empty?
0
           builder.tag!(tag, :type => :array)
0
         else
...
31
32
33
 
 
 
 
 
 
 
34
35
36
...
31
32
33
34
35
36
37
38
39
40
41
42
43
0
@@ -31,6 +31,13 @@ class XmlSerializationTest < ActiveRecord::TestCase
0
     assert_match %r{<created_at},     @xml
0
   end
0
 
0
+  def test_should_allow_camelized_tags
0
+    @xml = Contact.new.to_xml :root => 'xml_contact', :camelize => true
0
+    assert_match %r{^<XmlContact>},  @xml
0
+    assert_match %r{</XmlContact>$}, @xml
0
+    assert_match %r{<CreatedAt},    @xml
0
+  end
0
+
0
   def test_should_include_yielded_additions
0
     @xml = Contact.new.to_xml do |xml|
0
       xml.creator "David"
...
94
95
96
97
98
 
99
100
101
...
122
123
124
125
 
126
127
128
...
142
143
144
 
 
 
 
 
 
 
145
146
147
 
148
149
150
...
210
211
212
213
 
214
215
216
217
 
218
219
220
221
 
222
223
224
...
94
95
96
 
 
97
98
99
100
...
121
122
123
 
124
125
126
127
...
141
142
143
144
145
146
147
148
149
150
151
152
 
153
154
155
156
...
216
217
218
 
219
220
221
222
 
223
224
225
226
 
227
228
229
230
0
@@ -94,8 +94,7 @@ module ActiveSupport #:nodoc:
0
           options.reverse_merge!({ :builder => Builder::XmlMarkup.new(:indent => options[:indent]),
0
                                    :root => "hash" })
0
           options[:builder].instruct! unless options.delete(:skip_instruct)
0
-          dasherize = !options.has_key?(:dasherize) || options[:dasherize]
0
-          root = dasherize ? options[:root].to_s.dasherize : options[:root].to_s
0
+          root = rename_key(options[:root].to_s, options)
0
 
0
           options[:builder].__send__(:method_missing, root) do
0
             each do |key, value|
0
@@ -122,7 +121,7 @@ module ActiveSupport #:nodoc:
0
                   else
0
                     type_name = XML_TYPE_NAMES[value.class.name]
0
 
0
-                    key = dasherize ? key.to_s.dasherize : key.to_s
0
+                    key = rename_key(key.to_s, options)
0
 
0
                     attributes = options[:skip_types] || value.nil? || type_name.nil? ? { } : { :type => type_name }
0
                     if value.nil?
0
@@ -142,9 +141,16 @@ module ActiveSupport #:nodoc:
0
 
0
         end
0
 
0
+        def rename_key(key, options = {})
0
+          camelize = options.has_key?(:camelize) && options[:camelize]
0
+          dasherize = !options.has_key?(:dasherize) || options[:dasherize]
0
+          key = key.camelize if camelize
0
+          dasherize ? key.dasherize : key
0
+        end
0
+
0
         module ClassMethods
0
           def from_xml(xml)
0
-            typecast_xml_value(undasherize_keys(XmlMini.parse(xml)))
0
+            typecast_xml_value(unrename_keys(XmlMini.parse(xml)))
0
           end
0
 
0
           private
0
@@ -210,15 +216,15 @@ module ActiveSupport #:nodoc:
0
               end
0
             end
0
 
0
-            def undasherize_keys(params)
0
+            def unrename_keys(params)
0
               case params.class.to_s
0
                 when "Hash"
0
                   params.inject({}) do |h,(k,v)|
0
-                    h[k.to_s.tr("-", "_")] = undasherize_keys(v)
0
+                    h[k.to_s.underscore.tr("-", "_")] = unrename_keys(v)
0
                     h
0
                   end
0
                 when "Array"
0
-                  params.map { |v| undasherize_keys(v) }
0
+                  params.map { |v| unrename_keys(v) }
0
                 else
0
                   params
0
               end
...
403
404
405
 
 
 
 
 
 
 
406
407
408
...
403
404
405
406
407
408
409
410
411
412
413
414
415
0
@@ -403,6 +403,13 @@ class HashToXmlTest < Test::Unit::TestCase
0
     assert xml.include?(%(<name>David</name>))
0
   end
0
 
0
+  def test_one_level_camelize_true
0
+    xml = { :name => "David", :street_name => "Paulina" }.to_xml(@xml_options.merge(:camelize => true))
0
+    assert_equal "<Person>", xml.first(8)
0
+    assert xml.include?(%(<StreetName>Paulina</StreetName>))
0
+    assert xml.include?(%(<Name>David</Name>))
0
+  end
0
+
0
   def test_one_level_with_types
0
     xml = { :name => "David", :street => "Paulina", :age => 26, :age_in_millis => 820497600000, :moved_on => Date.new(2005, 11, 15), :resident => :yes }.to_xml(@xml_options)
0
     assert_equal "<person>", xml.first(8)

Comments

mdchaney Wed Apr 08 08:23:30 -0700 2009

Um, do you know how much code you broke by forcing “dasherize” upon us? I (and plenty of others) are using xml docs that are posted to an action, and taking advantage of the fact that the doc is busted out into a Hash that is added to params.

I have to either figure out how to persuade rails to set :dasherize to false, or go through a couple hundred lines of code and dasherize what I have. Either way, my code will only work on the latest version of rails.

This is a major change, and the default should always be to continue to do whatever was done historically, unless that historic functionality is broken.

mdchaney Wed Apr 08 10:15:09 -0700 2009

My bad, it’s not “dasherize”. The issue is line 223 of hash/conversions.rb – adding “underscore”. Same problem, though, and a major change in functionality.

NZKoz Thu Apr 09 00:39:39 -0700 2009

Sounds like a bug, please file a ticket on lighthouse and assign it to me, ideally with a test case for what’s broken.

NZKoz Thu Apr 09 00:39:52 -0700 2009

We can push out a point release to address this.

codebrulee Mon May 04 09:45:11 -0700 2009

Michael,
I created a patch for Hash#from_xml not working with all caps keys due to this commit and assigned it to you. https://rails.lighthouseapp.com/projects/8994-ruby-on-rails/tickets/2604