0

次のフォルダー構造を作成した Controllers フォルダーに Rails アプリケーションの API を作成しようとしています。

コントローラー > API > v1

私のルートは次のようになります

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, format: :json ArgumentError: 引数の数が間違っています (1 に対して 0)

2 つの問題は、1) 何らかの理由で ID が API アクションに送信されないこと、2) API にアクセスする方法がわからないことです。私はそれが api.localhost:3000/users/1 であるべきだと思った

助けてくれてありがとう

更新 これは rake ルートの出力です

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これは、ユーザーの作成中に間違った数の引数 (1 に対して 0) の重複のように見え ます

残念ながら、この投稿の解決策は私にとって選択肢ではありません。Userモデルが標準のWeb railsアプリとアプリのapi部分で共有されているためDeviseが外せません

更新 3 標準アプリで API を使用する他の方法を検討していましたが、ドアキーパーでデバイスを使用することは、トークン認証よりも優れたソリューションのようです。セットアップした後、同じ状況に戻りました

引数の数が間違っています (1 に対して 0)

サーバー出力には、次の出力が表示されます。これは有効なユーザー ID を使用しています。

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'

無効なIDを使用すると、この出力が得られます

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 いくつかのデバッグ ステートメントを挿入した後、ID がコントローラー アクションに渡され、ユーザーがデータベースから取得されます。

問題は

respond_with User.find(params[:id])

rails はユーザーをシリアライズできません。User を、Devise が有効になっておらず、モデルをシリアル化できる別のモデルに置き換えようとしました。ここでdeviseが問題を引き起こしている理由がわかりません。

4

2 に答える 2

1

1: コンソールで、FactoryGirl がユーザー ファクトリから作成されたユーザー オブジェクトを適切に返すことができることを確認し、それが get 要求で nil にならないようにします。

2: rake routes を実行して、生成された API ルートがどのように見えるかを確認します。以前にこれを設定していない場合は、ホスト ファイルを編集するか、Mac の pow や Linux の nginx w/ dnsmasq などを使用して、ローカル開発環境でサブドメインのサポートを有効にする必要があると思います。次に、 http: //api.myappname.dev/api/v1/users/1.json のように構成したサブドメインで API コントローラーを手動でテストし、その URL から有効な JSON 応答が返されることを確認します。

ルートでの API 名前空間のもう少しわかりやすい例:

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

  ...

  end
end
于 2015-07-07T21:12:31.193 に答える
0

これは解決策を見つけるのにしばらく時間がかかりました.上記の投稿から私が考えていたことをたどることができます.

最終的に、devise を使用したモデルは通常のモデルのようにシリアル化できないという問題を突き止めました。あなたはただ使うことはできません

respont_with User.first 

またはそのようなもの。Devise は、activerecord のデフォルトの to_json メソッドを無効にします。

to_json メソッドを上書きしたり、モデルで JBuilder を使用したりすることについては、多くのソリューションで説明されています。返せる可能性のある属性が制限されるため、私はこれが好きではありませんでした。

to_jsonのドキュメントを読んだ後、オプションで必要な属性を渡すだけで十分だと判断しました。

def show
  respond_with User.find(params[:id]).as_json(only: [:id, :name])
end
于 2015-07-29T19:07:10.753 に答える