mirror of
https://github.com/rails/rails.git
synced 2022-11-09 12:12:34 -05:00
Work around the fact the JSON gem was overwriting to_json implementation for all Ruby core classes.
This is required because the JSON gem is incompatible with Rails behavior and was not allowing ActiveModel::Errors to be serialized. So we need to ensure Rails implementation is the one triggered. [#4890 state:resolved]
This commit is contained in:
parent
cfaaed3f40
commit
7bd85a8fc2
5 changed files with 43 additions and 21 deletions
|
@ -3,6 +3,7 @@
|
|||
require 'active_support/core_ext/array/wrap'
|
||||
require 'active_support/core_ext/string/inflections'
|
||||
require 'active_support/core_ext/object/blank'
|
||||
require 'active_support/core_ext/hash/reverse_merge'
|
||||
require 'active_support/ordered_hash'
|
||||
|
||||
module ActiveModel
|
||||
|
@ -164,15 +165,12 @@ module ActiveModel
|
|||
# # <error>name must be specified</error>
|
||||
# # </errors>
|
||||
def to_xml(options={})
|
||||
require 'builder' unless defined? ::Builder
|
||||
options[:root] ||= "errors"
|
||||
options[:indent] ||= 2
|
||||
options[:builder] ||= ::Builder::XmlMarkup.new(:indent => options[:indent])
|
||||
to_a.to_xml options.reverse_merge(:root => "errors", :skip_types => true)
|
||||
end
|
||||
|
||||
options[:builder].instruct! unless options.delete(:skip_instruct)
|
||||
options[:builder].errors do |e|
|
||||
to_a.each { |error| e.error(error) }
|
||||
end
|
||||
# Returns an array as JSON representation for this object.
|
||||
def as_json(options=nil)
|
||||
to_a
|
||||
end
|
||||
|
||||
# Adds +message+ to the error messages on +attribute+, which will be returned on a call to
|
||||
|
@ -283,7 +281,6 @@ module ActiveModel
|
|||
# <li><tt>errors.attributes.title.blank</tt></li>
|
||||
# <li><tt>errors.messages.blank</tt></li>
|
||||
# </ol>
|
||||
|
||||
def generate_message(attribute, type = :invalid, options = {})
|
||||
type = options.delete(:message) if options[:message].is_a?(Symbol)
|
||||
|
||||
|
|
|
@ -32,7 +32,7 @@ class PresenceValidationTest < ActiveModel::TestCase
|
|||
assert t.valid?
|
||||
end
|
||||
|
||||
test 'accepts array arguments' do
|
||||
def test_accepts_array_arguments
|
||||
Topic.validates_presence_of %w(title content)
|
||||
t = Topic.new
|
||||
assert t.invalid?
|
||||
|
|
|
@ -6,6 +6,9 @@ require 'models/reply'
|
|||
require 'models/custom_reader'
|
||||
require 'models/automobile'
|
||||
|
||||
require 'active_support/json'
|
||||
require 'active_support/xml_mini'
|
||||
|
||||
class ValidationsTest < ActiveModel::TestCase
|
||||
|
||||
def setup
|
||||
|
@ -158,12 +161,18 @@ class ValidationsTest < ActiveModel::TestCase
|
|||
end
|
||||
end
|
||||
|
||||
def test_errors_to_xml
|
||||
r = Reply.new :title => "Wrong Create"
|
||||
assert r.invalid?
|
||||
xml = r.errors.to_xml(:skip_instruct => true)
|
||||
assert_equal "<errors>", xml.first(8)
|
||||
assert xml.include?("<error>Content is Empty</error>")
|
||||
def test_errors_conversions
|
||||
Topic.validates_presence_of %w(title content)
|
||||
t = Topic.new
|
||||
assert t.invalid?
|
||||
|
||||
xml = t.errors.to_xml
|
||||
assert_match %r{<errors>}, xml
|
||||
assert_match %r{<error>Title can't be blank</error>}, xml
|
||||
assert_match %r{<error>Content can't be blank</error>}, xml
|
||||
|
||||
json = t.errors.to_json
|
||||
assert_equal t.errors.to_a.to_json, json
|
||||
end
|
||||
|
||||
def test_validation_order
|
||||
|
|
|
@ -128,12 +128,21 @@ module ActiveSupport
|
|||
end
|
||||
end
|
||||
|
||||
class Object
|
||||
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
|
||||
def to_json(options = nil)
|
||||
ActiveSupport::JSON.encode(self, options)
|
||||
end
|
||||
# The JSON gem adds a few modules to Ruby core classes containing :to_json definition, overwriting
|
||||
# their default behavior. That said, we need to define the basic to_json method in all of them,
|
||||
# otherwise they will always use to_json gem implementation, which is backwards incompatible in
|
||||
# several cases (for instance, the JSON implementation for Hash does not work) with inheritance
|
||||
# and consequently classes as ActiveSupport::OrderedHash cannot be serialized to json.
|
||||
[Object, Array, FalseClass, Float, Hash, Integer, NilClass, String, TrueClass].each do |klass|
|
||||
klass.class_eval <<-RUBY, __FILE__, __LINE__
|
||||
# Dumps object in JSON (JavaScript Object Notation). See www.json.org for more info.
|
||||
def to_json(options = nil)
|
||||
ActiveSupport::JSON.encode(self, options)
|
||||
end
|
||||
RUBY
|
||||
end
|
||||
|
||||
class Object
|
||||
def as_json(options = nil) #:nodoc:
|
||||
if respond_to?(:to_hash)
|
||||
to_hash
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
require 'abstract_unit'
|
||||
require 'active_support/json'
|
||||
|
||||
class OrderedHashTest < Test::Unit::TestCase
|
||||
def setup
|
||||
|
@ -185,6 +186,12 @@ class OrderedHashTest < Test::Unit::TestCase
|
|||
assert @ordered_hash.inspect.include?(@hash.inspect)
|
||||
end
|
||||
|
||||
def test_json
|
||||
ordered_hash = ActiveSupport::OrderedHash[:foo, :bar]
|
||||
hash = Hash[:foo, :bar]
|
||||
assert_equal ordered_hash.to_json, hash.to_json
|
||||
end
|
||||
|
||||
def test_alternate_initialization_with_splat
|
||||
alternate = ActiveSupport::OrderedHash[1,2,3,4]
|
||||
assert_kind_of ActiveSupport::OrderedHash, alternate
|
||||
|
|
Loading…
Reference in a new issue