aboutsummaryrefslogtreecommitdiffstats
path: root/activemodel
diff options
context:
space:
mode:
Diffstat (limited to 'activemodel')
-rw-r--r--activemodel/lib/active_model/attribute_methods.rb35
-rw-r--r--activemodel/lib/active_model/serialization.rb18
-rw-r--r--activemodel/lib/active_model/serializers/json.rb14
-rw-r--r--activemodel/lib/active_model/validations.rb4
-rw-r--r--activemodel/test/cases/serializeration/json_serialization_test.rb27
5 files changed, 62 insertions, 36 deletions
diff --git a/activemodel/lib/active_model/attribute_methods.rb b/activemodel/lib/active_model/attribute_methods.rb
index b8126fb67e..44e3e64a9e 100644
--- a/activemodel/lib/active_model/attribute_methods.rb
+++ b/activemodel/lib/active_model/attribute_methods.rb
@@ -1,5 +1,5 @@
require 'active_support/core_ext/hash/keys'
-require 'active_support/core_ext/class/inheritable_attributes'
+require 'active_support/core_ext/class/attribute'
module ActiveModel
class MissingAttributeError < NoMethodError
@@ -56,6 +56,11 @@ module ActiveModel
module AttributeMethods
extend ActiveSupport::Concern
+ included do
+ class_attribute :attribute_method_matchers, :instance_writer => false
+ self.attribute_method_matchers = []
+ end
+
module ClassMethods
# Defines an "attribute" method (like +inheritance_column+ or +table_name+).
# A new (class) method will be created with the given name. If a value is
@@ -143,7 +148,7 @@ module ActiveModel
# person.clear_name
# person.name # => nil
def attribute_method_prefix(*prefixes)
- attribute_method_matchers.concat(prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix })
+ self.attribute_method_matchers += prefixes.map { |prefix| AttributeMethodMatcher.new :prefix => prefix }
undefine_attribute_methods
end
@@ -180,7 +185,7 @@ module ActiveModel
# person.name # => "Bob"
# person.name_short? # => true
def attribute_method_suffix(*suffixes)
- attribute_method_matchers.concat(suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix })
+ self.attribute_method_matchers += suffixes.map { |suffix| AttributeMethodMatcher.new :suffix => suffix }
undefine_attribute_methods
end
@@ -218,7 +223,7 @@ module ActiveModel
# person.reset_name_to_default!
# person.name # => 'Gemma'
def attribute_method_affix(*affixes)
- attribute_method_matchers.concat(affixes.map { |affix| AttributeMethodMatcher.new :prefix => affix[:prefix], :suffix => affix[:suffix] })
+ self.attribute_method_matchers += affixes.map { |affix| AttributeMethodMatcher.new :prefix => affix[:prefix], :suffix => affix[:suffix] }
undefine_attribute_methods
end
@@ -312,7 +317,7 @@ module ActiveModel
private
class AttributeMethodMatcher
- attr_reader :prefix, :suffix
+ attr_reader :prefix, :suffix, :method_missing_target
AttributeMethodMatch = Struct.new(:target, :attr_name)
@@ -320,28 +325,22 @@ module ActiveModel
options.symbolize_keys!
@prefix, @suffix = options[:prefix] || '', options[:suffix] || ''
@regex = /^(#{Regexp.escape(@prefix)})(.+?)(#{Regexp.escape(@suffix)})$/
+ @method_missing_target = :"#{@prefix}attribute#{@suffix}"
+ @method_name = "#{prefix}%s#{suffix}"
end
def match(method_name)
- if matchdata = @regex.match(method_name)
- AttributeMethodMatch.new(method_missing_target, matchdata[2])
+ if @regex =~ method_name
+ AttributeMethodMatch.new(method_missing_target, $2)
else
nil
end
end
def method_name(attr_name)
- "#{prefix}#{attr_name}#{suffix}"
- end
-
- def method_missing_target
- :"#{prefix}attribute#{suffix}"
+ @method_name % attr_name
end
end
-
- def attribute_method_matchers #:nodoc:
- read_inheritable_attribute(:attribute_method_matchers) || write_inheritable_attribute(:attribute_method_matchers, [])
- end
end
# Allows access to the object attributes, which are held in the
@@ -390,7 +389,7 @@ module ActiveModel
# Returns a struct representing the matching attribute method.
# The struct's attributes are prefix, base and suffix.
def match_attribute_method?(method_name)
- self.class.send(:attribute_method_matchers).each do |method|
+ self.class.attribute_method_matchers.each do |method|
if (match = method.match(method_name)) && attribute_method?(match.attr_name)
return match
end
@@ -401,7 +400,7 @@ module ActiveModel
# prevent method_missing from calling private methods with #send
def guard_private_attribute_method!(method_name, args)
if self.class.private_method_defined?(method_name)
- raise NoMethodError.new("Attempt to call private method", method_name, args)
+ raise NoMethodError.new("Attempt to call private method `#{method_name}'", method_name, args)
end
end
diff --git a/activemodel/lib/active_model/serialization.rb b/activemodel/lib/active_model/serialization.rb
index 542cff3aaa..8f90ef64ba 100644
--- a/activemodel/lib/active_model/serialization.rb
+++ b/activemodel/lib/active_model/serialization.rb
@@ -54,12 +54,14 @@ module ActiveModel
#
# person = Person.new
# person.serializable_hash # => {"name"=>nil}
- # person.as_json # => "{\"name\":null}"
+ # person.as_json # => {"name"=>nil}
+ # person.to_json # => "{\"name\":null}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
# person.name = "Bob"
# person.serializable_hash # => {"name"=>"Bob"}
- # person.as_json # => "{\"name\":\"Bob\"}"
+ # person.as_json # => {"name"=>"Bob"}
+ # person.to_json # => "{\"name\":\"Bob\"}"
# person.to_xml # => "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<serial-person...
#
# Valid options are <tt>:only</tt>, <tt>:except</tt> and <tt>:methods</tt> .
@@ -67,14 +69,14 @@ module ActiveModel
def serializable_hash(options = nil)
options ||= {}
- options[:only] = Array.wrap(options[:only]).map { |n| n.to_s }
- options[:except] = Array.wrap(options[:except]).map { |n| n.to_s }
+ only = Array.wrap(options[:only]).map(&:to_s)
+ except = Array.wrap(options[:except]).map(&:to_s)
attribute_names = attributes.keys.sort
- if options[:only].any?
- attribute_names &= options[:only]
- elsif options[:except].any?
- attribute_names -= options[:except]
+ if only.any?
+ attribute_names &= only
+ elsif except.any?
+ attribute_names -= except
end
method_names = Array.wrap(options[:methods]).inject([]) do |methods, name|
diff --git a/activemodel/lib/active_model/serializers/json.rb b/activemodel/lib/active_model/serializers/json.rb
index c9271ed9b4..0bfbf2aa06 100644
--- a/activemodel/lib/active_model/serializers/json.rb
+++ b/activemodel/lib/active_model/serializers/json.rb
@@ -79,18 +79,16 @@ module ActiveModel
# "title": "Welcome to the weblog"},
# {"comments": [{"body": "Don't think too hard"}],
# "title": "So I was thinking"}]}
- def encode_json(encoder)
- hash = serializable_hash(encoder.options)
+
+ def as_json(options = nil)
+ hash = serializable_hash(options)
+
if include_root_in_json
- custom_root = encoder.options && encoder.options[:root]
+ custom_root = options && options[:root]
hash = { custom_root || self.class.model_name.element => hash }
end
- ActiveSupport::JSON.encode(hash)
- end
-
- def as_json(options = nil)
- self
+ hash
end
def from_json(json)
diff --git a/activemodel/lib/active_model/validations.rb b/activemodel/lib/active_model/validations.rb
index cd37925292..1b5fb55b79 100644
--- a/activemodel/lib/active_model/validations.rb
+++ b/activemodel/lib/active_model/validations.rb
@@ -100,7 +100,7 @@ module ActiveModel
# validate :must_be_friends
#
# def must_be_friends
- # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
+ # errors.add(:base, "Must be friends to leave a comment") unless commenter.friend_of?(commentee)
# end
# end
#
@@ -114,7 +114,7 @@ module ActiveModel
# end
#
# def must_be_friends
- # errors.add_to_base("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
+ # errors.add(:base, ("Must be friends to leave a comment") unless commenter.friend_of?(commentee)
# end
# end
#
diff --git a/activemodel/test/cases/serializeration/json_serialization_test.rb b/activemodel/test/cases/serializeration/json_serialization_test.rb
index 3bc39bb06d..20d123ef0b 100644
--- a/activemodel/test/cases/serializeration/json_serialization_test.rb
+++ b/activemodel/test/cases/serializeration/json_serialization_test.rb
@@ -116,5 +116,32 @@ class JsonSerializationTest < ActiveModel::TestCase
assert_equal hash.to_json, car.errors.to_json
end
+ test "serializable_hash should not modify options passed in argument" do
+ options = { :except => :name }
+ @contact.serializable_hash(options)
+
+ assert_nil options[:only]
+ assert_equal :name, options[:except]
+ end
+
+ test "as_json should return a hash" do
+ json = @contact.as_json
+
+ assert_kind_of Hash, json
+ assert_kind_of Hash, json['contact']
+ %w(name age created_at awesome preferences).each do |field|
+ assert_equal @contact.send(field), json['contact'][field]
+ end
+ end
+
+ test "custom as_json should be honored when generating json" do
+ def @contact.as_json(options); { :name => name, :created_at => created_at }; end
+ json = @contact.to_json
+
+ assert_match %r{"name":"Konata Izumi"}, json
+ assert_match %r{"created_at":#{ActiveSupport::JSON.encode(Time.utc(2006, 8, 1))}}, json
+ assert_no_match %r{"awesome":}, json
+ assert_no_match %r{"preferences":}, json
+ end
end