mirror of
https://github.com/wahyd4/wahyd4.github.com.git
synced 2026-08-10 05:47:00 +10:00
- 308 posts reverse-extracted from wahyd4.github.com (Hexo 6.3.0 + NexT 8.25) - Hexo project with NexT theme, reading-experience custom styles - publish-post.sh: write post -> hexo build -> PR (master untouched)
105 lines
4.5 KiB
Markdown
105 lines
4.5 KiB
Markdown
---
|
|
title: "在Rails中使用 active_model_serializers 构建json response"
|
|
date: 2015-03-21 10:35:00
|
|
tags: [ruby, json]
|
|
---
|
|
|
|
Rails 本身提供很不错的json response功能,可以很方便的将model对象自动转换为json数据。如果我们期望返回的结果很简单也可以构建一个简单的hash,自行编辑你希望的key和value,由Rails 来帮你生成json。那如果是介于两者之间的情况呢?
|
|
|
|
- 我希望将我的model以json的形式返回,但是我并不希望将所有的字段返回。
|
|
- 我希望将我的model中部分属性进行稍微的处理和计算后返回,这样客户端可以直接使用某些字段,而不需要将应用自身的逻辑暴露给客户端,如我有个model记录微信支付属性,有个字段是关于微信支付(”trade\_status”),它的值有trade\_success, “wait\_for\_payment”,显然我们可以返回给客户端 “支付成功”,”等待支付”更好。传统的做法,我们为了达到这个目的,我们不仅需要将trade\_stauts进行构建,还需要将其他参数也重复写出来。
|
|
|
|
ActiveModel::Serializers这个gem 包就可以更好的帮助我们解决上面的痛点,我们只需要对需要返回的属性列举出来,只对需要更改的属性进行计算,其他都不需要了。下面就介绍下它的一些常见用法。
|
|
|
|
首先安装Gem
|
|
|
|
```ruby
|
|
gem 'active_model_serializers'
|
|
```
|
|
|
|
为了可以在我们的rails 项目中使用它,我们还需要在application controller中添加:
|
|
|
|
```ruby
|
|
include ActionController::Serialization
|
|
```
|
|
|
|
active\_model\_serializers的使用就是在你是需要返回json的地方,为你的数据创建serializer,你的对象就能通过serializer变成希望的结果。这里假设我有一个User用户对象,User的的大致结构:
|
|
|
|
```ruby
|
|
class User
|
|
field :nick_name, type: String
|
|
field :email, type: String
|
|
field :age, type: Integer
|
|
field :password, type:String
|
|
# 等等更多属性。。。
|
|
end
|
|
```
|
|
|
|
我现在有个UserController,需要以JSON的形式返回用户的基本信息: 昵称,邮箱,是否成年(大于等于18岁算成年),接下来在app 目录下创建serializers 目录,并创建class UserSerializer对象,继承自 ActiveModel::Serializer, 然后我们的serializer就应该是这样:
|
|
|
|
```ruby
|
|
class UserSerializer ActiveModel::Serializer
|
|
attributes :nick_name, :email, :if_adult
|
|
|
|
def if_adult
|
|
object.age > 18 #object 就是需要被序列化的对象
|
|
end
|
|
end
|
|
```
|
|
|
|
在serializer中,我们只需要将我们需要的属性通过attributes 的形式列出来,如果model没有的属性,我们需要自行实现该方法。
|
|
我们也可以覆盖属性,如上的例子,我们也可以将if\_adult 改成age,同样我们需要有:
|
|
|
|
```ruby
|
|
def age
|
|
object.age > 18
|
|
end
|
|
```
|
|
|
|
接下来完成我们的最后一步,在controller中使用serializer
|
|
|
|
```ruby
|
|
class UserController ApplicationController
|
|
def show
|
|
#假设 @user 是我们经过查询后得到的对象
|
|
render json: @user, serializer: UserSerializer
|
|
end
|
|
|
|
def index
|
|
#假设 @users 是我们经过查询后得到的对象
|
|
render json: @user, each_serializer: UserSerializer
|
|
end
|
|
end
|
|
```
|
|
|
|
我们我们希望对一个数组对象进行序列化,我们则需要使用each\_serializer,使用该属性后,你的返回结果将变成对象,数组则包裹下对象之下。本例则类似于
|
|
|
|
```json
|
|
users: [
|
|
{},
|
|
{}
|
|
]
|
|
```
|
|
|
|
这里的”users”这是json的根属性, serializer支持用户自定义根属性,
|
|
|
|
```ruby
|
|
render json: @user, serializer: UserSerializer, root: 'customer'
|
|
```
|
|
|
|
我非常喜欢active model serializers 的一个属性是,支持在serializer中访问你希望的属性,在rails 中,很多时候我们希望访问current\_user对象,获取当前登录用户的相关信息。那serializer 则可以很好的做的这一点,在active model serializers 中有 serialization\_scope 这样一个方法,在application controller 中声明此方法,传入你希望的参数,便可以在serializer class 中自由访问该对象。解决了serializer 与其他对象交互的问题。
|
|
|
|
```ruby
|
|
serialization_scope :current_user
|
|
```
|
|
|
|
在serializer中, scope 对象便是注入的 current\_user对象
|
|
|
|
```ruby
|
|
scope.email
|
|
```
|
|
|
|
此外,active model serializers 支持在返回的json中额外注入meta属性,这样既保留了serializer的简单,模板化,也增添了自由度,使得用户可以自行添加一些额外的属性。
|
|
|
|
更详细的使用还请参考:[Github](https://github.com/rails-api/active_model_serializers)
|