This is useful to set application-wide default behavior - e.g. in
previous versions of AMS the default behavior was to serialize the
full object graph by default - equivalent to the '**' include tree.
Currently just the global setting, but I think this could also work
on a per-serializer basis, with more attention.
failing test
use try for when the assoc_data is possibly nil
rubocop test/action_controller/json_api/deserialization_test.rb -a
attempt to work on rails-master
account for rails/master having instead of nil for assoc_data
added changelog
The JSON API adapater dasherizes every key, but the deserializer left the keys
unaltered. Thus, the client had to send underscored keys in the request body in
order for Rails to properly match sent values to model attributes.
This commit adds automatic key transformation on deserialization. Per default the
deserializer transforms the keys to underscore, but this behaviour can also be
changed by including `key_transform` in the deserializer options.
NoMethodError is current_user is nil, so nil.admin?
NameError is a superclass of NoMethodError (which Rails 4.0 won't allow)
and means current_user might not be defined
Idea per remear (Ben Mills) in the slack:
https://amserializers.slack.com/archives/general/p1455140474000171
remear:
just so i understand, the adapter in `render json: resource, status: 422, adapter: 'json_api/error',
serializer: ActiveModel::Serializer::ErrorSerializer` is a different one than, say what i’ve
specified in a base serializer with `ActiveModel::Serializer.config.adapter = :json_api`. correct?
and a followup question of, why not same adapter but different serializer?
me:
With the way the code is written now, it might be possible to not require a special jsonapi adapter.
However, the behavior is pretty different from the jsonapi adapter.
this first draft of the PR had it automatically set the adapter if there were errors. since that
requires more discussion, I took a step back and made it explicit for this PR
If I were to re-use the json api adapter and remove the error one, it think the serializable hash
method would look like
```
def serializable_hash(options = nil)
return { errors: JsonApi::Error.collection_errors } if serializer.is_a?(ErrorsSerializer)
return { errors: JsonApi::Error.resource_errors(serializer) } if serializer.is_a?(ErrorSerializer)
options ||= {}
```
I suppose it could be something more duckish like
```
def serializable_hash(options = nil)
if serializer.errors? # object.errors.any? || object.any? {|o| o.errors.any? }
JsonApi::Error.new(serializer).serializable_hash
else
# etc
```
http://jsonapi.org/format/#document-top-level
fix failing tests
support for top-level links limited to jsonapi adapter
Move docs from README to docs/ dir
move links to json-api adapter & create Links class to hold links data
One of three constituents is used to provide the
CollectionSerializer's #json_key:
1) the :root option - controlled by the caller
2) the #name of the first resource serializer - the root or
underscored model name
3) the underscored #name of the resources object - generally
equivalent to the underscored model name of #2
Of the three, only the latter 2 are out of the callers control, and
only the latter two are expected to be singular by default. Not
pluralizing the root gives the caller additional flexibility in
defining the desired root, whether conventionally plural,
unconventionally plural (e.g. objects_received:) or singular.
Squashed commits:
Add Logging
Generates logging when renders a serializer.
Tunning performance on notify_active_support
- Use yield over block.call
- Freeze the event name string
Organize the logger architeture
* Keep only the `ActiveModel::Serializer.logger` to follow the same public API we
have for example to config, like `ActiveModel::Serializer.config.adapter` and
remove the `ActiveModelSerializers.logger` API.
* Define the logger on the load of the AMS, following the Rails convention on
Railties [1], [2] and [3].
This way on non Rails apps we have a default logger and on Rails apps we will
use the `Rails.logger` the same way that Active Job do [4].
[1]: 2ad9afe4ff/activejob/lib/active_job/railtie.rb (L9-L11)
[2]: 2ad9afe4ff/activerecord/lib/active_record/railtie.rb (L75-L77)
[3]: 2ad9afe4ff/actionview/lib/action_view/railtie.rb (L19-L21)
[4]: 2ad9afe4ff/activejob/lib/active_job/logging.rb (L10-L11)
Performance tunning on LogSubscriber#render
Move the definition of locals to inside the `info` block this way the code is
executed only when the logger is called.
Remove not needed check on SerializableResource
Use SerializableResource on ActionController integration
On the ActionController was using a adapter, and since the instrumentation is
made on the SerializableResource we need to use the SerializableResource over
the adapter directly. Otherwise the logger is not called on a Rails app.
Use SerializableResource on the ActionController, since this is the main
interface to create and call a serializer.
Using always the SerializableResource we can keep the adapter code more easy to
mantain since no Adapter will need to call the instrumentation, only the
SerializableResource care about this.
Add docs about logging
Add a CHANGELOG entry
Keep the ActiveModelSerializers.logger
Better wording on Logging docs
[ci skip]
Add doc about instrumentation
[ci skip]
Use ActiveModel::Callbacks on the SerializableResource
I was seeing transient failures where adapters may not be registered.
e.g. https://travis-ci.org/rails-api/active_model_serializers/builds/77735382
Since we're using the Adapter, JsonApi, and Json classes
as namespaces, some of the conventions we use for modules don't apply.
Basically, we don't want to define the class anywhere besides itself.
Otherwise, the inherited hooks may not run, and some adapters may not
be registered.
For example:
If we have a class Api `class Api; end`
And Api is also used as a namespace for `Api::Product`
And the classes are defined in different files.
In one file:
```ruby
class Api
autoload :Product
def self.inherited(subclass)
puts
p [:inherited, subclass.name]
puts
end
end
```
And in another:
```ruby
class Api
class Product < Api
def sell_sell_sell!
# TODO: sell
end
end
end
```
If we load the Api class file first, the inherited hook will be defined on the class
so that when we load the Api::Product class, we'll see the output:
```plain
[ :inherited, Api::Product]
```
However, if we load the Api::Product class first, since it defines the `Api` class
and then inherited from it, the Api file was never loaded, the hook never defined,
and thus never run.
By defining the class as `class Api::Product < Api` We ensure the the Api class
MUST be defined, and thus, the hook will be defined and run and so sunshine and unicorns.
Appendix:
The below would work, but triggers a circular reference warning.
It's also not recommended to mix require with autoload.
```ruby
require 'api'
class Api
class Product < Api
def sell_sell_sell!
# TODO: sell
end
end
end
```
This failure scenario was introduced by removing the circular reference warnings in
https://github.com/rails-api/active_model_serializers/pull/1067
Style note:
To make diffs on the adapters smalleer and easier to read, I've maintained the same
identention that was in the original file. I've decided to prefer ease of reading
the diff over style, esp. since we may later return to the preferred class declaration style.
with '#' will be ignored, and an empty message aborts the commit.