Utiliser Sinatra pour des projets plus importants via plusieurs fichiers

Il semble que dans Sinatra, tous les gestionnaires de routes sont écrits dans un seul fichier, si je comprends bien, il agit comme un seul grand contrôleur. Existe-t-il un moyen de le diviser en fichiers indépendants distincts, par exemple quand quelqu’un appelle “/” – une action est exécutée et si smth comme “/ posts / 2” est reçu alors une autre action – une logique similaire appliquée en PHP ?

Voici un modèle de base pour les applications Sinatra que j’utilise. (Mes applications plus grandes contiennent plus de 200 fichiers comme celui-ci, sans compter les gemmes vendues, qui couvrent 75 à 100 routes explicites. Certaines de ces routes sont des routes Regexp couvrant plus de 50 modèles de routes supplémentaires.) application comme celle-ci en utilisant:
thin -R config.ru start

Edit : Je maintiens maintenant mon propre squelette Monk basé sur le ci-dessous appelé Riblits . Pour l’utiliser pour copier mon modèle comme base pour vos propres projets:

 # Before creating your project monk add riblits git://github.com/Phrogz/riblits.git # Inside your empty project directory monk init -s riblits 

Disposition du fichier:

 config.ru
 app.rb
 helpers /
   init.rb
   partials.rb
 des modèles/
   init.rb
   user.rb
 routes /
   init.rb
   login.rb
   main.rb
 vues /
   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' 

modèles / 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 

Absolument. Pour voir un exemple de cela, je vous recommande de télécharger le joyau Monk, décrit ici:

https://github.com/monkrb/monk

Vous pouvez l’installer via rubygems.org. Une fois que vous avez le bijou, générez un exemple d’application en suivant les instructions ci-dessus.

Notez que vous n’avez pas besoin d’utiliser Monk pour votre développement réel, sauf si vous le souhaitez (en fait, je pense que ce n’est peut-être pas le cas). Le point est de voir comment vous pouvez facilement structurer votre application dans le style MVC (avec des fichiers de route de type contrôleur distincts) si vous le souhaitez.

C’est assez simple si vous regardez comment Monk le gère, principalement en ce qui concerne la nécessité de fichiers dans des répertoires séparés, quelque chose comme (vous devrez définir root_path):

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

Faites une recherche sur Google pour «Sinatra passe-partout» pour obtenir des idées sur la façon dont les autres installent leurs applications Sinatra. À partir de cela, vous pouvez probablement en trouver un qui convient à vos besoins ou simplement créer le vôtre. Ce n’est pas trop difficile à faire. Au fur et à mesure que vous développez d’autres applications Sinatra, vous pouvez les append à votre programme.

Voici ce que j’ai fait et utilisé pour tous mes projets:

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

Je sais que c’est une vieille requête, mais je ne peux toujours pas croire que personne n’a mentionné Padrino. Vous pouvez l’utiliser comme un cadre au-dessus de Sinatra, ou en ajoutant uniquement les gemmes qui vous intéressent. Il frappe dix fesses de cul!

La clé de la modularité sur Sinatra pour les grands projets est d’apprendre à utiliser les outils sous-jacents.

SitePoint a un très bon tutoriel à partir duquel vous pouvez voir les applications et aides Sinatra modulaires. Cependant, vous devez porter une attention particulière à un détail important. Vous conservez plusieurs applications Sinatra et les montez avec Rackup. Une fois que vous savez comment écrire une application de base, regardez le fichier config.ru de ce tutoriel et observez comment ils montent des applications Sinatra indépendantes.

Une fois que vous aurez appris à utiliser Sinatra avec Rack, un tout nouveau monde de stratégies de modularité s’ouvrira. Cela invite évidemment à essayer quelque chose de vraiment utile: vous pouvez désormais compter sur des gems individuels pour chaque sous-application , ce qui pourrait vous permettre de facilement mettre à jour vos modules.

Ne sous-estimez pas le pouvoir d’utiliser des modules de gemmes pour votre application. Vous pouvez facilement tester les modifications expérimentales dans un environnement bien délimité et les déployer facilement. Aussi facile de revenir en arrière si quelque chose ne va pas.

Il y a mille façons d’organiser votre code, cela ne ferait pas de mal à essayer d’avoir une présentation similaire à Rails. Cependant, il existe également des articles intéressants sur la façon de personnaliser votre propre structure. Ce poste couvre d’autres besoins fréquents de la plupart des développeurs Web.

Si vous avez le temps, je vous encourage à en apprendre davantage sur Rack, le fondement commun de toute application Web basée sur Ruby. Cela peut avoir un impact beaucoup moins important sur votre façon de travailler, mais il y a toujours certaines tâches que la plupart des gens effectuent sur leurs applications et qui conviennent mieux à un middleware Rack.

Mon approche pour héberger différents projets sur le même site consiste à utiliser sinatra/namespace de la manière suivante:

serveur.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 ... 

Un autre détail sur les sous-projets que j’ai utilisés était d’append leurs noms, descriptions et itinéraires à une sorte de variable globale, utilisée par "/" pour créer une page d’accueil, mais je n’ai pas d’extrait de code pour le moment.

Lire les documents ici:

Extensions de Sinatra

Il semble que Sinatra vous permette de décomposer votre application en modules Ruby, qui peuvent être extraits via la méthode Sinatra “register” ou les méthodes “helpers”, comme ceci:

helpers.rb

 require 'sinatra/base' module Sinatra module Sample module Helpers def require_logged_in() redirect('/login') unless session[:authenticated] end end end end 

routage / 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 

Lorsque Monk ne travaillait pas pour moi, j’ai commencé à travailler sur des modèles.

Si vous y réfléchissez, il n’ya rien de particulier à attacher un ensemble de fichiers. La philosophie du moine m’a été expliquée au début de 2011 lors de RedDotRubyConf et ils m’ont spécifiquement dit que c’était vraiment facultatif de l’utiliser surtout maintenant qu’il n’était plus maintenu.

C’est un bon début pour ceux qui veulent utiliser ActiveRecord:

Simple Sinatra MVC

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