【问题标题】:Custom attributes not showing in Active Model Serializer自定义属性未显示在 Active Model Serializer 中
【发布时间】:2016-06-07 22:10:24
【问题描述】:

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

类别序列化器:

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

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

end

匹配序列化器:

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 查询字段中获得了此信息,但我仍然没有获得自定义的本地化名称字段。

"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
          },

【问题讨论】:

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


    【解决方案1】:

    你需要对你的每一个分类进行序列化,查询是不够的,不妨试试这个:

    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

    【讨论】:

    • 嗨。感谢您尝试提供帮助,但这也不起作用。我添加了一个编辑,显示我使用你的建议得到了什么
    • 我今天升级到最新版本的 active_model_serializer (0.10.2),你的答案现在有效!感谢您的帮助!
    • 很高兴能帮上忙!
    【解决方案2】:

    由于您正在执行一些自定义方法而不是使用与对象的关系,因此您可能需要在方法中使用 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
    

    【讨论】:

    • 我已经尝试过您的解决方案,但它输出的内容完全相同。渲染匹配时仍然没有自定义的本地化名称字段。
    • 你能发布你的控制器吗?
    • 在将 ams 升级到 (0.10.2) 后,这个答案几乎可以工作,但由于我的查询返回一个数组而给出了错误。 Francesco Lupo 的回答考虑到了这一点(因此是 map 函数)。无论如何,感谢您的帮助,答案当然适用于其他用例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-09-03
    • 1970-01-01
    • 1970-01-01
    • 2017-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多