This commit is contained in:
Adman65 2011-12-06 15:27:47 +02:00
parent 3edf6c2b39
commit 498c780a8f
3 changed files with 122 additions and 5 deletions

View File

@ -351,6 +351,32 @@ for the current user.
NOTE: The logic for deciding which comments a user should see still belongs in the model layer. In general, you should encapsulate concerns that require making direct Active Record queries in scopes or public methods on your models. NOTE: The logic for deciding which comments a user should see still belongs in the model layer. In general, you should encapsulate concerns that require making direct Active Record queries in scopes or public methods on your models.
h4. Modifying Associations
You can also rename associations if required. Say for example you have an association that
makes sense to be named one thing in your code, but another when data is serialized.
You can use the <code>:as</code> option to specify a different name for an association.
Here is an exmaple:
<pre lang="ruby">
class UserSerializer < ActiveModel::Serializer
has_many :followed_posts, :as => :posts
has_one :owne_account, :as => :account
end
</pre>
Using the <code>:as</code> without a <code>:serializer</code> option will use implicit detection
to determine a serializer. In this example, you'd have to define two classes: <code>PostSerializer</code>
and <code>AccountSerializer</code>. You can also add the <code>:serializer</code> option
to set it explicitly:
<pre lang="ruby">
class UserSerializer < ActiveModel::Serializer
has_many :followed_posts, :as => :posts, :serializer => CustomPostSerializer
has_one :owne_account, :as => :account, :serializer => PrivateAccountSerializer
end
</pre>
h3. Customizing Associations h3. Customizing Associations
Not all front-ends expect embedded documents in the same form. In these cases, you can override the Not all front-ends expect embedded documents in the same form. In these cases, you can override the
@ -431,6 +457,7 @@ The +association_ids+ helper will use the overridden version of the association,
this case, +association_ids+ will only include the ids of the comments provided by the this case, +association_ids+ will only include the ids of the comments provided by the
+comments+ method. +comments+ method.
h3. Special Association Serializers h3. Special Association Serializers
So far, associations defined in serializers use either the +as_json+ method on the model So far, associations defined in serializers use either the +as_json+ method on the model

View File

@ -68,6 +68,10 @@ module ActiveModel
def serializer def serializer
options[:serializer] options[:serializer]
end end
def key
options[:as] || name
end
end end
class HasMany < Config #:nodoc: class HasMany < Config #:nodoc:
@ -122,7 +126,14 @@ module ActiveModel
class_eval "def #{attr}() object.#{attr} end", __FILE__, __LINE__ class_eval "def #{attr}() object.#{attr} end", __FILE__, __LINE__
end end
options[:serializer] ||= const_get("#{attr.to_s.camelize}Serializer") # if :as is specified without :serializer, then use conventions
# to determine the serializer
if options[:as] && !options[:serializer]
options[:serializer] = const_get("#{options[:as].to_s.camelize.singularize}Serializer")
else
options[:serializer] ||= const_get("#{attr.to_s.camelize}Serializer")
end
klass.new(attr, options) klass.new(attr, options)
end end
end end
@ -212,7 +223,7 @@ module ActiveModel
_associations.each do |association| _associations.each do |association|
associated_object = send(association.name) associated_object = send(association.name)
hash[association.name] = association.serialize(associated_object, scope) hash[association.key] = association.serialize(associated_object, scope)
end end
hash hash
@ -225,7 +236,7 @@ module ActiveModel
_associations.each do |association| _associations.each do |association|
associated_object = send(association.name) associated_object = send(association.name)
hash[association.name] = association.serialize_ids(associated_object, scope) hash[association.key] = association.serialize_ids(associated_object, scope)
end end
hash hash
@ -250,4 +261,4 @@ class Array
def active_model_serializer def active_model_serializer
ActiveModel::ArraySerializer ActiveModel::ArraySerializer
end end
end end

View File

@ -34,6 +34,11 @@ class SerializerTest < ActiveModel::TestCase
end end
class Post < Model class Post < Model
def initialize(attributes)
super(attributes)
self.comments ||= []
end
attr_accessor :comments attr_accessor :comments
def active_model_serializer; PostSerializer; end def active_model_serializer; PostSerializer; end
end end
@ -429,4 +434,78 @@ class SerializerTest < ActiveModel::TestCase
{ :comment => { :title => "Comment1" } } { :comment => { :title => "Comment1" } }
], serializer.as_json) ], serializer.as_json)
end end
end
class CustomBlog < Blog
attr_accessor :public_posts, :public_user
end
class CustomBlogSerializer < ActiveModel::Serializer
has_many :public_posts, :as => :posts, :serializer => PostSerializer
has_one :public_user, :as => :user, :serializer => UserSerializer
end
def test_associations_with_as
posts = [
Post.new(:title => 'First Post', :body => 'text'),
Post.new(:title => 'Second Post', :body => 'text')
]
user = User.new
custom_blog = CustomBlog.new
custom_blog.public_posts = posts
custom_blog.public_user = user
serializer = CustomBlogSerializer.new(custom_blog, :scope => true)
assert_equal({
:custom_blog => {
:posts => [
{:title => 'First Post', :body => 'text', :comments => []},
{:title => 'Second Post', :body => 'text', :comments => []}
],
:user => {
:first_name => "Jose",
:last_name => "Valim", :ok => true,
:scope => true
}
}
}, serializer.as_json)
end
def test_implicity_detection_for_association_serializers
implicit_serializer = Class.new(ActiveModel::Serializer) do
root :custom_blog
const_set(:UserSerializer, UserSerializer)
const_set(:PostSerializer, PostSerializer)
has_many :public_posts, :as => :posts
has_one :public_user, :as => :user
end
posts = [
Post.new(:title => 'First Post', :body => 'text', :comments => []),
Post.new(:title => 'Second Post', :body => 'text', :comments => [])
]
user = User.new
custom_blog = CustomBlog.new
custom_blog.public_posts = posts
custom_blog.public_user = user
serializer = implicit_serializer.new(custom_blog, :scope => true)
assert_equal({
:custom_blog => {
:posts => [
{:title => 'First Post', :body => 'text', :comments => []},
{:title => 'Second Post', :body => 'text', :comments => []}
],
:user => {
:first_name => "Jose",
:last_name => "Valim", :ok => true,
:scope => true
}
}
}, serializer.as_json)
end
end