web-dev-qa-db-fra.com

Utilisation de Sinatra pour des projets plus importants via plusieurs fichiers

Il semble que dans Sinatra tous les gestionnaires d’itinéraires soient écrits dans un seul fichier, si j’ai bien compris, il s’agit d’un contrôleur grand/petit. Existe-t-il un moyen de le scinder en plusieurs fichiers indépendants? Par conséquent, lorsque quelqu'un appelle "/" - une action est exécutée, et s'il ressemble à "/ posts/2", il en reçoit une autre - une logique similaire à celle appliquée en PHP ?

183
spacemonkey

Voici un modèle de base pour les applications Sinatra que j'utilise. (Mes applications plus grandes ont plus de 200 fichiers ventilés comme ceci, sans compter les gemmes fournies par le fournisseur, couvrant 75 à 100 itinéraires explicites. Certains de ces itinéraires sont des itinéraires Regexp couvrant plus de 50 modèles d'itinéraire.) Lorsque vous utilisez Thin, vous exécutez un application comme celle-ci utilisant:
thin -R config.ru start

Edit : Je maintiens maintenant mon propre squelette Monk basé sur ce qui est appelé Riblits. Pour l'utiliser pour copier mon modèle comme base de 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 
 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'


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
395
Phrogz

Absolument. Pour voir un exemple, je vous recommande de télécharger la gemme Monk, décrite ici:

https://github.com/monkrb/monk

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

Notez que vous n'êtes pas obligé d'utiliser Monk pour votre développement actuel à moins que vous ne le vouliez (en fait, je pense que cela peut ne pas être courant). Le but est de voir comment vous pouvez facilement structurer votre application dans le style MVC (avec des fichiers de routage distincts similaires à ceux d'un contrôleur) si vous le souhaitez.

C'est assez simple si vous regardez comment Monk le gère, principalement en exigeant des fichiers dans des répertoires séparés, par exemple (vous devrez définir root_path):

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

Effectuez une recherche Google sur "Sinatra" pour avoir des idées sur la manière dont les autres développent leurs applications Sinatra. À partir de là, vous pouvez probablement en trouver un qui répond à vos besoins ou tout simplement en créer un. Ce n'est pas trop difficile à faire. Au fur et à mesure que vous développez d'autres applications Sinatra, vous pouvez en ajouter à votre passe-partout.

Voici ce que j'ai fabriqué et utilisé pour tous mes projets:

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

10
Robert Ziehl

Je sais que c’est une vieille requête, mais je ne peux toujours pas croire que personne ne soit mentionné Padrino Vous pouvez l’utiliser comme cadre au-dessus de Sinatra, ou ajouter au cas par cas uniquement les pierres précieuses qui vous intéressent. Il frappe dix fesses de cul!

7
Steven Garcia

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

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

Un autre détail concernant les sous-projets que j’ai utilisés est d’ajouter leurs noms, description et itinéraires à une sorte de variable globale, utilisée par "/" faire une page d'accueil de guide, mais je n'ai pas d'extrait pour l'instant.

2
Nakilon

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 spécial à propos de l’arrimage d’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 dit précisément que c’est vraiment facultatif de l’utiliser, en particulier maintenant que c’est à peine si elle est maintenue.

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

Sinatra simple MVC

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

1
kgpdeveloper

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

SitePoint a un très bon tutoriel d'où vous pouvez voir des applications et des aides modulaires de Sinatra. 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, consultez le fichier config.ru de ce didacticiel et observez comment ils installent des applications indépendantes Sinatra.

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 maintenant compter sur des gems individuels pour chaque sous application, ce qui pourrait vous permettre de faire facilement la version de vos modules.

Ne sous-estimez pas la puissance de l'utilisation de gem-modules pour votre application. Vous pouvez facilement tester des modifications expérimentales dans un environnement bien délimité et les déployer facilement. Également facile à revenir en cas de problème.

Il existe mille façons d’organiser votre code, il n’est donc pas gênant d’obtenir une présentation similaire à Rails. Cependant, il y a aussi quelques excellents messages sur la façon de personnaliser votre propre structure. Cet article 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 point de convergence de toute application Web basée sur Ruby). Cela pourrait avoir un impact beaucoup moins important sur la façon dont vous faites votre travail, mais Il existe toujours certaines tâches que la plupart des gens font sur leurs applications et qui conviennent mieux à un middleware Rack.

1
SystematicFrank

Lire la documentation ici:

Extensions Sinatra

Il semble que Sinatra vous permette de décomposer votre application en Ruby Modules, qui peuvent être insérés via la méthode "register" de Sinatra ou des méthodes "helpers", comme suit:

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
1