2016-02-25 2 views
2

Быстрый вопрос здесь. Пробовал поиск безрезультатно.Сериализаторы активной модели - Настройка ответа JSON

Я работаю над тем, чтобы получить RESTful API с земли для моего текущего проекта. Я нашел 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 и сделать это так, что я могу делать все, что я ш муравей с 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

Я понял это:

Я чувствую, что это Hacky подход, поскольку в основном, я не использую сериализаторы для моделей, связанных с моей моделью пользователя, и я переопределяю метод атрибутов, но то, что я сделал, это то, что я удалил все отношения из моего сериализатора User, после чего я перегрузил атрибуты точно так, как писал до:

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

EDIT: Я нашел еще лучший способ:

Мой сериализатору:

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

Если вы хотите объединить результат в один хэш.

Вы можете использовать flatten method, пример.

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 
Смежные вопросы