2016-02-25 36 views
2

快速问题在这里。尝试搜索无济于事。主动模型串行器 - 自定义JSON响应

我正在努力为当前项目获得RESTful API。我发现Rails是这个目标的绝对宠儿,所以请检查另一个标记为rails的超棒!

但是我已经遇到了障碍,同时设计了/用户我目前的API响应这是一个本应返回用户对象的JSON数组的方法:

我的用户模型:

class User < ActiveRecord::Base 

    devise :database_authenticatable, :registerable, :recoverable, :rememberable, :trackable, :validatable 

    has_many :favorites 
    has_many :reservations 

    has_many :venues, through: :favorites 
    has_many :venues, through: :reservations 

    belongs_to :gender 
    belongs_to :city 
    belongs_to :role 
    has_one :avatar 

    has_many :payments 
    has_one :payment_history 

    has_many :promotion_claims 
    has_many :social_identifiers 

end 

我的路线:

Rails.application.routes.draw do 

    namespace :api, defaults: { format: :json } do 
    namespace :v1 do 
     devise_for :users 

     .......................... 

     resources :roles 
     resources :genders 
     resources :cities 

     #Users method 
     get 'users', to: "users#index" 

    end 
    end 

我的控制器:

class API::V1::UsersController < API::V1::ApplicationController 
    before_action :set_address, only: [:show, :edit, :update, :destroy] 

    # GET /users 
    # GET /users.json 
    def index 
    @users = User.all 
    render json: @users 
    end 
end 

我的串行:

class UserSerializer < ActiveModel::Serializer 
    attributes :id, :first_name, :last_name, :cellphone, :email, :birthday, :username 
    has_one :gender 
    has_one :city 
    has_one :role 
end 

class GenderSerializer < ActiveModel::Serializer 
    attributes :name 
end 

class CitySerializer < ActiveModel::Serializer 
    attributes :name 
end 

class RoleSerializer < ActiveModel::Serializer 
    attributes :name 
end 

以此为据达到一个相当令人满意的结果如我所得到的JSON响应:

// GET http://localhost:3000/api/v1/users 

[ 
    { 
    "id": 1, 
    "first_name": "Richmond", 
    "last_name": "Huels", 
    "cellphone": "29 8244 9100", 
    "email": "[email protected]", 
    "birthday": "2011-02-23T19:24:00.151Z", 
    "username": "alba.ortiz", 
    "gender": { 
     "name": "Male" 
    }, 
    "city": { 
     "name": "San Pedro Garza García" 
    }, 
    "role": { 
     "name": "admin" 
    } 
    }, 

不过,我想我的JSON响应要更多的东西像:

// 20160225162402 
// GET http://localhost:3000/api/v1/users 

[ 
    { 
    "id": 1, 
    "first_name": "Richmond", 
    "last_name": "Huels", 
    "cellphone": "29 8244 9100", 
    "email": "[email protected]", 
    "birthday": "2011-02-23T19:24:00.151Z", 
    "username": "alba.ortiz", 
    "gender": "Male", 
    "city": "San Pedro Garza García", 
    "role": "rp" 
    }, 

我试着覆盖UserSerializer中的属性方法,并使它,所以我可以做任何我w蚂蚁与json哈希返回之前,但它没有工作:

#attributes override to get the right format for the response 
    def attributes 
    data = super 
    data[:city] = data[:city][:name] 
    data[:gender] = data[:gender][:name] 
    data[:role] = data[:city][:name] 
    data 
    end 

有没有什么办法来实现我需要我的API?

谢谢红宝石主义者,你统治并保持惊人!

回答

1

我想通了:

我觉得这是因为哈克方法基本上,我没有使用与我的用户模型相关的模型的序列化程序,并且我重写了属性方法,但是我所做的是从用户序列化程序中删除了所有关系,然后完全按照我写的那样覆盖了属性它之前:

class UserSerializer < ActiveModel::Serializer 
    attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role 

    def attributes 
    data = super 
    data[:gender] = data[:gender][:name] 
    data[:city] = data[:city][:name] 
    data[:role] = data[:role][:name] 
    data 
    end 
end 

这让我的JSON响应,我需要完美:

enter image description here

编辑:我发现了一个更好的方法:

我的串行:

class UserSerializer < ActiveModel::Serializer 
    attributes :id, :first_name, :last_name, :gender, :cellphone, :city, :email, :birthday, :username, :role 

    def gender 
    return object.gender.name 
    end 

    def city 
    return object.city.name 
    end 

    def role 
    return object.role.name 
    end 

end 

在我看来,更清洁和更面向对象。

确保所有其他序列化器都已到位,并且模型对其字段具有适当的验证。

的结果是完全一样的:

enter image description here

0

如果你想合并结果到单个散列。

您可以使用展平方法,例如。

s = [ 1, 2, 3 ]   #=> [1, 2, 3] 
t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] 
a = [ s, t, 9, 10 ]  #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] 
a.flatten     #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] 

在你的情况下,让所有的结果,并把它传递给变量“数据”后

data.flatten