自定义属性未在Active Model Serializer中显示

时间:2016-06-07 22:10:24

标签: ruby-on-rails active-model-serializers rails-api

当我的序列化程序自定义记录包含自定义字段时,我的字段不完整:

类别序列化器:

class CategorySerializer < ApplicationSerializer
  attributes :id, :name, :localized_name, :picture, :status, :visible, :country

def localized_name
  I18n.t((object.name + '_name').to_sym)
end

end

Match Serializer:

class MatchSerializer < ApplicationSerializer
  attributes :id, :player1, :player2, :match_type, :status, :winner, :score, :match_categories

  def match_categories
    #adds international category array to the intersection of player1 and player2 category arrays
    #this is done so that players playing against other countries player will allways
    #play at least international categories and any other categories common to both

    Category.where(country_id: 1) +
(Category.where(country_id: object.player1.country) & Category.where(country_id: object.player2.country))
  end

end

渲染类别时,我将完整字段作为JSON响应:

{
  "data": [
    {
      "id": "1",
      "type": "categories",
      "attributes": {
        "name": "Sports",
        "localized_name": "Deportes",
        "picture": "default_url",
        "status": "active",
        "visible": false,
        "country": {
          "id": 1,
          "name": "International",
          "country_code": "NA",
          "picture": "default_url",
          "language_code": "en",
          "status": "active",
          "visible": false,
          "created_at": "2016-06-06T16:12:29.701Z",
          "updated_at": "2016-06-06T16:12:29.701Z"
        }
      }
    },

渲染匹配时,Match序列化程序将计算匹配中涉及的类别数组,并为每个类别呈现类别信息。但是,如您所见,类别自定义字段:localized_name未包含在内。

>{
  "data": [
    {
      "id": "1",
      "type": "matches",
      "attributes": {
        "player1": {
          "id": 1,
          "provider": "email",
          "uid": "user1@gmail.com",
          "country_id": 2,
          "name": null,
          "first_name": null,
          "last_name": null,
          "gender": null,
          "fb_auth_token": null,
          "nickname": null,
          "image": null,
          "email": "user1@gmail.com",
          "friend_count": null,
          "friends": null,
          "status": "active",
          "premium": null,
          "created_at": "2016-06-06T16:13:58.711Z",
          "updated_at": "2016-06-06T16:14:15.722Z"
        },
        "player2": {
          "id": 2,
          "provider": "email",
          "uid": "user2@gmail.com",
          "country_id": 2,
          "name": null,
          "first_name": null,
          "last_name": null,
          "gender": null,
          "fb_auth_token": null,
          "nickname": null,
          "image": null,
          "email": "user2@gmail.com",
          "friend_count": null,
          "friends": null,
          "status": "active",
          "premium": null,
          "created_at": "2016-06-07T08:03:38.472Z",
          "updated_at": "2016-06-07T08:03:38.611Z"
        },
        "match_type": "Duel",
        "status": "active",
        "winner": null,
        "score": null,
        **"match_categories": [
          {
            "id": 1,
            "country_id": 1,
            "name": "Sports",
            "picture": "default_url",
            "status": "active",
            "visible": false,
            "created_at": "2016-06-06T16:12:29.893Z",
            "updated_at": "2016-06-06T16:12:29.893Z"
          },
          {
            "id": 2,
            "country_id": 2,
            "name": "Futbolistas Peruanos",
            "picture": "default_url",
            "status": "active",
            "visible": false,
            "created_at": "2016-06-06T16:12:29.961Z",
            "updated_at": "2016-06-06T16:12:29.961Z"
          },

如何在此场景中显示localized_name字段?

编辑:请求的控制器。很标准

class MatchesController < ApplicationController
  before_action :set_match, only: [:show, :update, :destroy]

 # GET /matches
  def index
    @matches = Match.all

    render json: @matches
  end

  # GET /matches/1
  def show
    render json: @match
  end

  # POST /matches
  def create
    @match = Match.new(match_params)

    #if player1 not explicitly included will set player1 as uid header of API call
    @match.player1_id ||= current_user.id
    #if player2 parame set as random will generate random user from all curently active users
    if params[:match][:player2_id] == 'random'
      #call model method that returns a random array of userids to play as player 2 but
      #passing player1_id so that method will remove it from possible responses
      #since player1 cannot play itself
      @match.player2_id = @match.active_random_player2(@match.player1_id)
    end

    if @match.save
      render json: @match, status: :created, location: @match
    else
      render json: @match.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /matches/1
  def update
    if @match.update(match_params)

      render json: @match
    else
      render json: @match.errors, status: :unprocessable_entity
    end
  end

  # DELETE /matches/1
  def destroy
    @match.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_match
      @match = Match.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def match_params
  params.require(:match).permit(:player1_id, :player2_id, :match_type, :bet, :status, :winner, :score)
    end
end


class CategoriesController < ApplicationController
  before_action :set_category, only: [:show, :update, :destroy]

  # GET /categories/newmatch
  def newmatch
    @categories = Category.where(country: current_user.country)

    render json: @categories
  end

  # GET /categories
  def index
    if params[:all] && params[:all] != 'false'
      @categories = Category.all
    else
      @categories = Category.where(country: current_user.country)
    end

    render json: @categories

  end

  # GET /categories/1
  def show
    render json: @category
  end

  # POST /categories
  def create

    @category = Category.new(category_params)
    if @category.save!
      render json: @category, status: :created, location: @category
    else
      render json: @category.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /categories/1
  def update
    if @category.update(category_params)
      render json: @category
    else
      render json: @category.errors, status: :unprocessable_entity
    end
  end

  # DELETE /categories/1
  def destroy
    @category.destroy
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_category
      @category = Category.find(params[:id])
    end

    # Only allow a trusted parameter "white list" through.
    def category_params
      #add permitted translation locale parameters based on required translations
      #resource agnostic method in application controller
      params.require(:category).permit(:name, :picture, :status, :visible, :country_id, :all)
    end
end

编辑:

在尝试Francesco Lupo的建议时,我在match_categories查询字段中获取此信息,但我仍然没有获得自定义的localized_name字段。

"match_categories": [
          {
            "object": {
              "id": 1,
              "country_id": 1,
              "name": "Sports",
              "picture": "default_url",
              "status": "active",
              "visible": false,
              "created_at": "2016-07-08T23:11:43.304Z",
              "updated_at": "2016-07-08T23:11:43.304Z"
            },
            "instance_options": {
              "root": false
            },
            "root": false,
            "scope": null
          },

2 个答案:

答案 0 :(得分:3)

您需要序列化每个类别,查询是不够的,也许可以试试这个:

def match_categories
  categories = Category.where(country_id: 1) + (Category.where(country_id: object.player1.country) & Category.where(country_id: object.player2.country))
  categories.map { |category| CategorySerializer.new(category, root: false) }
end

这样,您的所有类别都将被正确序列化。

根据@Augusto评论,可能需要更新active_model_serializer

答案 1 :(得分:1)

由于您正在使用某些自定义方法而不是使用与对象的关系,因此您可能需要在方法中使用CategorySerializer:

def match_categories
   categories = Category.where(country_id: 1) + (Category.where(country_id: object.player1.country) & Category.where(country_id: object.player2.country))
   CategorySerializer.new(categories)
end