mirror of
https://github.com/ditkrg/active_model_serializers.git
synced 2026-01-23 06:16:50 +00:00
Merge pull request #1272 from bf4/add_public_poro_base
Add PORO serializable base class: ActiveModelSerializers::Model
This commit is contained in:
commit
737784c9b7
@ -374,6 +374,13 @@ class PostSerializer < ActiveModel::Serializer
|
|||||||
end
|
end
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Serializing non-ActiveRecord objects
|
||||||
|
|
||||||
|
All serializable resources must pass the ActiveModel::Serializer::Lint::Tests.
|
||||||
|
|
||||||
|
See the ActiveModelSerializers::Model for a base class that implements the full
|
||||||
|
API for a plain-old Ruby object (PORO).
|
||||||
|
|
||||||
## Getting Help
|
## Getting Help
|
||||||
|
|
||||||
If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
|
If you find a bug, please report an [Issue](https://github.com/rails-api/active_model_serializers/issues/new).
|
||||||
|
|||||||
@ -80,8 +80,8 @@ module ActiveModel::Serializer::Lint
|
|||||||
# arguments (Rails 4.0) or a splat (Rails 4.1+).
|
# arguments (Rails 4.0) or a splat (Rails 4.1+).
|
||||||
# Fails otherwise.
|
# Fails otherwise.
|
||||||
#
|
#
|
||||||
# <tt>cache_key</tt> returns a (self-expiring) unique key for the object,
|
# <tt>cache_key</tt> returns a (self-expiring) unique key for the object, and
|
||||||
# which is used by the adapter.
|
# is part of the (self-expiring) cache_key, which is used by the adapter.
|
||||||
# It is not required unless caching is enabled.
|
# It is not required unless caching is enabled.
|
||||||
def test_cache_key
|
def test_cache_key
|
||||||
assert_respond_to resource, :cache_key
|
assert_respond_to resource, :cache_key
|
||||||
@ -92,6 +92,19 @@ module ActiveModel::Serializer::Lint
|
|||||||
assert_includes [-1, 0], actual_arity, "expected #{actual_arity.inspect} to be 0 or -1"
|
assert_includes [-1, 0], actual_arity, "expected #{actual_arity.inspect} to be 0 or -1"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Passes if the object responds to <tt>updated_at</tt> and if it takes no
|
||||||
|
# arguments.
|
||||||
|
# Fails otherwise.
|
||||||
|
#
|
||||||
|
# <tt>updated_at</tt> returns a Time object or iso8601 string and
|
||||||
|
# is part of the (self-expiring) cache_key, which is used by the adapter.
|
||||||
|
# It is not required unless caching is enabled.
|
||||||
|
def test_updated_at
|
||||||
|
assert_respond_to resource, :updated_at
|
||||||
|
actual_arity = resource.method(:updated_at).arity
|
||||||
|
assert_equal actual_arity, 0, "expected #{actual_arity.inspect} to be 0"
|
||||||
|
end
|
||||||
|
|
||||||
# Passes if the object responds to <tt>id</tt> and if it takes no
|
# Passes if the object responds to <tt>id</tt> and if it takes no
|
||||||
# arguments.
|
# arguments.
|
||||||
# Fails otherwise.
|
# Fails otherwise.
|
||||||
|
|||||||
@ -7,6 +7,9 @@ module ActiveModelSerializers
|
|||||||
mattr_accessor :logger
|
mattr_accessor :logger
|
||||||
self.logger = Rails.logger || Logger.new(IO::NULL)
|
self.logger = Rails.logger || Logger.new(IO::NULL)
|
||||||
|
|
||||||
|
extend ActiveSupport::Autoload
|
||||||
|
autoload :Model
|
||||||
|
|
||||||
module_function
|
module_function
|
||||||
|
|
||||||
# @note
|
# @note
|
||||||
|
|||||||
39
lib/active_model_serializers/model.rb
Normal file
39
lib/active_model_serializers/model.rb
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
# ActiveModelSerializers::Model is a convenient
|
||||||
|
# serializable class to inherit from when making
|
||||||
|
# serializable non-activerecord objects.
|
||||||
|
module ActiveModelSerializers
|
||||||
|
class Model
|
||||||
|
include ActiveModel::Model
|
||||||
|
include ActiveModel::Serializers::JSON
|
||||||
|
|
||||||
|
attr_reader :attributes
|
||||||
|
|
||||||
|
def initialize(attributes = {})
|
||||||
|
@attributes = attributes
|
||||||
|
super
|
||||||
|
end
|
||||||
|
|
||||||
|
# Defaults to the downcased model name.
|
||||||
|
def id
|
||||||
|
attributes.fetch(:id) { self.class.name.downcase }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Defaults to the downcased model name and updated_at
|
||||||
|
def cache_key
|
||||||
|
attributes.fetch(:cache_key) { "#{self.class.name.downcase}/#{id}-#{updated_at.strftime("%Y%m%d%H%M%S%9N")}" }
|
||||||
|
end
|
||||||
|
|
||||||
|
# Defaults to the time the serializer file was modified.
|
||||||
|
def updated_at
|
||||||
|
attributes.fetch(:updated_at) { File.mtime(__FILE__) }
|
||||||
|
end
|
||||||
|
|
||||||
|
def read_attribute_for_serialization(key)
|
||||||
|
if key == :id || key == 'id'
|
||||||
|
attributes.fetch(key) { id }
|
||||||
|
else
|
||||||
|
attributes[key]
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -46,7 +46,7 @@ module ActionController
|
|||||||
|
|
||||||
def test_render_skipping_adapter
|
def test_render_skipping_adapter
|
||||||
get :render_skipping_adapter
|
get :render_skipping_adapter
|
||||||
assert_equal '{"attributes":{"name":"Name 1","description":"Description 1","comments":"Comments 1"}}', response.body
|
assert_equal '{"name":"Name 1","description":"Description 1","comments":"Comments 1"}', response.body
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
9
test/active_model_serializers/model_test.rb
Normal file
9
test/active_model_serializers/model_test.rb
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
require 'test_helper'
|
||||||
|
|
||||||
|
class ActiveModelSerializers::ModelTest < Minitest::Test
|
||||||
|
include ActiveModel::Serializer::Lint::Tests
|
||||||
|
|
||||||
|
def setup
|
||||||
|
@resource = ActiveModelSerializers::Model.new
|
||||||
|
end
|
||||||
|
end
|
||||||
@ -36,7 +36,7 @@ module ActiveModel
|
|||||||
assert_equal({
|
assert_equal({
|
||||||
id: 42,
|
id: 42,
|
||||||
tags: [
|
tags: [
|
||||||
{ 'attributes' => { 'id' => 1, 'name' => '#hash_tag' } }
|
{ 'id' => 1, 'name' => '#hash_tag' }
|
||||||
]
|
]
|
||||||
}.to_json, adapter.serializable_hash[:post].to_json)
|
}.to_json, adapter.serializable_hash[:post].to_json)
|
||||||
end
|
end
|
||||||
|
|||||||
44
test/fixtures/poro.rb
vendored
44
test/fixtures/poro.rb
vendored
@ -1,44 +1,16 @@
|
|||||||
verbose = $VERBOSE
|
verbose = $VERBOSE
|
||||||
$VERBOSE = nil
|
$VERBOSE = nil
|
||||||
class Model
|
class Model < ActiveModelSerializers::Model
|
||||||
FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read)
|
FILE_DIGEST = Digest::MD5.hexdigest(File.open(__FILE__).read)
|
||||||
|
|
||||||
def self.model_name
|
|
||||||
@_model_name ||= ActiveModel::Name.new(self)
|
|
||||||
end
|
|
||||||
|
|
||||||
def initialize(hash = {})
|
|
||||||
@attributes = hash
|
|
||||||
end
|
|
||||||
|
|
||||||
def cache_key
|
|
||||||
"#{self.class.name.downcase}/#{self.id}-#{self.updated_at.strftime("%Y%m%d%H%M%S%9N")}"
|
|
||||||
end
|
|
||||||
|
|
||||||
def serializable_hash(options = nil)
|
|
||||||
@attributes
|
|
||||||
end
|
|
||||||
|
|
||||||
def read_attribute_for_serialization(name)
|
|
||||||
if name == :id || name == 'id'
|
|
||||||
id
|
|
||||||
else
|
|
||||||
@attributes[name]
|
|
||||||
end
|
|
||||||
end
|
|
||||||
|
|
||||||
def id
|
|
||||||
@attributes[:id] || @attributes['id'] || object_id
|
|
||||||
end
|
|
||||||
|
|
||||||
### Helper methods, not required to be serializable
|
### Helper methods, not required to be serializable
|
||||||
#
|
|
||||||
# Convenience for adding @attributes readers and writers
|
# Convenience when not adding @attributes readers and writers
|
||||||
def method_missing(meth, *args)
|
def method_missing(meth, *args)
|
||||||
if meth.to_s =~ /^(.*)=$/
|
if meth.to_s =~ /^(.*)=$/
|
||||||
@attributes[$1.to_sym] = args[0]
|
attributes[$1.to_sym] = args[0]
|
||||||
elsif @attributes.key?(meth)
|
elsif attributes.key?(meth)
|
||||||
@attributes[meth]
|
attributes[meth]
|
||||||
else
|
else
|
||||||
super
|
super
|
||||||
end
|
end
|
||||||
@ -47,10 +19,6 @@ class Model
|
|||||||
def cache_key_with_digest
|
def cache_key_with_digest
|
||||||
"#{cache_key}/#{FILE_DIGEST}"
|
"#{cache_key}/#{FILE_DIGEST}"
|
||||||
end
|
end
|
||||||
|
|
||||||
def updated_at
|
|
||||||
@attributes[:updated_at] ||= DateTime.now.to_time
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
class Profile < Model
|
class Profile < Model
|
||||||
|
|||||||
@ -24,6 +24,9 @@ module ActiveModel
|
|||||||
def id
|
def id
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def updated_at
|
||||||
|
end
|
||||||
|
|
||||||
def self.model_name
|
def self.model_name
|
||||||
@_model_name ||= ActiveModel::Name.new(self)
|
@_model_name ||= ActiveModel::Name.new(self)
|
||||||
end
|
end
|
||||||
|
|||||||
@ -54,7 +54,7 @@ module ActiveModel
|
|||||||
|
|
||||||
assert_equal key, :tags
|
assert_equal key, :tags
|
||||||
assert_equal serializer, nil
|
assert_equal serializer, nil
|
||||||
assert_equal [{ attributes: { name: '#hashtagged' } }].to_json, options[:virtual_value].to_json
|
assert_equal [{ name: '#hashtagged' }].to_json, options[:virtual_value].to_json
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user