Skip to content

Commit

Permalink
Adds support for custom serializers
Browse files Browse the repository at this point in the history
This commit implements the 0.9.x style of 
explicitly passing a serializer to a JSON render
call in a controller as an option to `render :json`

Additionally, this commit adds Yard for docs
  • Loading branch information
jdjkelly committed Jul 30, 2014
1 parent 448fc29 commit e43b9f3
Show file tree
Hide file tree
Showing 4 changed files with 66 additions and 6 deletions.
1 change: 1 addition & 0 deletions Gemfile
Expand Up @@ -4,6 +4,7 @@ source 'https://rubygems.org'
gemspec

gem "minitest"
gem "yard"

version = ENV["RAILS_VERSION"] || "4.1"

Expand Down
23 changes: 21 additions & 2 deletions lib/action_controller/serialization.rb
Expand Up @@ -5,13 +5,32 @@ module Serialization
extend ActiveSupport::Concern

include ActionController::Renderers

# Overrides ActiveController's JSON serialization
# strategy with our own approach. By default, uses
# the NullAdapter and a serializer matching the
# resource passed by the controller.
#
# @option options [Class] :serializer A serializer
# @option options [Class] :adapter An adapter
#
# @api private

def _render_option_json(resource, options)
serializer = ActiveModel::Serializer.serializer_for(resource)
serializer = if options[:serializer]
options[:serializer]
else
ActiveModel::Serializer.serializer_for(resource)
end

if serializer
object = serializer.new(resource)
adapter = ActiveModel::Serializer.default_adapter.new(object)

adapter = if options[:adapter]
options[:adapter]
else
ActiveModel::Serializer.default_adapter.new(object)
end.new(object)

super(adapter, options)
else
Expand Down
27 changes: 23 additions & 4 deletions lib/active_model/serializer.rb
Expand Up @@ -12,7 +12,17 @@ def default_adapter
def self.inherited(base)
base._attributes = []
end


# Define the list of attributes to serialize
#
# For each symbol passed, check to see if the model
# has a matching method defined. Otherwise, define a
# new method which calls `read_attribute_for_serialization`
#
# @param [Symbol] attrs
# the attr to define a new method for
#
# @api public
def self.attributes(*attrs)
@_attributes.concat attrs

Expand All @@ -23,7 +33,13 @@ def self.attributes(*attrs)
end
end

if RUBY_VERSION >= '2.0'
if RUBY_VERSION >= '2.0'
# Returns constantized serial class, for a given resource
#
# @param [Object] resource
# the resource to find a matching serializer for
#
# @api public
def self.serializer_for(resource)
if resource.respond_to?(:to_ary)
ArraySerializer
Expand All @@ -43,14 +59,17 @@ def self.serializer_for(resource)
"#{resource.class.name}Serializer".safe_constantize
end
end
end
end

attr_accessor :object

def initialize(object)
@object = object
end

# Returns a hash of attributes defined by `self.attributes(*attrs)`
#
# @api public
def attributes
self.class._attributes.dup.each_with_object({}) do |name, hash|
hash[name] = send(name)
Expand Down
21 changes: 21 additions & 0 deletions test/action_controller/serialization_test.rb
Expand Up @@ -20,6 +20,27 @@ def test_render_using_implicit_serializer
assert_equal '{"name":"Name 1","description":"Description 1"}', @response.body
end
end

class ExplicitSerializerTest < ActionController::TestCase
class ExplicitProfileSerializer < ActiveModel::Serializer
attributes :name
end

class MyController < ActionController::Base
def render_using_explicit_serializer
render json: Profile.new({ name: 'Name 1', description: 'Description 1', comments: 'Comments 1' }), serializer: ExplicitProfileSerializer
end
end

tests MyController

def test_render_using_explicit_serializer
get :render_using_explicit_serializer

assert_equal 'application/json', @response.content_type
assert_equal '{"name":"Name 1"}', @response.body
end
end
end
end

0 comments on commit e43b9f3

Please sign in to comment.