7

Rails 3 アプリケーション用の JSONP API を作成しようとしています。現在、コントローラーには、次のパターンに従う多くのアクションがあります。

# This is from my users_controller.rb, as an example

def index
  @users = User.all
  respond_with(@users, :callback => params[:callback])
end

:callback => params[:callback]これはそのまま機能しますが、すべてのアクションの への呼び出しでを繰り返さなくて済むように、DRY したいと思いrespond_withます。これどうやってするの?

更新:上記のコードの醜い点の 1 つは、:callback => params[:callback]JSON だけでなく、任意の応答形式に対してオプションが渡されることです。次のコードはおそらくより正確です。

def index
  @users = User.all
  respond_with(@users) do |format|
    format.json { render :json => @users, :callback => params[:callback]}
  end
end

この問題に対処するために考えた方法がいくつかありますが、それらを機能させる方法がわかりません。

  • パラメーターを自動的に含めるオプションをrender受け入れるように (おそらくアプリケーション コントローラーで)オーバーライドします。このようにして、上記のコードを次のように変更できます。これはやや短いです。:jsonp:callback => params[:callback]
def index
  @users = User.all
  respond_with(@users) do |format|
    format.json { render :jsonp => @users}
  end
end
  • to_json私の問題を解決するためにオーバーライドするレスポンダーを作成してください。そうすれば、ブロックを省略して電話をかけるだけrespond_with(@users, :responder => 'MyResponder')で問題を解決できます。または、 plataformatec の Responders gemを使用してアプリケーション レスポンダーにこのコードを含めることもできるので、respond_with(@users)それだけで十分です。
4

5 に答える 5

3

これを行うことができる gem があります: rack-jsonp-middleware

セットアップ手順はサイト上ではほとんどありませんが、それを使用する小さな Rails プロジェクトを作成しました。コミットを見て、ミドルウェアを起動して実行するために何をしたかを確認してください。

https://github.com/rwilcox/rack_jsonp_example

于 2011-04-20T03:38:14.563 に答える
1

これはレスポンダ ソリューションと比べると少し「ローテク」ですが、これを処理するために appliation_controller.rb にプライベート メソッドを作成するだけではどうでしょうか。params 変数が利用可能になり、 @users オブジェクトをそれに渡すことができます。

#application_controller.rb
private
  def jsonp(my_object)
    render :json => my_object, :callback => params[:callback]
  end

#controller
def index
  @users = User.all
  respond_with(@users) do |format|
    format.json { jsonp(@users)}
  end
end
于 2010-12-17T16:54:00.187 に答える
1

今日、#rubyonrails IRC チャンネルで私を助けてくれた samuelkadolph に感謝します。彼はこの要点で解決策を提供し、便宜上以下にコピーしました。

def custom_respond_with(*resources, &block)
  options = resources.extract_options!

  if options[:callback]
    old_block = block
    block = lambda do |format|
      old_block.call(format) if block_given?
      format.json { render :json => [] }
    end
  end

  respond_with(*(resources << options), &block)
end

私のアプリケーションではまだこれを試していませんが、うまくいくはずです。respond_with彼はまた、このメソッドの名前を変更し、定義の最後の行を に変更するだけで、メソッド自体を同様にオーバーライドできることも確認しましたsuper(*(resources << options), &block)

これは私のために働くと思います。しかし、仕事をするためのカスタム レスポンダーの書き方にはまだ興味があります。(それはよりエレガントなソリューションになるでしょう、IMHO。)

更新:アプリケーションでこれを試してみましたが、いくつかの小さな変更で機能します。これは、 JSON リクエストにオプションをprivate自動的に提供するように設計された、ApplicationControllerのセクションで現在使用しているバージョンです。:callback => params[:callback]

def custom_respond_with(*resources, &block)
  options = resources.extract_options!

  if params[:callback]
    old_block = block
    block = lambda do |format|
      old_block.call(format) if block_given?
      format.json { render :json => resources, :callback => params[:callback] }
    end
  end

  respond_with(*(resources << options), &block)
end

それを機能させるには、に変更if options[:callback]する必要があったことに注意してくださいif params[:callback]

于 2010-12-17T22:44:55.443 に答える
0

この回答もご覧ください。基本的に、コントローラーの「デフォルト」の Respond_to を作成して、すべてのアクションをデフォルトで json に応答させることができます。

それはあなたが求めていたものでしたか?

于 2011-04-20T03:47:47.443 に答える