通过多个文件对大型项目使用 Sinatra

似乎在 Sinatra 中,所有的路由处理程序都被写入到一个文件中,如果我理解正确的话,它就像一个大/小控制器。有没有办法把它分割成单独的独立文件,这样当有人调用“/”-一个操作被执行,并且如果像“/post/2”这样的 smth 被接收,那么另一个操作-类似的逻辑被应用在 PHP 中?

57531 次浏览

当然,为了看到这样一个例子,我建议下载 Monk gem,如下所述:

Https://github.com/monkrb/monk

你可以通过 rubygems.org“ gem install”它。一旦你有了 gem,使用上面链接的指令生成一个示例应用程序。

请注意,您不必在实际开发中使用 Monk,除非您愿意(事实上,我认为它可能不是最新的)。关键在于,如果你愿意,你可以看看如何轻松地以 MVC 风格(使用单独的控制器样的路由文件)来构建你的应用程序。

如果你看看 Monk 是如何处理它的,它非常简单,主要是要求文件位于不同的目录中,比如(你必须定义 root _ path) :

Dir[root_path("app/**/*.rb")].each do |file|
require file
end

下面是我使用的 Sinatra 应用程序的基本模板。(我的大型应用程序有200多个这样的文件,不包括供应商的宝石,涵盖75-100显式路由。其中一些路线是 Regexp 路线,覆盖额外的50 + 路线模式。)使用瘦程序时,您可以使用以下方法运行应用程序:
thin -R config.ru start

编辑 : 我现在维护我自己的 和尚骨架,基于下面的 里布里茨。使用它来复制我的模板作为您自己项目的基础:

# 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


应用程序

# 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/partals.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


Model/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'


Model/user.rb

# encoding: utf-8
class User < Sequel::Model
# ...
end


路由/init.rb

# encoding: utf-8
require_relative 'login'
require_relative 'main'


路线/登入资料

# 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


路线/主要道路

# encoding: utf-8
class MyApp < Sinatra::Application
get "/" do
@title = "Welcome to MyApp"
haml :main
end
end


视图/布局

!!! 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

在谷歌上搜索“ Sinatra 样板”,看看其他人是如何布局他们的 Sinatra 应用程序的。从那里你可能会找到一个适合你的需要或只是使你自己的。这并不难。随着你开发更多的 Sinatra 应用程序,你可以添加到你的样板。

下面是我所有项目中制作和使用的东西:

Https://github.com/rziehl/sinatra-boilerplate

我知道这是一个老的查询,但我仍然不能相信没有人提到 教父你可以使用它作为一个框架顶部的辛纳屈,或零碎添加只有你感兴趣的宝石。它踢了十个屁股的屁股!

当 Monk 不为我工作时,我开始自己制作模板。

仔细想想,绑定一组文件并没有什么特别之处。2011年早些时候,在 RedDotRubyConf 上,僧侣哲学被解释给我听,他们特别告诉我,使用它是可选的,特别是现在它很难维护。

对于那些想要使用 ActiveRecord 的人来说,这是一个好的开始:

简单的 Sinatra MVC

Https://github.com/katgironpe/simple-sinatra-mvc

看看这里的文件:

Sinatra 扩音器

似乎 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

路由/foos.rb

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

对于大型项目来说,在 Sinatra 上实现模块化的关键是学习使用底层工具。

SitePoint 有一个非常 教得不错,从那里你可以看到模块化的 Sinatra 应用程序和帮助。然而,你应该特别注意一个重要的细节。你保持多个 Sinatra 应用程序和 上马他们与 Rackup。一旦你知道如何编写一个基本的应用程序,看看该教程的 Config.ru文件,并观察他们如何挂载独立的 Sinatra 应用程序。

一旦你学会了用 Rack 运行 Sinatra,一个全新的模块化战略世界将会打开。很明显,这让我们尝试一些真正有用的东西: 现在,您可以依赖于为每个 附属申请提供单独的 Gems,这可能使您能够轻松地对模块进行版本控制。

不要低估了在应用程序中使用 gem 模块的能力。您可以轻松地在定义良好的环境中测试实验性更改并轻松地部署它们。如果出现问题,也同样容易恢复原状。

有成千上万种方法可以组织您的代码,所以尝试获得类似于 Rails 的布局不会有什么坏处。然而,也有一些关于如何定制自己的结构的 很棒的帖子。这篇文章涵盖了大多数网络开发者的其他常见需求。

如果你有时间,我鼓励你学习更多关于 Rack 的知识,这是任何基于 Ruby 的 web 应用程序的共同点。它可能对您的工作方式的影响要小得多,但是大多数人在他们的应用程序上做的某些任务更适合作为 Rack 中间件。

我在同一个网站上主持不同项目的方法是以这样的方式使用 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 _ some project. 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

查看某项目

!!!
%html
...

我使用的子项目的另一个细节是添加它们的名称、描述和到某种全局变量的路由,"/"使用这种全局变量来创建指南主页,但我现在没有一个片段。