我正在尝试使用DSL来管理同一路由内的不同语言环境,例如get "/test"
。
这是学习如何扩展Sinatra的练习,因此Rack::Locale
或类似工具不是有效的答案。
基于请求JSON主体的主体,假设我以POST或PUT形式接收JSON,我想以特定的语言环境进行响应。
我目前有一个我认为自己需要的准系统脚本:
class Locale
attr_reader :locale_id
attr_reader :described_class
alias :current_locale :locale_id
def initialize(locale_id, &block)
@locale_id = locale_id
instance_eval &block
end
end
def locale(locale_id, &block)
Locale.new(locale_id, &block)
end
我缺少基于输入的request.body
JSON中的语言环境做出响应的能力,并且这里的类还有其他我不知道的必要或缺失的东西。
如何使用它的示例是:
get '/' do
locale 'cs-CS' do
"Czech"
#or db query or string
end
locale 'en-UK' do
"British english"
#or db query or string
end
end
因此,为了更清楚地说明,我将尝试使用TDD方法:
作为用户,当我发送包含:"locale": "cs-CS"
的JSON时,结果是捷克语。
您是否已阅读Extending The DSL和README的条件部分?
现在,您并没有真正扩展DSL。我会稍微重新设计它,因为它看起来像您要在case语句上进行匹配,但这意味着要创建许多类或一个丑陋的匹配语句。但是,Sinatra已经有了一些非常好的方法来匹配路线和条件。因此,像这样的东西会更惯用:
post '/', :locale => "Czech" do
"Czech"
end
post '/', :locale => "British English" do
"British"
end
或
post '/', :locale => "en-GB" do
"cs-CS"
end
post '/', :locale => "cs-CS" do
"cs-CS"
end
如何执行此操作?首先,您需要一个过滤器来转换传入的JSON:
before do
if request.media_type == "application/json"
request.body.rewind
@json = JSON.parse request.body.read
@locale = @json["locale"] && Locales[@json["locale"]]
end
end
然后您将需要一个条件来检查:
set(:locale) {|value|
condition {
!!@locale && (@locale == value || @json["locale"] == value)
}
}
全部(app.rb):
require 'sinatra'
Locales = {
'cs-CS' => "Czech",
'en-GB' => "British English"
}
before do
if request.media_type == "application/json"
request.body.rewind
@json = JSON.parse request.body.read
@locale = @json["locale"] && Locales[@json["locale"]]
end
end
set(:locale) {|value|
condition {
!!@locale && (@locale == value || @json["locale"] == value)
}
}
post '/', :locale => "en-GB" do
"cs-CS"
end
post '/', :locale => "cs-CS" do
"cs-CS"
end
可以,但是不能作为扩展。因此,依靠我在顶部发布的文档:
require 'sinatra/base'
module Sinatra
module Localiser
Locales = {
'cs-CS' => "Czech",
'en-GB' => "British English"
}
def localise!(locales=Locales)
before do
if request.media_type == "application/json"
request.body.rewind
@json = JSON.parse request.body.read
@locale = @json["locale"] && locales[@json["locale"]]
end
end
set(:locale) {|value|
condition {
!!@locale && (@locale == value || @json["locale"] == value)
}
}
end
end
register Localiser
end
现在它将扩展DSL。例如:
require "sinatra/localiser"
class Localised < Sinatra::Base
register Sinatra::Localiser
localise!
post '/', :locale => "Czech" do
"Czech"
end
post '/', :locale => "British English" do
"British"
end
["get","post"].each{|verb|
send verb, "/*" do
"ELSE"
end
}
run! if app_file == $0
end
希望能为您澄清一些事情。