copy-edit viget posts

This commit is contained in:
David Eisinger
2023-10-24 20:48:09 -04:00
parent 0438a6d828
commit f86f391e82
77 changed files with 1663 additions and 1380 deletions

View File

@@ -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
```