我正在从Rails提供版本化的Web服务。我如何定制Rails 4 render()找到文件的方式?
我也非常希望能够调用呈现像正常:
render 'index'
,并让它正确地从下面的服务请求的版本:
index.v1.json.jbuilder
index.v2.json.jbuilder
index.v3.json.jbuilder
假设我已经知道了请求的版本在控制器动作执行的上下文中,我如何获得render()来利用它?
我正在从Rails提供版本化的Web服务。我如何定制Rails 4 render()找到文件的方式?
我也非常希望能够调用呈现像正常:
render 'index'
,并让它正确地从下面的服务请求的版本:
index.v1.json.jbuilder
index.v2.json.jbuilder
index.v3.json.jbuilder
假设我已经知道了请求的版本在控制器动作执行的上下文中,我如何获得render()来利用它?
听起来像一个制造商的设计模式可能会在这里工作。有一个视图构建器对象返回所需的行为。
module ViewBuiler
def build(name, api_version)
View.new(name, api_version).build
end
class View < Struct(:name, :api_version)
def build
[name, api_version, 'json', 'jbuilder'].join('.')
end
end
end
和控制器,你可能只是这样做:
ApplicationController
include ViewBuilder
end
MyController < ApplicationController
def index
...
# you can pass either strings or symbols to build and it will
# return 'index.v1.json.jbuilder'
render build(:index, params[:api_version])
end
end
与免责声明,这只是一个想法,不是我实现了。我喜欢这种方法有两个原因。控制器操作仍然很瘦,并且没有逻辑。像这样的构建者似乎很容易测试。并且它可以将可能改变的东西(视图等)分离成可以频繁更改的东西,只要它保留了控制器可以使用的界面即可。
这似乎是变体的候选人。但这对4.1来说是新的。
class MyController < ActionController::Base
before_action :set_variant
def my_action
.....
respond_to do |format|
format.json do |json|
json.v1 do
# render whatever you need here
end
end
end
end
protected
def set_variant
request.variant = :v1 if request.params[:version] == "v1"
....
end
end
是否可以将视图重构为由版本命名的文件夹,然后使用更复杂的渲染调用? (例如,渲染“#{version} /#{controller}/index”) – Coenwulf
这很吸引人,也许是一个很好的选择,尽管我可能会这样做(渲染“index _#{version}”)。 –