活动模型序列化程序 - 路径助手的未定义方法

时间:2016-04-17 20:51:11

标签: active-model-serializers

我正在使用rails-api gem构建一个新应用程序。我正在使用active_model_serializers来自定义我的JSON响应。在尝试向序列化程序添加url属性时,出现错误,指示我的资源的路由助手方法未定义。要遵循的相关代码:

# Routes
Rails.application.routes.draw do
  namespace :api, defaults: { format: 'json' } do
    namespace :v1 do
      resources :tasks, except: [:new, :edit]
    end
  end
end

# Controller - api/v1/tasks_controller.rb
class Api::V1::TasksController < ApplicationController
  before_action :set_task, only: [:show, :update, :destroy]

  # GET /tasks
  # GET /tasks.json
  def index
    @tasks = Task.all

    render json: @tasks
  end

  # GET /tasks/1
  # GET /tasks/1.json
  def show
    render json: @task
  end

  # POST /tasks
  # POST /tasks.json
  def create
    @task = Task.new(task_params)

    if @task.save
      render json: @task, status: :created, location: api_v1_task_path(@task.id)
    else
      render json: @task.errors, status: :unprocessable_entity
    end
  end

  # PATCH/PUT /tasks/1
  # PATCH/PUT /tasks/1.json
  def update
    @task = Task.find(params[:id])

    if @task.update(task_params)
      head :no_content
    else
      render json: @task.errors, status: :unprocessable_entity
    end
  end

  # DELETE /tasks/1
  # DELETE /tasks/1.json
  def destroy
    @task.destroy

    head :no_content
  end

  private

    def set_task
      @task = Task.find(params[:id])
    end

    def task_params
      params.require(:task).permit(:name)
    end
end

# Serializer
class TaskSerializer < ActiveModel::Serializer
  attributes :id, :name, :url

  def url
    api_v1_task_url(object)
  end
end

正如您所看到的,我正在使用命名空间路由并使控制器正常工作。我尝试检索任务时收到undefined method 'api_v1_task_url错误。我无法弄清楚为什么不包括辅助方法。我感到困惑,因为我在添加自定义属性时发现的每个教程都没有对使用这些宝石进行任何调整(rails-apiactive_model_serializers)。

以下是一些更相关的信息:    rails版本:4.2.6    rails-api版本:0.4.0    active_model_serializers版本:0.10.0.rc5

修改:以下是rake routes

的输出
     Prefix Verb    URI Pattern                 Controller#Action
api_v1_tasks GET    /api/v1/tasks(.:format)     api/v1/tasks#index {:format=>"json"}
             POST   /api/v1/tasks(.:format)     api/v1/tasks#create {:format=>"json"}
 api_v1_task GET    /api/v1/tasks/:id(.:format) api/v1/tasks#show {:format=>"json"}
             PATCH  /api/v1/tasks/:id(.:format) api/v1/tasks#update {:format=>"json"}
             PUT    /api/v1/tasks/:id(.:format) api/v1/tasks#update {:format=>"json"}
             DELETE /api/v1/tasks/:id(.:format) api/v1/tasks#destroy {:format=>"json"}

编辑2 :根据以下建议,我尝试了:

# Serializer
class TaskSerializer < ActiveModel::Serializer
  attributes :id, :name, :url

  def url
    link(:self) { api_v1_task_url(object) }
  end
end

收到undefined method 'link'错误。

编辑3: @beauby确实指出我在不正确的地方使用此方法,但正确使用它仍然无法通过序列化方法创建属性,因为我看过工作在许多教程中,例如:http://railscasts.com/episodes/409-active-model-serializers?view=asciicast。它在JSONAPI模式之后创建了一个links属性,虽然它有用而且我会记住,但这不是我想要完成的。

2 个答案:

答案 0 :(得分:4)

您可以将Rails.application.routes.url_helpers添加到TaskSerializer以使用url_helpers。

  class TaskSerializer < ActiveModel::Serializer
    include Rails.application.routes.url_helpers

    attributes :name

    link(:self) { api_v1_task_url(object) }
  end

您还可以使用:json作为ActiveModel适配器并手动添加资源位置。

  class TaskSerializer < ActiveModel::Serializer
    include Rails.application.routes.url_helpers

    attributes :name, :resource_location

    def resource_location 
      api_v1_task_url(object)
    end
  end

答案 1 :(得分:1)

如果您使用的是JsonApi适配器,则无法使用属性定义中的url_helpers,但可以在link内使用它定义如下:

  class TaskSerializer < ActiveModel::Serializer
    attributes :name
    link(:self) { api_v1_task_url(object) }
  end