jay*_*jay 25 versioning api respond-with ruby-on-rails-3
前言:
我研究了如何对API进行版本控制,并找到了几种方法.我决定尝试peter williams的建议并创建新的供应商mime类型来指定版本和格式.我无法在"导轨方式"之后找到这样做的明确说明,所以我拼凑了几个地方的信息.我能够让它工作,但渲染器处理Widget数组vs Widget实例的方式有一些愚蠢respond_with
.
基本步骤和问题:
我注册了mime类型,并在xml和json中为ApplicationController添加了版本1的渲染器,渲染了模型中的渲染器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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
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
Run Code Online (Sandbox Code Playgroud)
配置/初始化/ 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
Run Code Online (Sandbox Code Playgroud)
更新:
找到了另一个感觉更好但仍然有点奇怪的解决方案(我仍然不太习惯猴子补丁),可能没问题......基本上是将类方法的响应数据构建to_myproj_v1_json
到Array上的猴子补丁.这样,当有一个Widgets数组时,它会调用as_myproj_v1_json
每个Widget上的实例方法,并以所需格式返回整个Array.
一个说明:
我已将下面的代码更新为当前使用的代码,因此原始问题可能没有意义.如果有人想要原来的问题和代码显示为和响应中的固定代码,我可以这样做.