Uso de Sinatra para proyectos más grandes a través de varios archivos
Parece que en Sinatra todos los controladores de ruta se escriben en un solo archivo, si entiendo bien actúa como un controlador grande/pequeño. ¿Hay alguna manera de dividirlo en archivos independientes separados, así que cuando digamos que alguien llama a "/" - se ejecuta una acción, y si se recibe smth como "/posts/2" entonces se aplica otra acción - lógica similar en PHP?
8 answers
Aquí hay una plantilla básica para las aplicaciones de Sinatra que uso. (Mis aplicaciones más grandes tienen más de 200 archivos rotos de esta manera, sin contar las gemas vendor'd, que cubren 75-100 rutas explícitas. Algunas de estas rutas son rutas Regexp que cubren más de 50 patrones de ruta adicionales.) Al usar Thin, ejecuta una aplicación como esta usando:thin -R config.ru start
Edit : Ahora estoy manteniendo mi propio esqueleto Monk basado en el siguiente llamado Riblits. Para usarlo para copiar mi plantilla como la base para sus propios proyectos:
# Before creating your project
monk add riblits git://github.com/Phrogz/riblits.git
# Inside your empty project directory
monk init -s riblits
Archivo Diseño:
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
ayudantes/parciales.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
modelos / 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'
modelos/usuario.rb
# encoding: utf-8
class User < Sequel::Model
# ...
end
rutas / init.rb
# encoding: utf-8
require_relative 'login'
require_relative 'main'
rutas/inicio de sesión.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
rutas / main.rb
# encoding: utf-8
class MyApp < Sinatra::Application
get "/" do
@title = "Welcome to MyApp"
haml :main
end
end
vistas/diseño.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
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-03-22 12:51:06
Absolutamente. Para ver un ejemplo de esto recomiendo descargar la gema Monk, descrita aquí:
Https://github.com/monkrb/monk
Puede 'instalar gema' a través de rubygems.org.Una vez que tenga la gema, genere una aplicación de ejemplo utilizando las instrucciones enlazadas anteriormente.
Tenga en cuenta que no tiene que usar Monk para su desarrollo real a menos que lo desee (de hecho, creo que puede no ser actual). El punto es ver cómo puede estructurar fácilmente su aplicación en el estilo MVC (con archivos de ruta separados similares al controlador) si lo desea.
Es bastante simple si nos fijamos en cómo Monk lo maneja, principalmente una cuestión de requerir archivos en directorios separados, algo así como (tendrá que definir root_path):
Dir[root_path("app/**/*.rb")].each do |file|
require file
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-02-16 14:03:06
Haga una búsqueda en Google de "Sinatra boilerplate" para obtener algunas ideas sobre cómo otros están diseñando sus aplicaciones Sinatra. A partir de eso, probablemente pueda encontrar uno que se adapte a sus necesidades o simplemente hacer el suyo propio. No es muy difícil de hacer. A medida que desarrolles más aplicaciones Sinatra, puedes agregarlas a tu plantilla.
Esto es lo que hice y utilicé para todos mis proyectos:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-02-18 05:02:58
Sé que esta es una consulta antigua, pero todavía no puedo creer que nadie mencionó Padrino Puede usarlo como un marco sobre Sinatra, o por partes agregando solo las gemas que le interesen. ¡Patea diez culos!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2012-04-27 21:52:30
Mi enfoque para alojar diferentes proyectos en el mismo sitio es usar sinatra/namespace
de tal manera:
Servidor.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
...
Otro detalle sobre los subproyectos que utilicé fue agregar sus nombres, descripción y rutas a algún tipo de variable global, que es utilizada por "/"
para hacer una página de inicio de guía, pero no tengo un fragmento en este momento.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-07-17 14:45:20
Leyendo los documentos aquí:
Parece que Sinatra le permite descomponer su aplicación en módulos Ruby, que se pueden extraer a través del método "register" o métodos "helpers" de Sinatra, así:
Ayudantes.rb
require 'sinatra/base'
module Sinatra
module Sample
module Helpers
def require_logged_in()
redirect('/login') unless session[:authenticated]
end
end
end
end
Enrutamiento/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
App.rb
#!/usr/bin/env ruby
require 'sinatra'
require_relative 'routing/foos'
class SampleApp < Sinatra::Base
helpers Sinatra::Sample::Helpers
register Sinatra::Sample::Routing::Foos
end
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2013-05-03 17:36:32
Cuando Monk no trabajaba para mí, empecé a trabajar en plantillas yo mismo.
Si lo piensas bien, no hay nada especial en vincular un conjunto de archivos. La filosofía monk me fue explicada a principios de 2011 durante RedDotRubyConf y me han dicho específicamente que es realmente opcional usarla, especialmente ahora que apenas se mantiene.
Este es un buen comienzo para aquellos que quieren usar ActiveRecord:
Simple Sinatra MVC
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-02-23 17:00:59
La clave para la modularidad en Sinatra para proyectos más grandes es aprender a usar las herramientas subyacentes.
SitePoint tiene un muy buen tutorial desde donde se pueden ver aplicaciones modulares de Sinatra y helpers. Sin embargo tenéis que prestar la atención especial a un detalle importante. Mantiene varias aplicaciones Sinatra y las monta con Rackup. Una vez que sepa cómo escribir una aplicación básica, mire config.ru archivo de ese tutorial y observar cómo montan Sinatra independiente aplicaciones.
Una vez que aprendas a ejecutar Sinatra con Rack, se abrirá un nuevo mundo de estrategias de modularidad. Obviamente, esto invita a probar algo realmente útil: ahora puede confiar en tener gemas individuales para cada subaplicación , lo que podría permitirle versionar fácilmente sus módulos.
No subestime el poder de usar módulos de gemas para su aplicación. Puede probar fácilmente los cambios experimentales en un entorno bien delimitado e implementarlos fácilmente. Igualmente fácil de volver atrás si algo sale mal.
Hay mil formas de organizar tu código, por lo que no estaría de más intentar conseguir un diseño similar a Rails. Sin embargo, también hay algunos grandes mensajes acerca de cómo personalizar su propia estructura. Esa publicación cubre otras necesidades frecuentes de la mayoría de los desarrolladores web.
Si tienes tiempo, te animo a aprender más sobre Rack, el terreno común para cualquier aplicación web basada en Ruby. Podría tener un impacto mucho menor en cómo haces tu trabajo, pero siempre hay ciertas tareas que la mayoría de las personas hacen en sus aplicaciones que se ajustan mejor como un middleware de rack.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-06-30 12:37:56