Permalink
Browse files

* Add pluggable JSON backends with support for the JSON gem. [rick]

    Example: ActiveSupport::JSON.backend = "JSONGem"

  All internal Rails JSON encoding is now handled by ActiveSupport::JSON.encode().  Use of #to_json is not recommended, as it may clash with other libraries that overwrite it.  However, you can recover Rails specific functionality
  if you really want to use #to_json.

    gem 'json'
    ActiveSupport::JSON.backend = "JSONGem"

    class ActiveRecord::Base
      alias to_json rails_to_json
    end
  • Loading branch information...
1 parent bab2bfa commit 3c4c6bd0df598f865f49a983b4c65c415af4bcfc @technoweenie technoweenie committed Apr 23, 2009
Showing with 384 additions and 239 deletions.
  1. +1 −1 actionpack/lib/action_controller/base/render.rb
  2. +9 −7 actionpack/lib/action_view/helpers/prototype_helper.rb
  3. +5 −5 actionpack/lib/action_view/helpers/scriptaculous_helper.rb
  4. +9 −9 actionpack/test/controller/render_test.rb
  5. +8 −8 actionpack/test/template/prototype_helper_test.rb
  6. +7 −3 activerecord/lib/active_record/serializers/json_serializer.rb
  7. +56 −56 activerecord/test/cases/json_serialization_test.rb
  8. +4 −1 activeresource/lib/active_resource/base.rb
  9. +15 −0 activesupport/CHANGELOG
  10. +32 −2 activesupport/lib/active_support/json.rb
  11. +36 −0 activesupport/lib/active_support/json/backends/jsongem.rb
  12. +83 −0 activesupport/lib/active_support/json/backends/yaml.rb
  13. +0 −82 activesupport/lib/active_support/json/decoding.rb
  14. +3 −1 activesupport/lib/active_support/json/encoders/date.rb
  15. +3 −1 activesupport/lib/active_support/json/encoders/date_time.rb
  16. +4 −2 activesupport/lib/active_support/json/encoders/enumerable.rb
  17. +3 −1 activesupport/lib/active_support/json/encoders/false_class.rb
  18. +5 −3 activesupport/lib/active_support/json/encoders/hash.rb
  19. +3 −1 activesupport/lib/active_support/json/encoders/nil_class.rb
  20. +3 −1 activesupport/lib/active_support/json/encoders/numeric.rb
  21. +3 −1 activesupport/lib/active_support/json/encoders/object.rb
  22. +3 −1 activesupport/lib/active_support/json/encoders/regexp.rb
  23. +3 −1 activesupport/lib/active_support/json/encoders/string.rb
  24. +3 −1 activesupport/lib/active_support/json/encoders/symbol.rb
  25. +3 −1 activesupport/lib/active_support/json/encoders/time.rb
  26. +3 −1 activesupport/lib/active_support/json/encoders/true_class.rb
  27. +1 −1 activesupport/lib/active_support/json/encoding.rb
  28. +1 −1 activesupport/lib/active_support/json/variable.rb
  29. +3 −1 activesupport/lib/active_support/time_with_zone.rb
  30. +2 −2 activesupport/test/core_ext/time_with_zone_test.rb
  31. +51 −25 activesupport/test/json/decoding_test.rb
  32. +19 −19 activesupport/test/json/encoding_test.rb
@@ -254,7 +254,7 @@ def render(options = nil, extra_options = {}, &block) #:doc:
render_for_text(js)
elsif json = options[:json]
- json = json.to_json unless json.is_a?(String)
+ json = ActiveSupport::JSON.encode(json) unless json.is_a?(String)
json = "#{options[:callback]}(#{json})" unless options[:callback].blank?
response.content_type ||= Mime::JSON
render_for_text(json)
@@ -973,7 +973,7 @@ def drop_receiving(id, options = {})
def loop_on_multiple_args(method, ids)
record(ids.size>1 ?
"#{javascript_object_for(ids)}.each(#{method})" :
- "#{method}(#{ids.first.to_json})")
+ "#{method}(#{ActiveSupport::JSON.encode(ids.first)})")
end
def page
@@ -997,7 +997,7 @@ def render(*options_for_render)
end
def javascript_object_for(object)
- object.respond_to?(:to_json) ? object.to_json : object.inspect
+ ActiveSupport::JSON.encode(object)
end
def arguments_for_call(arguments, block = nil)
@@ -1139,7 +1139,7 @@ def append_to_function_chain!(call)
class JavaScriptElementProxy < JavaScriptProxy #:nodoc:
def initialize(generator, id)
@id = id
- super(generator, "$(#{id.to_json})")
+ super(generator, "$(#{ActiveSupport::JSON.encode(id)})")
end
# Allows access of element attributes through +attribute+. Examples:
@@ -1184,10 +1184,12 @@ def respond_to?(method)
true
end
- def to_json(options = nil)
+ def rails_to_json(options = nil)
@variable
end
+ alias to_json rails_to_json
+
private
def append_to_function_chain!(call)
@generator << @variable if @empty
@@ -1211,7 +1213,7 @@ def each_slice(variable, number, &block)
enumerate :eachSlice, :variable => variable, :method_args => [number], :yield_args => %w(value index), :return => true, &block
else
add_variable_assignment!(variable)
- append_enumerable_function!("eachSlice(#{number.to_json});")
+ append_enumerable_function!("eachSlice(#{ActiveSupport::JSON.encode(number)});")
end
end
@@ -1232,7 +1234,7 @@ def inject(variable, memo, &block)
def pluck(variable, property)
add_variable_assignment!(variable)
- append_enumerable_function!("pluck(#{property.to_json});")
+ append_enumerable_function!("pluck(#{ActiveSupport::JSON.encode(property)});")
end
def zip(variable, *arguments, &block)
@@ -1296,7 +1298,7 @@ def append_enumerable_function!(call)
class JavaScriptElementCollectionProxy < JavaScriptCollectionProxy #:nodoc:\
def initialize(generator, pattern)
- super(generator, "$$(#{pattern.to_json})")
+ super(generator, "$$(#{ActiveSupport::JSON.encode(pattern)})")
end
end
end
@@ -43,7 +43,7 @@ module ScriptaculousHelper
# You can change the behaviour with various options, see
# http://script.aculo.us for more documentation.
def visual_effect(name, element_id = false, js_options = {})
- element = element_id ? element_id.to_json : "element"
+ element = element_id ? ActiveSupport::JSON.encode(element_id) : "element"
js_options[:queue] = if js_options[:queue].is_a?(Hash)
'{' + js_options[:queue].map {|k, v| k == :limit ? "#{k}:#{v}" : "#{k}:'#{v}'" }.join(',') + '}'
@@ -138,7 +138,7 @@ def sortable_element(element_id, options = {})
end
def sortable_element_js(element_id, options = {}) #:nodoc:
- options[:with] ||= "Sortable.serialize(#{element_id.to_json})"
+ options[:with] ||= "Sortable.serialize(#{ActiveSupport::JSON.encode(element_id)})"
options[:onUpdate] ||= "function(){" + remote_function(options) + "}"
options.delete_if { |key, value| PrototypeHelper::AJAX_OPTIONS.include?(key) }
@@ -149,7 +149,7 @@ def sortable_element_js(element_id, options = {}) #:nodoc:
options[:containment] = array_or_string_for_javascript(options[:containment]) if options[:containment]
options[:only] = array_or_string_for_javascript(options[:only]) if options[:only]
- %(Sortable.create(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(Sortable.create(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
# Makes the element with the DOM ID specified by +element_id+ draggable.
@@ -164,7 +164,7 @@ def draggable_element(element_id, options = {})
end
def draggable_element_js(element_id, options = {}) #:nodoc:
- %(new Draggable(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(new Draggable(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
# Makes the element with the DOM ID specified by +element_id+ receive
@@ -219,7 +219,7 @@ def drop_receiving_element_js(element_id, options = {}) #:nodoc:
# Confirmation happens during the onDrop callback, so it can be removed from the options
options.delete(:confirm) if options[:confirm]
- %(Droppables.add(#{element_id.to_json}, #{options_for_javascript(options)});)
+ %(Droppables.add(#{ActiveSupport::JSON.encode(element_id)}, #{options_for_javascript(options)});)
end
end
end
@@ -194,19 +194,19 @@ def accessing_controller_name_in_template
end
def render_json_hello_world
- render :json => {:hello => 'world'}.to_json
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_hello_world_with_callback
- render :json => {:hello => 'world'}.to_json, :callback => 'alert'
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :callback => 'alert'
end
def render_json_with_custom_content_type
- render :json => {:hello => 'world'}.to_json, :content_type => 'text/javascript'
+ render :json => ActiveSupport::JSON.encode(:hello => 'world'), :content_type => 'text/javascript'
end
def render_symbol_json
- render :json => {:hello => 'world'}.to_json
+ render :json => ActiveSupport::JSON.encode(:hello => 'world')
end
def render_json_with_render_to_string
@@ -875,31 +875,31 @@ def test_render_file_from_template
def test_render_json
get :render_json_hello_world
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_callback
get :render_json_hello_world_with_callback
- assert_equal 'alert({"hello": "world"})', @response.body
+ assert_equal 'alert({"hello":"world"})', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_custom_content_type
get :render_json_with_custom_content_type
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'text/javascript', @response.content_type
end
def test_render_symbol_json
get :render_symbol_json
- assert_equal '{"hello": "world"}', @response.body
+ assert_equal '{"hello":"world"}', @response.body
assert_equal 'application/json', @response.content_type
end
def test_render_json_with_render_to_string
get :render_json_with_render_to_string
- assert_equal '{"hello": "partial html"}', @response.body
+ assert_equal '{"hello":"partial html"}', @response.body
assert_equal 'application/json', @response.content_type
end
@@ -328,28 +328,28 @@ def test_replace_element_with_string
def test_remove
assert_equal 'Element.remove("foo");',
@generator.remove('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.remove);',
+ assert_equal '["foo","bar","baz"].each(Element.remove);',
@generator.remove('foo', 'bar', 'baz')
end
def test_show
assert_equal 'Element.show("foo");',
@generator.show('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.show);',
+ assert_equal '["foo","bar","baz"].each(Element.show);',
@generator.show('foo', 'bar', 'baz')
end
def test_hide
assert_equal 'Element.hide("foo");',
@generator.hide('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.hide);',
+ assert_equal '["foo","bar","baz"].each(Element.hide);',
@generator.hide('foo', 'bar', 'baz')
end
def test_toggle
assert_equal 'Element.toggle("foo");',
@generator.toggle('foo')
- assert_equal '["foo", "bar", "baz"].each(Element.toggle);',
+ assert_equal '["foo","bar","baz"].each(Element.toggle);',
@generator.toggle('foo', 'bar', 'baz')
end
@@ -386,7 +386,7 @@ def test_to_s
assert_equal <<-EOS.chomp, @generator.to_s
Element.insert("element", { top: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
Element.insert("element", { bottom: "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E" });
-["foo", "bar"].each(Element.remove);
+["foo","bar"].each(Element.remove);
Element.update("baz", "\\u003Cp\\u003EThis is a test\\u003C/p\\u003E");
EOS
end
@@ -555,8 +555,8 @@ def test_collection_proxy_with_zip
end
assert_equal <<-EOS.strip, @generator.to_s
-var a = [1, 2, 3].zip([4, 5, 6], [7, 8, 9]);
-var b = [1, 2, 3].zip([4, 5, 6], [7, 8, 9], function(array) {
+var a = [1, 2, 3].zip([4,5,6], [7,8,9]);
+var b = [1, 2, 3].zip([4,5,6], [7,8,9], function(array) {
return array.reverse();
});
EOS
@@ -607,7 +607,7 @@ def test_debug_rjs
def test_literal
literal = @generator.literal("function() {}")
- assert_equal "function() {}", literal.to_json
+ assert_equal "function() {}", ActiveSupport::JSON.encode(literal)
assert_equal "", @generator.to_s
end
@@ -74,21 +74,25 @@ def self.included(base)
# {"comments": [{"body": "Don't think too hard"}],
# "title": "So I was thinking"}]}
def to_json(options = {})
+ json = JsonSerializer.new(self, options).to_s
if include_root_in_json
- "{#{self.class.json_class_name}: #{JsonSerializer.new(self, options).to_s}}"
+ "{#{self.class.json_class_name}:#{json}}"
else
- JsonSerializer.new(self, options).to_s
+ json
end
end
+ # For compatibility with ActiveSupport::JSON.encode
+ alias rails_to_json to_json
+
def from_json(json)
self.attributes = ActiveSupport::JSON.decode(json)
self
end
class JsonSerializer < ActiveRecord::Serialization::Serializer #:nodoc:
def serialize
- serializable_record.to_json
+ ActiveSupport::JSON.encode(serializable_record)
end
end
Oops, something went wrong.

0 comments on commit 3c4c6bd

Please sign in to comment.