diff options
author | José Valim <jose.valim@gmail.com> | 2011-11-25 09:49:54 +0000 |
---|---|---|
committer | José Valim <jose.valim@gmail.com> | 2011-11-25 09:49:54 +0000 |
commit | 696d01f7f4a8ed787924a41cce6df836cd73c46f (patch) | |
tree | d38247044fa4fb5eadd8c8f9182b9fa9e1f26576 | |
parent | 6d9f9b3b05f6ea55aad9853888912bcca4d81c9f (diff) | |
download | rails-696d01f7f4a8ed787924a41cce6df836cd73c46f.tar.gz rails-696d01f7f4a8ed787924a41cce6df836cd73c46f.tar.bz2 rails-696d01f7f4a8ed787924a41cce6df836cd73c46f.zip |
Add docs to serializers. Update CHANGELOGs.
-rw-r--r-- | actionpack/lib/action_controller/metal/serialization.rb | 23 | ||||
-rw-r--r-- | activemodel/CHANGELOG.md | 14 | ||||
-rw-r--r-- | activemodel/lib/active_model/serializer.rb | 78 | ||||
-rw-r--r-- | railties/CHANGELOG.md | 12 |
4 files changed, 114 insertions, 13 deletions
diff --git a/actionpack/lib/action_controller/metal/serialization.rb b/actionpack/lib/action_controller/metal/serialization.rb index 9fb49f512e..628d5996d7 100644 --- a/actionpack/lib/action_controller/metal/serialization.rb +++ b/actionpack/lib/action_controller/metal/serialization.rb @@ -1,4 +1,27 @@ module ActionController + # Action Controller Serialization + # + # Overrides render :json to check if the given object implements +active_model_serializer+ + # as a method. If so, use the returned serializer instead of calling +to_json+ in the object. + # + # This module also provides a serialization_scope method that allows you to configure the + # +serialization_scope+ of the serializer. Most apps will likely set the +serialization_scope+ + # to the current user: + # + # class ApplicationController < ActionController::Base + # serialization_scope :current_user + # end + # + # If you need more complex scope rules, you can simply override the serialization_scope: + # + # class ApplicationController < ActionController::Base + # private + # + # def serialization_scope + # current_user + # end + # end + # module Serialization extend ActiveSupport::Concern diff --git a/activemodel/CHANGELOG.md b/activemodel/CHANGELOG.md index 71a737caff..53934f08e7 100644 --- a/activemodel/CHANGELOG.md +++ b/activemodel/CHANGELOG.md @@ -1,4 +1,16 @@ -* Added ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin* +## Rails 3.2.0 (unreleased) ## + +* Add ActiveModel::Serializer that encapsulates an ActiveModel object serialization *José Valim* + +* Renamed (with a deprecation the following constants): + + ActiveModel::Serialization => ActiveModel::Serializable + ActiveModel::Serializers::JSON => ActiveModel::Serializable::JSON + ActiveModel::Serializers::Xml => ActiveModel::Serializable::XML + + *José Valim* + +* Add ActiveModel::Errors#added? to check if a specific error has been added *Martin Svalin* * Add ability to define strict validation(with :strict => true option) that always raises exception when fails *Bogdan Gusiev* diff --git a/activemodel/lib/active_model/serializer.rb b/activemodel/lib/active_model/serializer.rb index 5478da15c8..0e23df2f2b 100644 --- a/activemodel/lib/active_model/serializer.rb +++ b/activemodel/lib/active_model/serializer.rb @@ -5,6 +5,9 @@ require "set" module ActiveModel # Active Model Array Serializer + # + # It serializes an array checking if each element that implements + # the +active_model_serializer+ method passing down the current scope. class ArraySerializer attr_reader :object, :scope @@ -28,15 +31,46 @@ module ActiveModel end # Active Model Serializer + # + # Provides a basic serializer implementation that allows you to easily + # control how a given object is going to be serialized. On initialization, + # it expects to object as arguments, a resource and a scope. For example, + # one may do in a controller: + # + # PostSerializer.new(@post, current_user).to_json + # + # The object to be serialized is the +@post+ and the scope is +current_user+. + # + # We use the scope to check if a given attribute should be serialized or not. + # For example, some attributes maybe only be returned if +current_user+ is the + # author of the post: + # + # class PostSerializer < ActiveModel::Serializer + # attributes :title, :body + # has_many :comments + # + # private + # + # def attributes + # hash = super + # hash.merge!(:email => post.email) if author? + # hash + # end + # + # def author? + # post.author == scope + # end + # end + # class Serializer - module Associations - class Config < Struct.new(:name, :options) + module Associations #:nodoc: + class Config < Struct.new(:name, :options) #:nodoc: def serializer options[:serializer] end end - class HasMany < Config + class HasMany < Config #:nodoc: def serialize(collection, scope) collection.map do |item| serializer.new(item, scope).serializable_hash @@ -45,7 +79,7 @@ module ActiveModel def serialize_ids(collection, scope) # use named scopes if they are present - #return collection.ids if collection.respond_to?(:ids) + # return collection.ids if collection.respond_to?(:ids) collection.map do |item| item.read_attribute_for_serialization(:id) @@ -53,7 +87,7 @@ module ActiveModel end end - class HasOne < Config + class HasOne < Config #:nodoc: def serialize(object, scope) object && serializer.new(object, scope).serializable_hash end @@ -76,11 +110,12 @@ module ActiveModel class_attribute :_root_embed class << self + # Define attributes to be used in the serialization. def attributes(*attrs) self._attributes += attrs end - def associate(klass, attrs) + def associate(klass, attrs) #:nodoc: options = attrs.extract_options! self._associations += attrs.map do |attr| unless method_defined?(attr) @@ -92,24 +127,43 @@ module ActiveModel end end + # Defines an association in the object should be rendered. + # + # The serializer object should implement the association name + # as a method which should return an array when invoked. If a method + # with the association name does not exist, the association name is + # dispatched to the serialized object. def has_many(*attrs) associate(Associations::HasMany, attrs) end + # Defines an association in the object should be rendered. + # + # The serializer object should implement the association name + # as a method which should return an object when invoked. If a method + # with the association name does not exist, the association name is + # dispatched to the serialized object. def has_one(*attrs) associate(Associations::HasOne, attrs) end + # Define how associations should be embedded. + # + # embed :objects # Embed associations as full objects + # embed :ids # Embed only the association ids + # embed :ids, :include => true # Embed the association ids and include objects in the root + # def embed(type, options={}) self._embed = type self._root_embed = true if options[:include] end + # Defines the root used on serialization. If false, disables the root. def root(name) self._root = name end - def inherited(klass) + def inherited(klass) #:nodoc: return if klass.anonymous? name = klass.name.demodulize.underscore.sub(/_serializer$/, '') @@ -127,6 +181,8 @@ module ActiveModel @object, @scope = object, scope end + # Returns a json representation of the serializable + # object including the root. def as_json(*) if _root hash = { _root => serializable_hash } @@ -137,6 +193,8 @@ module ActiveModel end end + # Returns a hash representation of the serializable + # object without the root. def serializable_hash if _embed == :ids attributes.merge(association_ids) @@ -147,6 +205,8 @@ module ActiveModel end end + # Returns a hash representation of the serializable + # object associations. def associations hash = {} @@ -158,6 +218,8 @@ module ActiveModel hash end + # Returns a hash representation of the serializable + # object associations ids. def association_ids hash = {} @@ -169,6 +231,8 @@ module ActiveModel hash end + # Returns a hash representation of the serializable + # object attributes. def attributes hash = {} diff --git a/railties/CHANGELOG.md b/railties/CHANGELOG.md index b05ac21b49..b055b051be 100644 --- a/railties/CHANGELOG.md +++ b/railties/CHANGELOG.md @@ -1,20 +1,22 @@ ## Rails 3.2.0 (unreleased) ## +* Add a serializer generator and add a hook for it in the scaffold generators *José Valim* + * Scaffold returns 204 No Content for API requests without content. This makes scaffold work with jQuery out of the box. *José Valim* -* Updated Rails::Rack::Logger middleware to apply any tags set in config.log_tags to the newly ActiveSupport::TaggedLogging Rails.logger. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications *DHH* +* Update Rails::Rack::Logger middleware to apply any tags set in config.log_tags to the newly ActiveSupport::TaggedLogging Rails.logger. This makes it easy to tag log lines with debug information like subdomain and request id -- both very helpful in debugging multi-user production applications *DHH* * Default options to `rails new` can be set in ~/.railsrc *Guillermo Iguaran* -* Added destroy alias to Rails engines. *Guillermo Iguaran* +* Add destroy alias to Rails engines *Guillermo Iguaran* -* Added destroy alias for Rails command line. This allows the following: `rails d model post`. *Andrey Ognevsky* +* Add destroy alias for Rails command line. This allows the following: `rails d model post` *Andrey Ognevsky* * Attributes on scaffold and model generators default to string. This allows the following: "rails g scaffold Post title body:text author" *José Valim* -* Removed old plugin generator (`rails generate plugin`) in favor of `rails plugin new` command. *Guillermo Iguaran* +* Remove old plugin generator (`rails generate plugin`) in favor of `rails plugin new` command *Guillermo Iguaran* -* Removed old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API. *Guillermo Iguaran* +* Remove old 'config.paths.app.controller' API in favor of 'config.paths["app/controller"]' API *Guillermo Iguaran* * Rails 3.1.1 |