Korzystanie z Sinatry dla większych projektów za pomocą wielu plików

Wygląda na to, że w Sinatrze wszystkie programy obsługi tras są zapisywane w jednym pliku, jeśli dobrze rozumiem, działa to jako jeden duży / mały kontroler. Czy jest jakiś sposób na podzielenie go na osobne niezależne pliki, więc kiedy powiedzmy, że ktoś wywoła "/" - jedna akcja jest wykonywana, a jeśli zostanie odebrany smth jak "/posts / 2", to kolejna akcja - podobna logika, która jest stosowana w PHP?

 182
Author: Phrogz, 2011-02-16

8 answers

Oto podstawowy szablon dla aplikacji Sinatra, których używam. (Moje większe aplikacje mają ponad 200 plików rozbijanych w ten sposób, nie licząc klejnotów sprzedawców, obejmujących 75-100 wyraźnych tras. Niektóre z tych tras to trasy Regexp obejmujące dodatkowe 50 + wzorów tras.) Podczas korzystania z Thin uruchamiasz taką aplikację używając:
thin -R config.ru start

Edit : teraz utrzymuję swój własny Monk szkielet oparty na poniższej nazwie Riblits. Aby użyć go do skopiowania mojego szablonu jako podstawy dla własnych projektów:

# Before creating your project
monk add riblits git://github.com/Phrogz/riblits.git

# Inside your empty project directory
monk init -s riblits

Plik Layout:

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


pomocnicy / częściowe.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


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


modelki / użytkownik.rb

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


trasy / init.rb

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


trasy / logowanie.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


trasy / 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
 389
Author: Phrogz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-22 12:51:06

Absolutnie. Aby zobaczyć przykład tego polecam ściągnięcie klejnotu mnicha, opisanego tutaj:

Https://github.com/monkrb/monk

Możesz "zainstalować gem" za pomocą rubygems.org. gdy masz klejnot, wygenerować przykładową aplikację za pomocą instrukcji połączonych powyżej.

Zauważ, że nie musisz używać Monka do swojego rzeczywistego rozwoju, chyba że chcesz (w rzeczywistości myślę, że może to nie być aktualne). Chodzi o to, aby zobaczyć, jak można łatwo struktury aplikacji w stylu MVC (z oddzielnymi plikami trasy podobnymi do kontrolera), jeśli chcesz.

Jest to dość proste, jeśli spojrzysz na to, jak Monk sobie z tym radzi, głównie kwestia wymagania plików w oddzielnych katalogach, coś w stylu (będziesz musiał zdefiniować root_path):

Dir[root_path("app/**/*.rb")].each do |file|
    require file
end
 10
Author: TK-421,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-02-16 14:03:06

Wykonaj wyszukiwanie w Google "Sinatra boilerplate", aby uzyskać kilka pomysłów na to, jak inni układają swoje aplikacje Sinatra. Z tego prawdopodobnie można znaleźć taki, który odpowiada twoim potrzebom lub po prostu zrobić własne. To nie jest takie trudne. Wraz z rozwojem aplikacji Sinatra możesz dodawać do swojego boilerplate.

Oto co zrobiłem i wykorzystałem do wszystkich moich projektów:

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

 10
Author: Robert Ziehl,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-18 05:02:58

Wiem, że to stare zapytanie, ale nadal nie mogę uwierzyć, że nikt nie wspomniał o Padrino możesz użyć go jako frameworka na szczycie Sinatry, lub fragmentarycznie dodając tylko klejnoty, które Cię interesują. Kopie 10 tyłków!

 7
Author: Steven Garcia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-04-27 21:52:30

Moim podejściem do hostowania różnych projektów na tej samej stronie jest użycie sinatra/namespace w taki sposób:

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

Kolejnym szczegółem na temat podprojektów, których użyłem, było dodanie ich nazw, opisu i tras do jakiejś zmiennej globalnej, która jest używana przez "/" do tworzenia strony głównej przewodnika, ale nie mam teraz fragmentu.

 2
Author: Nakilon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-07-17 14:45:20

Czytanie dokumentów tutaj:

Sinatra Extensions

Wygląda na to, że Sinatra pozwala na rozłożenie aplikacji na Moduły Ruby, które można pobrać za pomocą metody Sinatra "register" lub metody "helpers", jak tak:

Pomocnicy.rb

require 'sinatra/base'

module Sinatra
  module Sample
    module Helpers

      def require_logged_in()
        redirect('/login') unless session[:authenticated]
      end

    end
  end
end

Routing / 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
Author: Erin Swenson-Healey,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-03 17:36:32

Kiedy Monk nie pracował dla mnie, sam zacząłem pracować nad szablonami.

Jeśli się nad tym zastanowić, nie ma nic specjalnego w wiązaniu zestawu plików. Filozofia mnicha została mi wyjaśniona na początku 2011 roku podczas RedDotRubyConf i powiedzieli mi, że jest to naprawdę opcjonalne, szczególnie teraz, gdy nie jest utrzymywane.

To dobry początek dla tych, którzy chcą używać ActiveRecord:

Simple Sinatra MVC

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

 1
Author: kgpdeveloper,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-23 17:00:59

Kluczem do modułowości w Sinatrze dla większych projektów jest nauka korzystania z podstawowych narzędzi.

SitePoint ma bardzo dobry tutorial , z którego można zobaczyć modułowe aplikacje i helpery. Należy jednak zwrócić szczególną uwagę na jeden ważny szczegół. Przechowujesz wiele aplikacji Sinatra i montujesz za pomocą Rackup. Gdy już wiesz jak napisać podstawową aplikację spójrz na config.ru Plik tego tutoriala i obserwuj jak montują niezależne aplikacje.

Gdy nauczysz się prowadzić Sinatrę z Rackiem, otworzy się zupełnie nowy świat strategii modułowości. To oczywiście zachęca do wypróbowania czegoś naprawdę użytecznego: teraz możesz polegać na posiadaniu indywidualnych klejnotów dla każdej subaplikacji , co może umożliwić Ci łatwą wersję Twoich modułów.

Nie lekceważ możliwości korzystania z modułów gem dla Twojej aplikacji. Możesz łatwo przetestować eksperymentalne zmiany w dobrze rozdzielonym środowisku i łatwo je wdrożyć. Równie łatwe do zawróć, jeśli coś pójdzie nie tak.

Istnieje tysiąc sposobów na uporządkowanie kodu, więc nie zaszkodzi spróbować uzyskać układ podobny do Rails. Jednak jest też kilka świetnych postów o tym, jak dostosować własną strukturę. Ten post obejmuje inne częste potrzeby większości twórców stron internetowych.

Jeśli masz czas, zachęcam cię do zapoznania się z Rack, wspólną płaszczyzną dla każdej aplikacji internetowej opartej na Rubim. Może mieć znacznie mniejszy wpływ na to, jak robisz swoje praca, ale zawsze są pewne zadania, które większość ludzi wykonuje w swoich aplikacjach, które lepiej pasują jako oprogramowanie pośredniczące w szafie.

 1
Author: SystematicFrank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-06-30 12:37:56