copy-edit viget posts
This commit is contained in:
@@ -2,7 +2,6 @@
|
||||
title: "Simple APIs using SerializeWithOptions"
|
||||
date: 2009-07-09T00:00:00+00:00
|
||||
draft: false
|
||||
needs_review: true
|
||||
canonical_url: https://www.viget.com/articles/simple-apis-using-serializewithoptions/
|
||||
---
|
||||
|
||||
@@ -12,14 +11,14 @@ serialization system, while expressive, requires entirely too much
|
||||
repetition. As an example, keeping a speaker's email address out of an
|
||||
API response is simple enough:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
```ruby
|
||||
@speaker.to_xml(:except => :email)
|
||||
```
|
||||
|
||||
But if we want to include speaker information in a talk response, we
|
||||
have to exclude the email attribute again:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
```ruby
|
||||
@talk.to_xml(:include => { :speakers => { :except => :email } })
|
||||
```
|
||||
|
||||
@@ -27,61 +26,60 @@ Then imagine that a talk has a set of additional directives, and the API
|
||||
responses for events and series include lists of talks, and you can see
|
||||
how our implementation quickly turned into dozens of lines of repetitive
|
||||
code strewn across several controllers. We figured there had to be a
|
||||
better way, so when we couldn\'t find one, we
|
||||
created [SerializeWithOptions](https://github.com/vigetlabs/serialize_with_options).
|
||||
better way, so when we couldn't find one, we created [SerializeWithOptions](https://github.com/vigetlabs/serialize_with_options).
|
||||
|
||||
At its core, SerializeWithOptions is a simple DSL for describing how to
|
||||
turn an ActiveRecord object into XML or JSON. To use it, put
|
||||
a `serialize_with_options` block in your model, like so:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks
|
||||
end
|
||||
# ...
|
||||
end
|
||||
```ruby
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks
|
||||
end
|
||||
# ...
|
||||
end
|
||||
|
||||
class Talk < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating
|
||||
except :creator_id
|
||||
includes :speakers, :event, :series
|
||||
end
|
||||
# ...
|
||||
class Talk < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating
|
||||
except :creator_id
|
||||
includes :speakers, :event, :series
|
||||
end
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
With this configuration in place, calling `@speaker.to_xml` is the same
|
||||
as calling:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
```ruby
|
||||
@speaker.to_xml(
|
||||
:methods => [:average_rating, :avatar:url],
|
||||
:except => [:email, :claim_code],
|
||||
:include => {
|
||||
:talks => {
|
||||
:methods => :average_rating,
|
||||
:except => :creator_id
|
||||
}
|
||||
}
|
||||
:methods => [:average_rating, :avatar:url],
|
||||
:except => [:email, :claim_code],
|
||||
:include => {
|
||||
:talks => {
|
||||
:methods => :average_rating,
|
||||
:except => :creator_id
|
||||
}
|
||||
}
|
||||
)
|
||||
```
|
||||
|
||||
Once you've defined your serialization options, your controllers will
|
||||
end up looking like this:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
def show
|
||||
@post = Post.find(params[:id]) respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @post }
|
||||
format.json { render :json => @post }
|
||||
end
|
||||
```ruby
|
||||
def show
|
||||
@post = Post.find(params[:id]) respond_to do |format|
|
||||
format.html
|
||||
format.xml { render :xml => @post }
|
||||
format.json { render :json => @post }
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
@@ -93,21 +91,21 @@ one, remove your last excuse.
|
||||
to handle some real-world scenarios we've encountered. You can now
|
||||
specify multiple `serialize_with_options` blocks:
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks
|
||||
end
|
||||
|
||||
serialize_with_options :with_email do
|
||||
methods :average_rating, :avatar_url
|
||||
except :claim_code
|
||||
includes :talks
|
||||
end
|
||||
# ...
|
||||
```ruby
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks
|
||||
end
|
||||
|
||||
serialize_with_options :with_email do
|
||||
methods :average_rating, :avatar_url
|
||||
except :claim_code
|
||||
includes :talks
|
||||
end
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
@@ -119,15 +117,15 @@ the same name if available, otherwise it will use the default.
|
||||
Additionally, you can now pass a hash to `:includes` to set a custom
|
||||
configuration for included models
|
||||
|
||||
``` {.code-block .line-numbers}
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks => { :include => :comments }
|
||||
end
|
||||
# ...
|
||||
```ruby
|
||||
class Speaker < ActiveRecord::Base
|
||||
# ...
|
||||
serialize_with_options do
|
||||
methods :average_rating, :avatar_url
|
||||
except :email, :claim_code
|
||||
includes :talks => { :include => :comments }
|
||||
end
|
||||
# ...
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
Reference in New Issue
Block a user