在Sinatra中,所有路由处理程序似乎都被写入单个文件中,如果我理解正确,它就像一个大/小控制器。是否有任何方法将其拆分为独立的单独文件,以便当某人调用“/”时执行一个操作,而如果接收到类似“/posts/2”的内容,则执行另一个操作-类似于PHP中应用的逻辑?
thin -R config.ru start
编辑: 我现在正在维护自己的Monk骨架,基于下面的Riblits。要将其用作复制我的模板作为您自己项目的基础,请执行以下操作:# Before creating your project
monk add riblits git://github.com/Phrogz/riblits.git
# Inside your empty project directory
monk init -s riblits
文件布局:
config.ru app.rb helpers/ init.rb partials.rb models/ init.rb user.rb routes/ init.rb login.rb main.rb views/ layout.haml login.haml main.haml
config.ru
root = ::File.dirname(__FILE__)
require ::File.join( root, 'app' )
run MyApp.new
app.rb
# encoding: utf-8
require 'sinatra'
require 'haml'
class MyApp < Sinatra::Application
enable :sessions
configure :production do
set :haml, { :ugly=>true }
set :clean_trace, true
end
configure :development do
# ...
end
helpers do
include Rack::Utils
alias_method :h, :escape_html
end
end
require_relative 'models/init'
require_relative 'helpers/init'
require_relative 'routes/init'
helpers/init.rb
# encoding: utf-8
require_relative 'partials'
MyApp.helpers PartialPartials
require_relative 'nicebytes'
MyApp.helpers NiceBytes
helpers/partials.rb
# encoding: utf-8
module PartialPartials
def spoof_request(uri,env_modifications={})
call(env.merge("PATH_INFO" => uri).merge(env_modifications)).last.join
end
def partial( page, variables={} )
haml page, {layout:false}, variables
end
end
helpers/nicebytes.rb
# encoding: utf-8
module NiceBytes
K = 2.0**10
M = 2.0**20
G = 2.0**30
T = 2.0**40
def nice_bytes( bytes, max_digits=3 )
value, suffix, precision = case bytes
when 0...K
[ bytes, 'B', 0 ]
else
value, suffix = case bytes
when K...M then [ bytes / K, 'kiB' ]
when M...G then [ bytes / M, 'MiB' ]
when G...T then [ bytes / G, 'GiB' ]
else [ bytes / T, 'TiB' ]
end
used_digits = case value
when 0...10 then 1
when 10...100 then 2
when 100...1000 then 3
else 4
end
leftover_digits = max_digits - used_digits
[ value, suffix, leftover_digits > 0 ? leftover_digits : 0 ]
end
"%.#{precision}f#{suffix}" % value
end
module_function :nice_bytes # Allow NiceBytes.nice_bytes outside of Sinatra
end
models/init.rb
# encoding: utf-8
require 'sequel'
DB = Sequel.postgres 'dbname', user:'bduser', password:'dbpass', host:'localhost'
DB << "SET CLIENT_ENCODING TO 'UTF8';"
require_relative 'users'
models/user.rb
# encoding: utf-8
class User < Sequel::Model
# ...
end
routes/init.rb
# encoding: utf-8
require_relative 'login'
require_relative 'main'
routes/login.rb
# encoding: utf-8
class MyApp < Sinatra::Application
get "/login" do
@title = "Login"
haml :login
end
post "/login" do
# Define your own check_login
if user = check_login
session[ :user ] = user.pk
redirect '/'
else
redirect '/login'
end
end
get "/logout" do
session[:user] = session[:pass] = nil
redirect '/'
end
end
routes/main.rb
# encoding: utf-8
class MyApp < Sinatra::Application
get "/" do
@title = "Welcome to MyApp"
haml :main
end
end
views/layout.haml
!!! XML
!!! 1.1
%html(xmlns="http://www.w3.org/1999/xhtml")
%head
%title= @title
%link(rel="icon" type="image/png" href="/favicon.png")
%meta(http-equiv="X-UA-Compatible" content="IE=8")
%meta(http-equiv="Content-Script-Type" content="text/javascript" )
%meta(http-equiv="Content-Style-Type" content="text/css" )
%meta(http-equiv="Content-Type" content="text/html; charset=utf-8" )
%meta(http-equiv="expires" content="0" )
%meta(name="author" content="MeWho")
%body{id:@action}
%h1= @title
#content= yield
https://github.com/monkrb/monk
你可以通过rubygems.org安装它。一旦你拥有了这个gem,按照上面链接的说明生成一个示例应用程序即可。Dir[root_path("app/**/*.rb")].each do |file|
require file
end
init.rb
相比上述方法的一个好处是可以控制加载顺序,以防存在相互依赖的文件。 - Phrogz可以通过谷歌搜索“Sinatra boilerplate”来获取其他人如何布置他们的Sinatra应用程序的一些想法。从中你可能会找到符合你需求的模板,或者自己制作一个模板也不难。当你开发更多的Sinatra应用程序时,可以添加到你的模板中。
下面是我为我所有项目所使用的模板:
我处理在同一网站上托管不同项目的方法是使用sinatra/namespace
,如下所示:
server.rb
require "sinatra"
require "sinatra/namespace"
if [ENV["LOGNAME"], ENV["USER"]] == [nil, "naki"]
require "sinatra/reloader"
register Sinatra::Reloader
set :port, 8719
else
set :environment, :production
end
for server in Dir.glob "server_*.rb"
require_relative server
end
get "/" do
"this route is useless"
end
server_someproject.rb
module SomeProject
def self.foo bar
...
end
...
end
namespace "/someproject" do
set :views, settings.root
get "" do
redirect request.env["REQUEST_PATH"] + "/"
end
get "/" do
haml :view_someproject
end
post "/foo" do
...
SomeProject.foo ...
end
end
view_someproject.haml
!!!
%html
...
我使用的另一个子项目的细节是将它们的名称、描述和路由添加到某种全局变量中,该变量被"/"
用于制作指南主页,但我现在没有代码片段。
阅读此处的文档:
似乎Sinatra允许您将应用程序分解为Ruby模块,可以通过Sinatra的“register”方法或“helpers”方法引入这些模块,如下所示:
require 'sinatra/base'
module Sinatra
module Sample
module Helpers
def require_logged_in()
redirect('/login') unless session[:authenticated]
end
end
end
end
require 'sinatra/base'
module Sinatra
module Sample
module Routing
module Foos
def self.registered(app)
app.get '/foos/:id' do
# invoke a helper
require_logged_in
# load a foo, or whatever
erb :foos_view, :locals => { :foo => some_loaded_foo }
end
end
end
end
end
end
#!/usr/bin/env ruby
require 'sinatra'
require_relative 'routing/foos'
class SampleApp < Sinatra::Base
helpers Sinatra::Sample::Helpers
register Sinatra::Sample::Routing::Foos
end
当 Monk 对我不起作用时,我开始自己制作模板。
如果你想一想,绑定一组文件并没有什么特别的。Monk 的哲学在 2011 年早期的 RedDotRubyConf 上向我解释过,他们特别告诉我现在它几乎没有维护,所以使用它真的是可选的。
这对于那些想要使用 ActiveRecord 的人来说是一个很好的开始:
简单的 Sinatra MVC
require "sequel"
和DB
的初始化放在models/init.rb
中,然后对所有文件使用require_relative
,是上述结构特别好的一点。这样,你可以进入models
目录,打开 IRB 控制台,输入require './init'
,就可以加载完整的数据库和模型设置,进行交互式探索了。 - PhrogzArray
类由核心库定义,但是你可以通过使用class Array; def some_awesome_method; end
来“monkeypatch”,并且 a) 所有以前的Array
功能都被保留,b) 所有Array
实例都将获得你的新代码。在 Ruby 中,类只是对象,可以随时进行增强和更改。 - Phrogzclean_trace
在 Sinatra 中是一个有效选项吗?https://github.com/sinatra/sinatra/issues/148 - briangonzalez