Неверное количество аргументов 0 для 1, невозможно сериализовать модель с помощью устройства

Я пытаюсь создать API для моего приложения rails в папке Controllers. Я создал следующую структуру папок.

контроллеры> API> v1

мои маршруты выглядят примерно так: api_constraints

MyApp::Application.routes.draw do
  devise_for :users

  resources :users

  ......
   other resources and matching for the standard application
  ......

  # Api definition
  namespace :api, defaults: { format: :json },constraints: { subdomain: 'api' }, path: '/'  do
    scope module: :v1,constraints: ApiConstraints.new(version: 1, default: true) do
      resources :sessions, :only => [:create]
      resources :users, :only => [:show]
    end
  end
end

Я получаю одинаковую ошибку как в моих сеансах, так и в контроллерах пользователей. Я просто выложу пользовательский контроллер, потому что он короче

class Api::V1::UsersController < ApiController
  respond_to :json

  def show
    respond_with User.find(params[:id])
  end
end

Тогда мои тесты

require 'spec_helper'

describe Api::V1::UsersController do

  describe "GET #show" do
    before(:each) do
      @user = FactoryGirl.create :user
      get :show, id: @user.id, format: :json
    end

    it "returns the information about a reporter on a hash" do
      user_response = JSON.parse(response.body, symbolize_names: true)
      expect(user_response[:email]).to eql @user.email
    end

    it { should respond_with 200 }
  end
end

И результат теста

4) Api::V1::UsersController GET #show Ошибка / Ошибка: get:show, id: @user.id, формат::json ArgumentError: неверное количество аргументов (0 для 1)

Две проблемы: 1) по какой-то причине идентификатор не отправляется в действие API 2) я не уверен, как добраться до API. Я думал, что это должен быть api.localhost:3000/users/1

Заранее благодарю за любую помощь

Обновление Это вывод для рейковых маршрутов.

api_sessions POST   /sessions(.:format)                         api/v1/sessions#create {:format=>:json, :subdomain=>"api"}

api_user GET    /users/:id(.:format)                        api/v1/users#show {:format=>:json, :subdomain=>"api"}

Обновление 2 Это выглядит как дубликат для неправильного количества аргументов (0 для 1) при создании моего пользователя

К сожалению, решение этого поста не вариант для меня. Я не могу удалить Devise, потому что модель User совместно используется в стандартном приложении Web rails и в части API приложения.

Обновление 3 Я искал другие способы иметь API со стандартным приложением, и использование devise with doorkeeper кажется лучшим решением, чем аутентификация токена. После настройки я снова в той же ситуации

неверное количество аргументов (0 для 1)

В выводе сервера я вижу следующий вывод. Это с действительным идентификатором пользователя.

Started GET "/api/v1/users/1" for ::1 at 2015-07-27 20:52:09 +0100 
Processing by Api::V1::UsersController#show as */*   
Parameters: {"id"=>"1"} 
Geokit is using the domain: localhost   
User Load (0.4ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 1]] 
Completed 500 Internal Server Error in 21ms

ArgumentError (wrong number of arguments (0 for 1)):   app/controllers/api/v1/users_controller.rb:5:in `show'

С неверным идентификатором я получаю этот вывод

Started GET "/api/v1/users/134" for ::1 at 2015-07-27 20:55:36 +0100     
Processing by Api::V1::UsersController#show as */*   
Parameters: {"id"=>"134"} 
Geokit is using the domain: localhost   
User Load (0.5ms)  SELECT  "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1  [["id", 134]] 
Completed 500 Internal Server Error in 6ms

NoMethodError (undefined method `api_error' for
#<Api::V1::UsersController:0x007fc5a17bf098>):   app/controllers/api_controller.rb:23:in `not_found'

Обновление 4 После вставки некоторых операторов отладки идентификатор передается в действие контроллера, а пользователь извлекается из базы данных.

Вопрос с

respond_with User.find(params[:id])

rails не может сериализовать пользователя. Я попытался заменить пользователя другой моделью, для которой не включен Devise, и он может сериализовать модель. Я не уверен, почему устройство вызывает проблему здесь.

2 ответа

Решение

Мне потребовалось некоторое время, чтобы найти решение, и вы можете проследить, о чем я думал из поста выше.

В конце я проследил проблему до того, что модель, использующую devise, не может быть сериализована как обычная модель. Вы не можете просто использовать

respont_with User.first 

или что-нибудь в этом роде. Devise отключает метод to_json по умолчанию для activerecord.

Во многих решениях говорилось о перезаписи метода to_json или использовании JBuilder в модели. Мне это не понравилось, потому что это ограничило бы возможные атрибуты, которые вы могли бы вернуть.

Посмотрев документацию по to_json, я решил, что просто передать атрибуты, которые я хотел в опциях, было именно то, что я хотел.

def show
  respond_with User.find(params[:id]).as_json(only: [:id, :name])
end

1: Убедитесь, что в консоли FactoryGirl может правильно возвращать пользовательский объект, созданный из вашей пользовательской фабрики, чтобы он не равнялся нулю в вашем запросе на получение.

2: Запустите Rake Routes, чтобы проверить, как API генерирует маршруты своего генерации. Я предполагаю, что если вы ранее не настраивали это, вам нужно отредактировать файл hosts или использовать что-то вроде pow на mac или nginx w/ dnsmasq в Linux, чтобы включить поддержку поддоменов в вашей локальной среде разработки. Затем вручную протестируйте свой контроллер API по любому субдомену, который вы настроили, например, по Jeff Atwood чтобы убедиться, что вы видите, как он получает действительный ответ JSON с этого URL.

Немного более чистый пример пространства имен API в маршрутах:

namespace :api, :path => "", :constraints => {:subdomain => "api"} do
  namespace :v1, defaults: { format: 'json' } do

  ...

  end
end
Другие вопросы по тегам