Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Add copy buttons to all
 blocks\n(function() {\n function addCopyButtons() {\n document.querySelectorAll('pre code').forEach(function(codeBlock) {\n if (codeBlock.parentElement.hasAttribute('data-copy-added')) return;\n codeBlock.parentElement.setAttribute('data-copy-added', 'true');\n \n var btn = document.createElement('button');\n btn.textContent = 'Copy';\n btn.style.cssText = 'position:absolute;top:4px;right:4px;padding:2px 8px;font-size:11px;background:#4ecdc4;border:none;border-radius:4px;color:#1a1a2e;cursor:pointer;opacity:0.7;transition:opacity 0.2s;';\n btn.onmouseover = function() { this.style.opacity = '1'; };\n btn.onmouseout = function() { this.style.opacity = '0.7'; };\n btn.onclick = function() {\n navigator.clipboard.writeText(codeBlock.textContent).then(function() {\n btn.textContent = 'Copied!';\n setTimeout(function() { btn.textContent = 'Copy'; }, 1500);\n });\n };\n codeBlock.parentElement.style.position = 'relative';\n codeBlock.parentElement.appendChild(btn);\n });\n }\n \n addCopyButtons();\n \n // Re-run on dynamic content\n var observer = new MutationObserver(addCopyButtons);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Add Copy Buttons to Code Blocks");
}
} catch(__e) { console.warn('[Userscript:Add Copy Buttons to Code Blocks]', __e); }
})();
(function(){
try {
var __m = "github.com";
var __re = new RegExp('^' + "github\\.com" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Force GitHub README to respect dark mode\n(function() {\n var style = document.createElement('style');\n style.textContent = '\n .markdown-body {\n color-scheme: dark light;\n }\n .markdown-body pre { background: #161b22 !important; }\n .markdown-body code { background: rgba(110, 118, 129, 0.4) !important; }\n .markdown-body table th, .markdown-body table td { border-color: #30363d !important; }\n .markdown-body img { background: #0d1117; }\n .markdown-body blockquote { border-left-color: #8b949e; }\n .markdown-body hr { border-color: #30363d; }\n ';\n document.head.appendChild(style);\n})();", "GitHub Dark Mode README Fix"); } } catch(__e) { console.warn('[Userscript:GitHub Dark Mode README Fix]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Highlight search terms from Google/DuckDuckGo/Bing referrer\n(function() {\n var ref = document.referrer;\n var terms = [];\n \n if (ref.includes('google.com') || ref.includes('duckduckgo.com') || ref.includes('bing.com')) {\n var url = new URL(ref);\n var q = url.searchParams.get('q') || url.searchParams.get('p');\n if (q) {\n terms = q.split(/\\s+/).filter(function(t) { return t.length > 2; });\n }\n }\n \n if (terms.length === 0) return;\n \n var style = document.createElement('style');\n style.textContent = '.userscript-highlight { background: #fbbf24; color: #1a1a2e; padding: 1px 3px; border-radius: 2px; }';\n document.head.appendChild(style);\n \n function highlight(node) {\n if (node.nodeType === 3) { // text node\n var text = node.textContent;\n var found = false;\n terms.forEach(function(term) {\n var regex = new RegExp('(' + term.replace(/[.*+?^${}()|[\\]\\\\]/g, '\\\\') + ')', 'gi');\n if (regex.test(text)) {\n found = true;\n var frag = document.createDocumentFragment();\n var parts = text.split(regex);\n parts.forEach(function(part, i) {\n if (i % 2 === 0) {\n frag.appendChild(document.createTextNode(part));\n } else {\n var span = document.createElement('span');\n span.className = 'userscript-highlight';\n span.textContent = part;\n frag.appendChild(span);\n }\n });\n node.parentNode.replaceChild(frag, node);\n }\n });\n } else if (node.nodeType === 1 && node.childNodes) { // element\n var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT'];\n if (!skipTags.includes(node.tagName)) {\n Array.from(node.childNodes).forEach(highlight);\n }\n }\n }\n \n highlight(document.body);\n \n // Re-highlight on dynamic content\n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1 || node.nodeType === 3) highlight(node);\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Highlight Search Terms"); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Strip utm_, fbclid, gclid, etc. from all links on page\n(function() {\n var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content',\n 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid',\n 'ref', 'ref_src', 'source', 'medium', 'campaign'];\n \n function cleanUrl(url) {\n try {\n var u = new URL(url, window.location.origin);\n var changed = false;\n trackingParams.forEach(function(p) {\n if (u.searchParams.has(p)) {\n u.searchParams.delete(p);\n changed = true;\n }\n });\n return changed ? u.toString() : url;\n } catch (e) {\n return url;\n }\n }\n \n function cleanLinks() {\n document.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n \n cleanLinks();\n \n var observer = new MutationObserver(function(mutations) {\n mutations.forEach(function(m) {\n m.addedNodes.forEach(function(node) {\n if (node.nodeType === 1) {\n if (node.tagName === 'A') cleanLinks();\n node.querySelectorAll('a[href]').forEach(function(a) {\n var clean = cleanUrl(a.href);\n if (clean !== a.href) a.href = clean;\n });\n }\n });\n });\n });\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "Remove Tracking Parameters from Links"); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Auto-enable theater mode on YouTube\n(function() {\n function tryTheater() {\n var btn = document.querySelector('button[aria-label=\"Theater mode\"], ytd-player #player button[title=\"Theater mode\"]');\n if (btn && !btn.classList.contains('activated')) {\n btn.click();\n }\n }\n \n // Try immediately\n tryTheater();\n \n // Try after navigation (SPA)\n var lastUrl = location.href;\n setInterval(function() {\n if (location.href !== lastUrl) {\n lastUrl = location.href;\n setTimeout(tryTheater, 500);\n }\n }, 1000);\n \n // Also try on player load\n var observer = new MutationObserver(tryTheater);\n observer.observe(document.body, { childList: true, subtree: true });\n})();", "YouTube Theater Mode Default"); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Remove or un-stick sticky/fixed headers that block content\n(function() {\n function unstick() {\n document.querySelectorAll('header, nav, [role=\"banner\"], .header, .navbar, .sticky, .fixed-top, [style*=\"position: fixed\"], [style*=\"position:sticky\"]').forEach(function(el) {\n if (el.style.position === 'fixed' || el.style.position === 'sticky' || \n getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') {\n el.style.position = 'static';\n el.style.top = 'auto';\n el.style.zIndex = 'auto';\n }\n });\n }\n \n unstick();\n \n var observer = new MutationObserver(unstick);\n observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] });\n})();", "Kill Sticky Headers"); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + '
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages

, 'i'); if (__m === '*' || __re.test(location.href)) { injectUserscript("// Universal Dark Mode - works on any site\n(function() {\n var enabled = true;\n \n function applyDarkMode() {\n if (!enabled) return;\n \n // Create style element if it doesn't exist\n var style = document.getElementById('universal-dark-mode-style');\n if (!style) {\n style = document.createElement('style');\n style.id = 'universal-dark-mode-style';\n document.head.appendChild(style);\n }\n \n // Dark mode CSS - inverts colors but preserves images/video\n style.textContent = '\n /* Invert everything except media */\n html {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #1a1a2e !important;\n }\n \n /* Restore images, videos, iframes, canvas */\n img, video, iframe, canvas, svg, picture, [style*=\"background-image\"] {\n filter: invert(1) hue-rotate(180deg) !important;\n }\n \n /* Preserve specific elements that should not be inverted */\n .no-dark-mode, .no-dark-mode *,\n [data-theme=\"light\"], [data-theme=\"light\"],\n .ace_editor, .ace_editor *,\n .CodeMirror, .CodeMirror *,\n .monaco-editor, .monaco-editor *,\n .markdown-body pre, .markdown-body pre *,\n .highlight, .highlight *,\n pre code, pre code * {\n filter: none !important;\n }\n \n /* Fix common UI elements */\n .modal, .popup, .dropdown-menu, .tooltip, .popover {\n filter: invert(1) hue-rotate(180deg) !important;\n background: #2d2d44 !important;\n border-color: #444 !important;\n }\n \n /* Scrollbars */\n ::-webkit-scrollbar { background: #1a1a2e !important; }\n ::-webkit-scrollbar-thumb { background: #444 !important; }\n ::-webkit-scrollbar-thumb:hover { background: #555 !important; }\n \n /* Selection */\n ::selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ::-moz-selection { background: #4ecdc4 !important; color: #1a1a2e !important; }\n ';\n }\n \n function removeDarkMode() {\n var style = document.getElementById('universal-dark-mode-style');\n if (style) style.remove();\n }\n \n // Toggle with Alt+Shift+D\n document.addEventListener('keydown', function(e) {\n if (e.altKey && e.shiftKey && e.key === 'D') {\n e.preventDefault();\n enabled = !enabled;\n if (enabled) {\n applyDarkMode();\n console.log('[Universal Dark Mode] Enabled');\n } else {\n removeDarkMode();\n console.log('[Universal Dark Mode] Disabled');\n }\n }\n });\n \n // Apply on load\n applyDarkMode();\n \n // Re-apply on dynamic content\n var observer = new MutationObserver(function(mutations) {\n if (enabled && !document.getElementById('universal-dark-mode-style')) {\n applyDarkMode();\n }\n });\n observer.observe(document.head, { childList: true });\n \n console.log('[Universal Dark Mode] Loaded - Press Alt+Shift+D to toggle');\n})();", "Universal Dark Mode"); } } catch(__e) { console.warn('[Userscript:Universal Dark Mode]', __e); } })(); })();
Skip to content

Repository files navigation

ActiveModel::Serializer

Build Status

ActiveModel::Serializer brings convention over configuration to your JSON generation.

AMS does this through two components: serializers and adapters. Serializers describe which attributes and relationships should be serialized. Adapters describe how attributes and relationships should be serialized.

By default AMS will use the Flatten Json Adapter. But we strongly advise you to use JsonApi Adapter that follows 1.0 of the format specified in jsonapi.org/format. Check how to change the adapter in the sections bellow.

RELEASE CANDIDATE, PLEASE READ

This is the master branch of AMS. It will become the 0.10.0 release when it's ready. Currently this is a release candidate. This is not backward compatible with 0.9.0 or 0.8.0.

0.10.x will be based on the 0.8.0 code, but with a more flexible architecture. We'd love your help. Learn how you can help here.

Example

Given two models, a Post(title: string, body: text) and a Comment(name:string, body:text, post_id:integer), you will have two serializers:

classPostSerializer < ActiveModel::Serializercachekey: 'posts',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:posturl[:post,:comment]end

Generally speaking, you as a user of AMS will write (or generate) these serializer classes. If you want to use a different adapter, such as a JsonApi, you can change this in an initializer:

ActiveModel::Serializer.config.adapter=ActiveModel::Serializer::Adapter::JsonApi

or

ActiveModel::Serializer.config.adapter=:json_api

You won't need to implement an adapter unless you wish to use a new format or media type with AMS.

If you want to have a root key on your responses you should use the Json adapter, instead of the default FlattenJson:

ActiveModel::Serializer.config.adapter=:json

If you would like the key in the outputted JSON to be different from its name in ActiveRecord, you can use the :key option to customize it:

classPostSerializer < ActiveModel::Serializerattributes:id,:body# look up :subject on the model, but use +title+ in the JSONattribute:subject,:key=>:titlehas_many:commentsend

In your controllers, when you use render :json, Rails will now first search for a serializer for the object and use it if available.

classPostsController < ApplicationControllerdefshow@post=Post.find(params[:id])renderjson: @postendend

In this case, Rails will look for a serializer named PostSerializer, and if it exists, use it to serialize the Post.

Specify a serializer

If you wish to use a serializer other than the default, you can explicitly pass it to the renderer.

1. For a resource:

renderjson: @post,serializer: PostPreviewSerializer

2. For an array resource:

# Use the default `ArraySerializer`, which will use `each_serializer` to# serialize each elementrenderjson: @posts,each_serializer: PostPreviewSerializer# Or, you can explicitly provide the collection serializer as wellrenderjson: @posts,serializer: PaginatedSerializer,each_serializer: PostPreviewSerializer

Meta

If you want a meta attribute in your response, specify it in the render call:

renderjson: @post,meta: {total: 10}

The key can be customized using meta_key option.

renderjson: @post,meta: {total: 10},meta_key: "custom_meta"

meta will only be included in your response if you are using an Adapter that supports root, as JsonAPI and Json adapters, the default adapter (FlattenJson) doesn't have root.

Overriding association methods

If you want to override any association, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefcommentsobject.comments.activeendend

Overriding attribute methods

If you want to override any attribute, you can use:

classPostSerializer < ActiveModel::Serializerattributes:id,:bodyhas_many:commentsdefbodyobject.body.downcaseendend

Built in Adapters

FlattenJSON

It's the default adapter, it generates a json response without a root key. Doesn't follow any specifc convention.

JSON

It also generates a json response but always with a root key. The root key can't be overridden, and will be automatically defined accordingly with the objects being serialized. Doesn't follow any specifc convention.

JSONAPI

This adapter follows 1.0 of the format specified in jsonapi.org/format. It will include the associated resources in the "included" member when the resource names are included in the include option.

render@posts,include: ['authors','comments']# orrender@posts,include: 'authors,comments'

Installation

Add this line to your application's Gemfile:

gem 'active_model_serializers'

And then execute:

$ bundle

Creating a Serializer

The easiest way to create a new serializer is to generate a new resource, which will generate a serializer at the same time:

$ rails g resource post title:string body:string

This will generate a serializer in app/serializers/post_serializer.rb for your new model. You can also generate a serializer for an existing model with the serializer generator:

$ rails g serializer post

The generated seralizer will contain basic attributes and has_many/has_one/belongs_to declarations, based on the model. For example:

classPostSerializer < ActiveModel::Serializerattributes:title,:bodyhas_many:commentshas_one:authorurl:postend

and

classCommentSerializer < ActiveModel::Serializerattributes:name,:bodybelongs_to:post_idurl[:post,:comment]end

The attribute names are a whitelist of attributes to be serialized.

The has_many, has_one, and belongs_to declarations describe relationships between resources. By default, when you serialize a Post, you will get its Comments as well.

You may also use the :serializer option to specify a custom serializer class, for example:

has_many:comments,serializer: CommentPreviewSerializer

And you can change the JSON key that the serializer should use for a particular association:

has_many:comments,key: :reviews

The url declaration describes which named routes to use while generating URLs for your JSON. Not every adapter will require URLs.

Caching

To cache a serializer, call cache and pass its options. The options are the same options of ActiveSupport::Cache::Store, plus a key option that will be the prefix of the object cache on a pattern "#{key}/#{object.id}-#{object.updated_at}".

The cache support is optimized to use the cached object in multiple request. An object cached on a show request will be reused at the index. If there is a relationship with another cached serializer it will also be created and reused automatically.

[NOTE] Every object is individually cached.

[NOTE] The cache is automatically expired after update an object but it's not deleted.

cache(options=nil)# options: ```{key, expires_in, compress, force, race_condition_ttl}```

Take the example bellow:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hoursattributes:title,:bodyhas_many:commentsurl:postend

On this example every Post object will be cached with the key "post/#{post.id}-#{post.updated_at}". You can use this key to expire it as you want, but in this case it will be automatically expired after 3 hours.

Fragmenting Caching

If there is some API endpoint that shouldn't be fully cached, you can still optimise it, using Fragment Cache on the attributes and relationships that you want to cache.

You can define the attribute by using only or except option on cache method.

[NOTE] Cache serializers will be used at their relationships

Example:

classPostSerializer < ActiveModel::Serializercachekey: 'post',expires_in: 3.hours,only: [:title]attributes:title,:bodyhas_many:commentsurl:postend

Getting Help

If you find a bug, please report an Issue.

If you have a question, please post to Stack Overflow.

Thanks!

Contributing

See CONTRIBUTING.md

About

ActiveModel::Serializer implementation and Rails hooks

Resources

Contributing

Stars

0 stars

Watchers

2 watching

Forks

Releases

Packages

Contributors

Languages