前文:
APIのバージョン管理方法を調査し、それを行ういくつかの方法を見つけました。私はpeterwilliamsの提案を試してみることにし、バージョンとフォーマットを指定するために新しいベンダーのmimeタイプを作成しました。「レールウェイ」に従ってこれを行うための明確な記述が見つからなかったので、いくつかの場所からの情報をまとめました。私はそれを機能させることができましたが、レンダラーがウィジェット配列とウィジェットインスタンスを処理する方法にいくつかの間抜けがありますrespond_with
。
基本的な手順と問題:
mimeタイプを登録し、xmlとjsonの両方でバージョン1のレンダラーをApplicationControllerに追加し、レンダラーの呼び出しto_myproj_v1_xml
とto_myproj_v1_json
モデルのメソッドを追加しました。 respond_with(@widget)
正常に動作しますが、「テンプレートがありません」というメッセージが表示されますrespond_with(@widgets)
。HTTP/1.1 500 Internal Server Error
回避策:
「テンプレートがありません」は、レンダリングが呼び出されず、一致するテンプレートが存在しないことを意味します。偶然、クラスメソッドを探していることに気づきました...そこで、機能する以下のコードを思いつきましたが、あまり満足していません。間抜けは主にxml = obj.to_myproj_v1_xml(obj)
モデルにあり、モデルの重複に関連しています。
私の質問は-誰かが少しきれいな方法で同様のことをしたことがありますか?
-=更新されたコード=-
config / initializers / mime_types.rb:
Mime::Type.register 'application/vnd.com.mydomain.myproj-v1+xml', :myproj_v1_xml
Mime::Type.register 'application/vnd.com.mydomain.myproj-v1+json', :myproj_v1_json
app / controllers / application_controller.rb:
class ApplicationController < ActionController::Base
protect_from_forgery
before_filter :authenticate
ActionController.add_renderer :myproj_v1_xml do |obj, options|
xml = obj.to_myproj_v1_xml
self.content_type ||= Mime::Type.lookup('application/vnd.com.mydomain.myproj-v1+xml')
self.response_body = xml
end
ActionController.add_renderer :myproj_v1_json do |obj, options|
json = obj.to_myproj_v1_json
self.content_type ||= Mime::Type.lookup('application/vnd.com.mydomain.myproj-v1+json')
self.response_body = json
end
end
app / models / widget.rb:
class Widget < ActiveRecord::Base
belongs_to :user
V1_FIELDS = [:version, :model, :description, :name, :id]
def to_myproj_v1_xml
self.to_xml(:only => V1_FIELDS)
end
def to_myproj_v1_json
self.to_json(:only => V1_FIELDS)
end
def as_myproj_v1_json
self.as_json(:only => V1_FIELDS)
end
end
app / controllers / widgets_controller.rb:
class WidgetsController < ApplicationController
respond_to :myproj_v1_xml, :myproj_v1_json
def index
@widgets = @user.widgets
respond_with(@widgets)
end
def create
@widget = @user.widgets.create(params[:widget])
respond_with(@widget)
end
def destroy
@widget = @user.widgets.find(params[:id])
respond_with(@widget.destroy)
end
def show
respond_with(@widget = @user.widgets.find(params[:id]))
end
...
end
config / initializers /monkey_array.rb
class Array
def to_myproj_v1_json(options = {})
a = []
self.each { |obj| a.push obj.as_myproj_v1_json }
a.to_json()
end
def to_myproj_v1_xml(options = {})
a = []
self.each { |obj| a.push obj.as_myproj_v1_json } # yes this is json instead of xml. as_json returns a hash
a.to_xml()
end
end
アップデート:
気分は良くなるが、それでも少し奇妙な別の解決策を見つけました(私はまだモンキーパッチに完全に慣れていません)、おそらく大丈夫です...基本的に応答データの構築をクラスメソッドto_myproj_v1_json
から配列のモンキーパッチに移動しました。このように、ウィジェットの配列がある場合、各ウィジェットでインスタンスメソッドを呼び出し、as_myproj_v1_json
配列全体を目的の形式として返します。
注:
- as_jsonはjson形式とは関係がなく、ハッシュを作成するだけです。カスタムフォーマットをas_myproj_v1_json(またはカスタムmimeタイプを使用していない場合はas_jsonオーバーライド)に追加すると、to_jsonはハッシュをjson文字列に変更します。
以下のコードを現在使用されているものに更新したため、元の質問が意味をなさない場合があります。誰かが元の質問とコードをそのまま表示し、応答に修正されたコードが必要な場合は、代わりにそれを行うことができます。