Make schema not crash on computed attributes

We do not know the type for computed attributes, so we pick nil.

Perhaps at some point we might add a :type option for attributes (or
not), but in any case it's important to not crash when there are
computed attributes.
This commit is contained in:
Jo Liss 2012-08-17 21:52:00 +02:00
parent 9f5e1b1776
commit 6281a9149e
2 changed files with 26 additions and 17 deletions

View File

@ -169,9 +169,15 @@ module ActiveModel
klass = model_class klass = model_class
columns = klass.columns_hash columns = klass.columns_hash
attrs = _attributes.inject({}) do |hash, (name,key)| attrs = {}
column = columns[name.to_s] _attributes.each do |name, key|
hash.merge key => column.type if column = columns[name.to_s]
attrs[key] = column.type
else
# Computed attribute (method on serializer or model). We cannot
# infer the type, so we put nil.
attrs[key] = nil
end
end end
associations = _associations.inject({}) do |hash, (attr,association_class)| associations = _associations.inject({}) do |hash, (attr,association_class)|

View File

@ -568,7 +568,7 @@ class SerializerTest < ActiveModel::TestCase
def test_associations_with_as def test_associations_with_as
posts = [ posts = [
Post.new(:title => 'First Post', :body => 'text'), Post.new(:title => 'First Post', :body => 'text'),
Post.new(:title => 'Second Post', :body => 'text') Post.new(:title => 'Second Post', :body => 'text')
] ]
user = User.new user = User.new
@ -586,15 +586,15 @@ class SerializerTest < ActiveModel::TestCase
{:title => 'Second Post', :body => 'text', :comments => []} {:title => 'Second Post', :body => 'text', :comments => []}
], ],
:user => { :user => {
:first_name => "Jose", :first_name => "Jose",
:last_name => "Valim", :ok => true, :last_name => "Valim", :ok => true,
:scope => true :scope => true
} }
} }
}, serializer.as_json) }, serializer.as_json)
end end
def test_implicity_detection_for_association_serializers def test_implicity_detection_for_association_serializers
implicit_serializer = Class.new(ActiveModel::Serializer) do implicit_serializer = Class.new(ActiveModel::Serializer) do
root :custom_blog root :custom_blog
const_set(:UserSerializer, UserSerializer) const_set(:UserSerializer, UserSerializer)
@ -605,7 +605,7 @@ class SerializerTest < ActiveModel::TestCase
end end
posts = [ posts = [
Post.new(:title => 'First Post', :body => 'text', :comments => []), Post.new(:title => 'First Post', :body => 'text', :comments => []),
Post.new(:title => 'Second Post', :body => 'text', :comments => []) Post.new(:title => 'Second Post', :body => 'text', :comments => [])
] ]
user = User.new user = User.new
@ -623,8 +623,8 @@ class SerializerTest < ActiveModel::TestCase
{:title => 'Second Post', :body => 'text', :comments => []} {:title => 'Second Post', :body => 'text', :comments => []}
], ],
:user => { :user => {
:first_name => "Jose", :first_name => "Jose",
:last_name => "Valim", :ok => true, :last_name => "Valim", :ok => true,
:scope => true :scope => true
} }
} }
@ -678,13 +678,16 @@ class SerializerTest < ActiveModel::TestCase
define_method(:model_class) do model end define_method(:model_class) do model end
end end
attributes :name, :age # Computed attribute; not a column.
def can_edit; end
attributes :name, :age, :can_edit
has_many :posts, :serializer => Class.new has_many :posts, :serializer => Class.new
has_one :parent, :serializer => Class.new has_one :parent, :serializer => Class.new
end end
assert_equal serializer.schema, { assert_equal serializer.schema, {
:attributes => { :name => :string, :age => :integer }, :attributes => { :name => :string, :age => :integer, :can_edit => nil },
:associations => { :associations => {
:posts => { :has_many => :posts }, :posts => { :has_many => :posts },
:parent => { :belongs_to => :parent } :parent => { :belongs_to => :parent }
@ -862,7 +865,7 @@ class SerializerTest < ActiveModel::TestCase
expected = serializer_class.new(post).as_json expected = serializer_class.new(post).as_json
assert_equal expected, hash_object assert_equal expected, hash_object
end end
def test_embed_ids_include_true_with_root def test_embed_ids_include_true_with_root
serializer_class = post_serializer serializer_class = post_serializer
@ -911,7 +914,7 @@ class SerializerTest < ActiveModel::TestCase
:author => [{ :first_name => "Jose", :last_name => "Valim" }] :author => [{ :first_name => "Jose", :last_name => "Valim" }]
}, serializer.as_json) }, serializer.as_json)
end end
# the point of this test is to illustrate that deeply nested serializers # the point of this test is to illustrate that deeply nested serializers
# still side-load at the root. # still side-load at the root.
def test_embed_with_include_inserts_at_root def test_embed_with_include_inserts_at_root
@ -1123,7 +1126,7 @@ class SerializerTest < ActiveModel::TestCase
actual = attachment_serializer.new(attachment, {}).as_json actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({ assert_equal({
:name => 'logo.png', :name => 'logo.png',
:url => 'http://example.com/logo.png', :url => 'http://example.com/logo.png',
:attachable => { :attachable => {
:type => :email, :type => :email,
@ -1160,7 +1163,7 @@ class SerializerTest < ActiveModel::TestCase
actual = attachment_serializer.new(attachment, {}).as_json actual = attachment_serializer.new(attachment, {}).as_json
assert_equal({ assert_equal({
:name => 'logo.png', :name => 'logo.png',
:url => 'http://example.com/logo.png', :url => 'http://example.com/logo.png',
:attachable => { :attachable => {
:type => :email, :type => :email,
@ -1199,7 +1202,7 @@ class SerializerTest < ActiveModel::TestCase
assert_equal({ assert_equal({
:attachment => { :attachment => {
:name => 'logo.png', :name => 'logo.png',
:url => 'http://example.com/logo.png', :url => 'http://example.com/logo.png',
:attachable => { :attachable => {
:type => :email, :type => :email,