Skip to content

Commit

Permalink
Rely solely on active_model_serializer and remove the fancy constant …
Browse files Browse the repository at this point in the history
…lookup.
  • Loading branch information
josevalim committed Nov 23, 2011
1 parent 6da52c6 commit 7fcc8c0
Show file tree
Hide file tree
Showing 7 changed files with 41 additions and 79 deletions.
4 changes: 3 additions & 1 deletion actionpack/lib/action_controller/metal/serialization.rb
Expand Up @@ -13,7 +13,9 @@ def serialization_scope
end

def _render_option_json(json, options)
json = json.active_model_serializer.new(json, serialization_scope) if json.respond_to?(:active_model_serializer)
if json.respond_to?(:active_model_serializer) && (serializer = json.active_model_serializer)
json = serializer.new(json, serialization_scope)
end
super
end

Expand Down
16 changes: 15 additions & 1 deletion actionpack/test/controller/render_json_test.rb
Expand Up @@ -26,8 +26,12 @@ def as_json(*)
end

class JsonSerializable
def initialize(skip=false)
@skip = skip
end

def active_model_serializer
JsonSerializer
JsonSerializer unless @skip
end

def as_json(*)
Expand Down Expand Up @@ -89,6 +93,11 @@ def render_json_with_serializer
@current_user = Struct.new(:as_json).new(:current_user => true)
render :json => JsonSerializable.new
end

def render_json_with_serializer_api_but_without_serializer
@current_user = Struct.new(:as_json).new(:current_user => true)
render :json => JsonSerializable.new(true)
end
end

tests TestController
Expand Down Expand Up @@ -166,4 +175,9 @@ def test_render_json_with_serializer
assert_match '"scope":{"current_user":true}', @response.body
assert_match '"object":{"serializable_object":true}', @response.body
end

def test_render_json_with_serializer_api_but_without_serializer
get :render_json_with_serializer_api_but_without_serializer
assert_match '{"serializable_object":true}', @response.body
end
end
12 changes: 6 additions & 6 deletions activemodel/lib/active_model/serializable.rb
@@ -1,6 +1,7 @@
require 'active_support/core_ext/hash/except'
require 'active_support/core_ext/hash/slice'
require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/string/inflections'

module ActiveModel
# == Active Model Serializable
Expand Down Expand Up @@ -72,11 +73,10 @@ module Serializable
autoload :JSON, "active_model/serializable/json"
autoload :XML, "active_model/serializable/xml"

include ActiveModel::Serializer::Scope

module ClassMethods #:nodoc:
def _model_serializer
@_model_serializer ||= ActiveModel::Serializer::Finder.find(self, self)
def active_model_serializer
return @active_model_serializer if defined?(@active_model_serializer)
@active_model_serializer = "#{self.name}Serializer".safe_constantize
end
end

Expand Down Expand Up @@ -108,8 +108,8 @@ def serializable_hash(options = nil)
end

# Returns a model serializer for this object considering its namespace.
def model_serializer
self.class._model_serializer
def active_model_serializer
self.class.active_model_serializer
end

private
Expand Down
45 changes: 8 additions & 37 deletions activemodel/lib/active_model/serializer.rb
@@ -1,7 +1,6 @@
require "active_support/core_ext/class/attribute"
require "active_support/core_ext/string/inflections"
require "active_support/core_ext/module/anonymous"
require "active_support/core_ext/module/introspection"
require "set"

module ActiveModel
Expand All @@ -15,7 +14,7 @@ def initialize(object, scope)

def serializable_array
@object.map do |item|
if serializer = Serializer::Finder.find(item, scope)
if item.respond_to?(:active_model_serializer) && (serializer = item.active_model_serializer)
serializer.new(item, scope)
else
item
Expand All @@ -30,41 +29,6 @@ def as_json(*args)

# Active Model Serializer
class Serializer
module Finder
mattr_accessor :constantizer
@@constantizer = ActiveSupport::Inflector

# Finds a serializer for the given object in the given scope.
# If the object implements a +model_serializer+ method, it does
# not do a scope lookup but uses the model_serializer method instead.
def self.find(object, scope)
if object.respond_to?(:model_serializer)
object.model_serializer
else
scope = scope.class unless scope.respond_to?(:const_defined?)
object = object.class unless object.respond_to?(:name)
serializer = "#{object.name.demodulize}Serializer"

begin
scope.const_get serializer
rescue NameError => e
raise unless e.message =~ /uninitialized constant ([\w_]+::)*#{serializer}$/
scope.parents.each do |parent|
return parent.const_get(serializer) if parent.const_defined?(serializer)
end
nil
end
end
end
end

# Defines the serialization scope. Core extension serializers
# are defined in this module so a scoped lookup is able to find
# core extension serializers.
module Scope
ArraySerializer = ::ActiveModel::ArraySerializer
end

module Associations
class Config < Struct.new(:name, :options)
def serializer
Expand Down Expand Up @@ -216,3 +180,10 @@ def attributes
end
end
end

class Array
# Array uses ActiveModel::ArraySerializer.
def active_model_serializer
ActiveModel::ArraySerializer
end
end
37 changes: 3 additions & 34 deletions activemodel/test/cases/serializer_test.rb
Expand Up @@ -19,10 +19,8 @@ class User
include ActiveModel::Serializable

attr_accessor :superuser
attr_writer :model_serializer

def initialize(hash={})
@model_serializer = nil
@attributes = hash.merge(:first_name => "Jose", :last_name => "Valim", :password => "oh noes yugive my password")
end

Expand All @@ -33,17 +31,15 @@ def read_attribute_for_serialization(name)
def super_user?
@superuser
end

def model_serializer
@model_serializer || super
end
end

class Post < Model
attr_accessor :comments
def active_model_serializer; PostSerializer; end
end

class Comment < Model
def active_model_serializer; CommentSerializer; end
end

class UserSerializer < ActiveModel::Serializer
Expand Down Expand Up @@ -428,38 +424,11 @@ def test_array_serializer
post.comments = []

array = [model, post, comments]
serializer = ActiveModel::Serializer::Finder.find(array, user).new(array, user)
serializer = array.active_model_serializer.new(array, user)
assert_equal([
{ :model => "Model" },
{ :post => { :body => "Body of new post", :comments => [], :title => "New Post" } },
{ :comment => { :title => "Comment1" } }
], serializer.as_json)
end

def test_array_serializer_respects_model_serializer
user = User.new(:first_name => "Jose", :last_name => "Valim")
user.model_serializer = User2Serializer

array = [user]
serializer = ActiveModel::Serializer::Finder.find(array, user).new(array, {})
assert_equal([
{ :user2 => { :last_name => "Valim", :first_name => "Jose", :ok => true } },
], serializer.as_json)
end

def test_finder_respects_model_serializer
user = User.new(:first_name => "Jose", :last_name => "Valim")
assert_equal UserSerializer, user.model_serializer

serializer = ActiveModel::Serializer::Finder.find(user, self).new(user, {})
assert_equal({
:user => { :last_name => "Valim", :first_name => "Jose"},
}, serializer.as_json)

user.model_serializer = User2Serializer
serializer = ActiveModel::Serializer::Finder.find(user, self).new(user, {})
assert_equal({
:user2 => { :last_name => "Valim", :first_name => "Jose", :ok => true },
}, serializer.as_json)
end
end
1 change: 1 addition & 0 deletions activesupport/lib/active_support/dependencies.rb
Expand Up @@ -542,6 +542,7 @@ def get(key)
key = key.name if key.respond_to?(:name)
@store[key] ||= Inflector.constantize(key)
end
alias :[] :get

def safe_get(key)
key = key.name if key.respond_to?(:name)
Expand Down
5 changes: 5 additions & 0 deletions activesupport/test/class_cache_test.rb
Expand Up @@ -49,6 +49,11 @@ def test_get_constantizes_fails_on_invalid_names
end
end

def test_get_alias
assert @cache.empty?
assert_equal @cache[ClassCacheTest.name], @cache.get(ClassCacheTest.name)
end

def test_safe_get_constantizes
assert @cache.empty?
assert_equal ClassCacheTest, @cache.safe_get(ClassCacheTest.name)
Expand Down

0 comments on commit 7fcc8c0

Please sign in to comment.