Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Move SerializableResource to ActiveModelSerializers namespace #1608

Merged
merged 1 commit into from
Mar 30, 2016
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ Fixes:
- [#1488](https://github.com/rails-api/active_model_serializers/pull/1488) Require ActiveSupport's string inflections (@nate00)

Misc:
- [#1608](https://github.com/rails-api/active_model_serializers/pull/1608) Move SerializableResource to ActiveModelSerializers (@groyoh)
- [#1602](https://github.com/rails-api/active_model_serializers/pull/1602) Add output examples to Adapters docs (@remear)
- [#1557](https://github.com/rails-api/active_model_serializers/pull/1557) Update docs regarding overriding the root key (@Jwan622)
- [#1471](https://github.com/rails-api/active_model_serializers/pull/1471) [Cleanup] Serializer caching is its own concern. (@bf4)
Expand Down
12 changes: 6 additions & 6 deletions docs/ARCHITECTURE.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ serializer. For example, the `Attributes` example represents each serializer as
unmodified attributes. The `JsonApi` adapter represents the serializer as a [JSON
API](http://jsonapi.org/) document.

The **`ActiveModel::SerializableResource`** acts to coordinate the serializer(s) and adapter
The **`ActiveModelSerializers::SerializableResource`** acts to coordinate the serializer(s) and adapter
to an object that responds to `to_json`, and `as_json`. It is used in the controller to
encapsulate the serialization resource when rendered. However, it can also be used on its own
to serialize a resource outside of a controller, as well.
Expand Down Expand Up @@ -62,16 +62,16 @@ High-level overview:
- `:each_serializer` specifies the serializer for each resource in the collection.
- For a single resource, the `:serializer` option is the resource serializer.
- Options are partitioned in serializer options and adapter options. Keys for adapter options are specified by
[`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model/serializable_resource.rb#L4).
[`ADAPTER_OPTION_KEYS`](https://github.com/rails-api/active_model_serializers/blob/master/lib/active_model_serializers/serializable_resource.rb#L5).
The remaining options are serializer options.

Details:

1. **ActionController::Serialization**
1. `serializable_resource = ActiveModel::SerializableResource.new(resource, options)`
1. `serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)`
1. `options` are partitioned into `adapter_opts` and everything else (`serializer_opts`).
The `adapter_opts` keys are defined in `ActiveModel::SerializableResource::ADAPTER_OPTION_KEYS`.
1. **ActiveModel::SerializableResource**
The `adapter_opts` keys are defined in `ActiveModelSerializers::SerializableResource::ADAPTER_OPTION_KEYS`.
1. **ActiveModelSerializers::SerializableResource**
1. `if serializable_resource.serializer?` (there is a serializer for the resource, and an adapter is used.)
- Where `serializer?` is `use_adapter? && !!(serializer)`
- Where `use_adapter?`: 'True when no explicit adapter given, or explicit value is truthy (non-nil);
Expand Down Expand Up @@ -122,5 +122,5 @@ render json: MyModel.new(level: 'awesome'), adapter: :json
would be serialized the same as

```ruby
ActiveModel::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
ActiveModelSerializers::SerializableResource.new(MyModel.new(level: 'awesome'), adapter: :json).as_json
```
4 changes: 2 additions & 2 deletions docs/general/rendering.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,11 +56,11 @@ API for a plain-old Ruby object (PORO).

## SerializableResource options

The `options` hash passed to `render` or `ActiveModel::SerializableResource.new(resource, options)`
The `options` hash passed to `render` or `ActiveModelSerializers::SerializableResource.new(resource, options)`
are partitioned into `serializer_opts` and `adapter_opts`. `adapter_opts` are passed to new Adapters;
`serializer_opts` are passed to new Serializers.

The `adapter_opts` are specified in [ActiveModel::SerializableResource::ADAPTER_OPTIONS](../../lib/active_model/serializable_resource.rb#L4).
The `adapter_opts` are specified in [ActiveModelSerializers::SerializableResource::ADAPTER_OPTIONS](../../lib/active_model_serializers/serializable_resource.rb#L5).
Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I figured out that the relative urls links to rails-api repo instead of mine so the link does not work.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

link with this change looks fine https://github.com/groyoh/active_model_serializers/blob/move_serializable_resource/lib/active_model_serializers/serializable_resource.rb#L5

The `serializer_opts` are the remaining options.

(In Rails, the `options` are also passed to the `as_json(options)` or `to_json(options)`
Expand Down
8 changes: 4 additions & 4 deletions docs/howto/outside_controller_use.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ post = Post.create(title: "Sample post", body: "I love Active Model Serializers!
options = {}

# Create a serializable resource instance
serializable_resource = ActiveModel::SerializableResource.new(post, options)
serializable_resource = ActiveModelSerializers::SerializableResource.new(post, options)

# Convert your resource into json
model_json = serializable_resource.as_json
Expand All @@ -38,20 +38,20 @@ serializer = ActiveModel::Serializer.serializer_for(post, options)
You could also retrieve the serializer via:

```ruby
ActiveModel::SerializableResource.new(post, options).serializer
ActiveModelSerializers::SerializableResource.new(post, options).serializer
```

Both approaches will return an instance, if any, of the resource's serializer.

## Serializing before controller render

At times, you might want to use a serializer without rendering it to the view. For those cases, you can create an instance of `ActiveModel::SerializableResource` with
At times, you might want to use a serializer without rendering it to the view. For those cases, you can create an instance of `ActiveModelSerializers::SerializableResource` with
the resource you want to be serialized and call `.as_json`.

```ruby
def create
message = current_user.messages.create!(message_params)
message_json = ActiveModel::SerializableResource.new(message).as_json
message_json = ActiveModelSerializers::SerializableResource.new(message).as_json
MessageCreationWorker.perform(message_json)
head 204
end
Expand Down
2 changes: 1 addition & 1 deletion docs/jsonapi/errors.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ options = nil
resource = ModelWithErrors.new
resource.errors.add(:name, 'must be awesome')

serializable_resource = ActiveModel::SerializableResource.new(
serializable_resource = ActiveModelSerializers::SerializableResource.new(
resource, {
serializer: ActiveModel::Serializer::ErrorSerializer,
adapter: :json_api
Expand Down
5 changes: 1 addition & 4 deletions lib/action_controller/serialization.rb
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,6 @@ module Serialization

include ActionController::Renderers

# Deprecated
ADAPTER_OPTION_KEYS = ActiveModel::SerializableResource::ADAPTER_OPTION_KEYS

module ClassMethods
def serialization_scope(scope)
self._serialization_scope = scope
Expand All @@ -32,7 +29,7 @@ def get_serializer(resource, options = {})
"Please pass 'adapter: false' or see ActiveSupport::SerializableResource.new"
options[:adapter] = false
end
serializable_resource = ActiveModel::SerializableResource.new(resource, options)
serializable_resource = ActiveModelSerializers::SerializableResource.new(resource, options)
serializable_resource.serialization_scope ||= serialization_scope
serializable_resource.serialization_scope_name = _serialization_scope
# For compatibility with the JSON renderer: `json.to_json(options) if json.is_a?(String)`.
Expand Down
78 changes: 4 additions & 74 deletions lib/active_model/serializable_resource.rb
Original file line number Diff line number Diff line change
@@ -1,81 +1,11 @@
require 'set'
require 'active_model_serializers/adapter'

module ActiveModel
class SerializableResource
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links])
include ActiveModelSerializers::Logging

delegate :serializable_hash, :as_json, :to_json, to: :adapter
notify :serializable_hash, :render
notify :as_json, :render
notify :to_json, :render

# Primary interface to composing a resource with a serializer and adapter.
# @return the serializable_resource, ready for #as_json/#to_json/#serializable_hash.
def initialize(resource, options = {})
@resource = resource
@adapter_opts, @serializer_opts =
options.partition { |k, _| ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
end

def serialization_scope=(scope)
serializer_opts[:scope] = scope
end

def serialization_scope
serializer_opts[:scope]
end

def serialization_scope_name=(scope_name)
serializer_opts[:scope_name] = scope_name
end

# NOTE: if no adapter is available, returns the resource itself. (i.e. adapter is a no-op)
def adapter
@adapter ||= find_adapter
end
alias adapter_instance adapter
class << self
extend ActiveModelSerializers::Deprecate

def find_adapter
return resource unless serializer?
ActiveModelSerializers::Adapter.create(serializer_instance, adapter_opts)
rescue ActiveModel::Serializer::CollectionSerializer::NoSerializerError
resource
delegate_and_deprecate :new, ActiveModelSerializers::SerializableResource
end

def serializer_instance
@serializer_instance ||= serializer.new(resource, serializer_opts)
end

# Get serializer either explicitly :serializer or implicitly from resource
# Remove :serializer key from serializer_opts
# Replace :serializer key with :each_serializer if present
def serializer
@serializer ||=
begin
@serializer = serializer_opts.delete(:serializer)
@serializer ||= ActiveModel::Serializer.serializer_for(resource)

if serializer_opts.key?(:each_serializer)
serializer_opts[:serializer] = serializer_opts.delete(:each_serializer)
end
@serializer
end
end
alias serializer_class serializer

# True when no explicit adapter given, or explicit appear is truthy (non-nil)
# False when explicit adapter is falsy (nil or false)
def use_adapter?
!(adapter_opts.key?(:adapter) && !adapter_opts[:adapter])
end

def serializer?
use_adapter? && !!serializer
end

protected

attr_reader :resource, :adapter_opts, :serializer_opts
end
end
29 changes: 12 additions & 17 deletions lib/active_model/serializer/adapter.rb
Original file line number Diff line number Diff line change
@@ -1,29 +1,24 @@
require 'active_model_serializers/adapter'
require 'active_model_serializers/deprecate'

module ActiveModel
class Serializer
# @deprecated Use ActiveModelSerializers::Adapter instead
module Adapter
class << self
extend ActiveModelSerializers::Deprecate

def self.delegate_and_deprecate(method)
delegate method, to: ActiveModelSerializers::Adapter
deprecate method, 'ActiveModelSerializers::Adapter.'
DEPRECATED_METHODS = [:create, :adapter_class, :adapter_map, :adapters, :register, :lookup].freeze
DEPRECATED_METHODS.each do |method|
delegate_and_deprecate method, ActiveModelSerializers::Adapter
end
private_class_method :delegate_and_deprecate

delegate_and_deprecate :create
delegate_and_deprecate :adapter_class
delegate_and_deprecate :adapter_map
delegate_and_deprecate :adapters
delegate_and_deprecate :register
delegate_and_deprecate :lookup
end

require 'active_model/serializer/adapter/base'
require 'active_model/serializer/adapter/null'
require 'active_model/serializer/adapter/attributes'
require 'active_model/serializer/adapter/json'
require 'active_model/serializer/adapter/json_api'
end
end
end

require 'active_model/serializer/adapter/base'
require 'active_model/serializer/adapter/null'
require 'active_model/serializer/adapter/attributes'
require 'active_model/serializer/adapter/json'
require 'active_model/serializer/adapter/json_api'
1 change: 1 addition & 0 deletions lib/active_model_serializers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ module ActiveModelSerializers
autoload :FragmentCache
autoload :Callbacks
autoload :Deserialization
autoload :SerializableResource
autoload :Logging
autoload :Test
autoload :Adapter
Expand Down
1 change: 0 additions & 1 deletion lib/active_model_serializers/adapter/json_api/link.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,6 @@ def initialize(serializer, value)
# actionpack-4.0.13/lib/action_dispatch/routing/route_set.rb:417: warning: instance variable @_routes not initialized
@object = serializer.object
@scope = serializer.scope

# Use the return value of the block unless it is nil.
if value.respond_to?(:call)
@value = instance_eval(&value)
Expand Down
2 changes: 1 addition & 1 deletion lib/active_model_serializers/callbacks.rb
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ module ClassMethods
# Defines a callback that will get called around the render method,
# whether it is as_json, to_json, or serializable_hash
#
# class ActiveModel::SerializableResource
# class ActiveModelSerializers::SerializableResource
# include ActiveModelSerializers::Callbacks
#
# around_render do |args, block|
Expand Down
6 changes: 6 additions & 0 deletions lib/active_model_serializers/deprecate.rb
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,12 @@ def deprecate(name, replacement)
end
end

def delegate_and_deprecate(method, delegee)
delegate method, to: delegee
deprecate method, "#{delegee.name}."
end

module_function :deprecate
module_function :delegate_and_deprecate
end
end
2 changes: 1 addition & 1 deletion lib/active_model_serializers/fragment_cache.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ def fetch
private

def serialize(object, serializer_class)
ActiveModel::SerializableResource.new(
SerializableResource.new(
object,
serializer: serializer_class,
adapter: adapter.class
Expand Down
81 changes: 81 additions & 0 deletions lib/active_model_serializers/serializable_resource.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
require 'set'

module ActiveModelSerializers
class SerializableResource
ADAPTER_OPTION_KEYS = Set.new([:include, :fields, :adapter, :meta, :meta_key, :links])
include ActiveModelSerializers::Logging

delegate :serializable_hash, :as_json, :to_json, to: :adapter
notify :serializable_hash, :render
notify :as_json, :render
notify :to_json, :render

# Primary interface to composing a resource with a serializer and adapter.
# @return the serializable_resource, ready for #as_json/#to_json/#serializable_hash.
def initialize(resource, options = {})
@resource = resource
@adapter_opts, @serializer_opts =
options.partition { |k, _| ADAPTER_OPTION_KEYS.include? k }.map { |h| Hash[h] }
end

def serialization_scope=(scope)
serializer_opts[:scope] = scope
end

def serialization_scope
serializer_opts[:scope]
end

def serialization_scope_name=(scope_name)
serializer_opts[:scope_name] = scope_name
end

# NOTE: if no adapter is available, returns the resource itself. (i.e. adapter is a no-op)
def adapter
@adapter ||= find_adapter
end
alias adapter_instance adapter

def find_adapter
return resource unless serializer?
ActiveModelSerializers::Adapter.create(serializer_instance, adapter_opts)
rescue ActiveModel::Serializer::CollectionSerializer::NoSerializerError
resource
end

def serializer_instance
@serializer_instance ||= serializer.new(resource, serializer_opts)
end

# Get serializer either explicitly :serializer or implicitly from resource
# Remove :serializer key from serializer_opts
# Replace :serializer key with :each_serializer if present
def serializer
@serializer ||=
begin
@serializer = serializer_opts.delete(:serializer)
@serializer ||= ActiveModel::Serializer.serializer_for(resource)

if serializer_opts.key?(:each_serializer)
serializer_opts[:serializer] = serializer_opts.delete(:each_serializer)
end
@serializer
end
end
alias serializer_class serializer

# True when no explicit adapter given, or explicit appear is truthy (non-nil)
# False when explicit adapter is falsy (nil or false)
def use_adapter?
!(adapter_opts.key?(:adapter) && !adapter_opts[:adapter])
end

def serializer?
use_adapter? && !serializer.nil?
end

protected

attr_reader :resource, :adapter_opts, :serializer_opts
end
end
2 changes: 1 addition & 1 deletion lib/grape/formatters/active_model_serializers.rb
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ module ActiveModelSerializers
def self.call(resource, env)
serializer_options = {}
serializer_options.merge!(env[:active_model_serializer_options]) if env[:active_model_serializer_options]
ActiveModel::SerializableResource.new(resource, serializer_options).to_json
::ActiveModelSerializers::SerializableResource.new(resource, serializer_options).to_json
end
end
end
Expand Down
Loading