Использование Sinatra для больших проектов через несколько файлов - PullRequest
183 голосов
/ 16 февраля 2011

Кажется, что в Sinatra все обработчики маршрутов записываются в один файл, если я правильно понимаю, он действует как один большой / маленький контроллер.Есть ли способ разделить его на отдельные независимые файлы, поэтому, когда, скажем, кто-то вызывает "/" - выполняется одно действие, а если получено что-то вроде "/ posts / 2", тогда другое действие - аналогичная логика, которая применяется в PHP

Ответы [ 8 ]

394 голосов
/ 17 февраля 2011

Вот базовый шаблон для приложений Sinatra, которые я использую. (В моих больших приложениях разбито более 200 файлов, не считая драгоценных камней вендора, охватывающих 75-100 явных маршрутов. Некоторые из этих маршрутов являются маршрутами Regexp, охватывающими дополнительные 50+ шаблонов маршрутов.) При использовании Thin вы запускаете приложение, как это, используя:
thin -R config.ru start

Редактировать : Сейчас я поддерживаю свой собственный Монах скелет, основанный на ниже названном Riblits . Чтобы использовать его для копирования моего шаблона в качестве основы для ваших собственных проектов:

# 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


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'


хелперы / init.rb

# encoding: utf-8
require_relative 'partials'
MyApp.helpers PartialPartials

require_relative 'nicebytes'
MyApp.helpers NiceBytes


хелперы / 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


хелперы / 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


модели / 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'


Модели / user.rb

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


маршруты / init.rb

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


маршруты / 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


маршруты / main.rb

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


вид / 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
10 голосов
/ 20 марта 2012

Выполните поиск в Google по «шаблону Sinatra», чтобы получить некоторые идеи о том, как другие выкладывают свои приложения Sinatra. Из этого вы, вероятно, можете найти тот, который соответствует вашим потребностям или просто сделать свой собственный. Это не так уж сложно сделать. По мере того, как вы будете разрабатывать больше приложений для Sinatra, вы сможете добавить их в свой шаблон.

Вот что я сделал и использовал для всех своих проектов:

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

10 голосов
/ 16 февраля 2011

Абсолютно.Чтобы увидеть пример этого, я рекомендую скачать гем Monk, описанный здесь:

https://github.com/monkrb/monk

Вы можете установить его с помощью rubygems.org.Получив гем, создайте пример приложения, используя приведенные выше инструкции.

Обратите внимание, что вам не нужно использовать Monk для фактической разработки, если вы не хотите (на самом деле я думаю, что это может быть не актуально).).Суть в том, чтобы увидеть, как вы можете легко структурировать свое приложение в стиле MVC (с отдельными файлами маршрутов, похожими на контроллеры), если хотите.вопрос о необходимости файлов в отдельных каталогах, что-то вроде (вам нужно определить root_path):

Dir[root_path("app/**/*.rb")].each do |file|
    require file
end
7 голосов
/ 28 апреля 2012

Я знаю, что это старый запрос, но я все еще не могу поверить, что никто не упомянул Padrino Вы можете использовать его в качестве основы поверх Sinatra или по частям, добавляя только те камни, которые вас интересуют.Это пинает десять ягодиц задницы!

2 голосов
/ 17 июля 2014

Мой подход к размещению различных проектов на одном сайте заключается в использовании 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_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
    ...

Еще одна деталь о подпроектах, которые я использовал, заключалась в добавлении их имен, описаний и маршрутов к некоторымсвоего рода глобальная переменная, которая используется "/" для создания домашней страницы руководства, но сейчас у меня нет фрагмента.

1 голос
/ 30 июня 2014

Ключом к модульности в Sinatra для крупных проектов является обучение использованию базовых инструментов.

SitePoint имеет очень хороший учебник , из которого вы можете увидеть модульные приложения и помощники Синатры. Однако стоит обратить особое внимание на одну важную деталь. Вы храните несколько приложений Sinatra и монтируете их с помощью Rackup. Когда вы знаете, как написать простое приложение, посмотрите на файл config.ru этого руководства и посмотрите, как они монтируют независимые приложения Sinatra.

Как только вы научитесь управлять Sinatra с Rack, откроется новый мир стратегий модульности. Это, очевидно, побуждает попробовать что-то действительно полезное: теперь вы можете рассчитывать на наличие отдельных Gems для каждого суб-приложения , что может позволить вам легко создавать версии ваших модулей.

Не стоит недооценивать возможности использования gem-модулей для вашего приложения. Вы можете легко протестировать экспериментальные изменения в хорошо разграниченной среде и легко развернуть их. В равной степени легко вернуться назад, если что-то пойдет не так.

Существуют тысячи способов организации вашего кода, поэтому не мешало бы получить компоновку, аналогичную Rails. Однако есть также замечательных постов о том, как настроить свою собственную структуру. Этот пост охватывает другие частые потребности большинства веб-разработчиков.

Если у вас есть время, я призываю вас узнать больше о Rack, общем фундаменте для любого веб-приложения на основе Ruby. Это может оказать гораздо меньшее влияние на то, как вы выполняете свою работу, но всегда есть определенные задачи, которые большинство людей выполняют в своих приложениях, которые лучше подходят в качестве промежуточного программного обеспечения Rack.

1 голос
/ 03 мая 2013

Чтение документов здесь:

Расширения Синатры

Похоже, что Sinatra позволяет вам разложить ваше приложение на модули Ruby, которые могут быть извлечены с помощью метода "register" Sinatra или методов "helpers", например:

helpers.rb

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

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 голос
/ 16 декабря 2012

Когда Монах не работал на меня, я сам начал работать с шаблонами.

Если подумать, нет ничего особенного в связывании набора файлов.Философия монаха была объяснена мне в начале 2011 года во время RedDotRubyConf, и они специально сказали мне, что использовать ее действительно необязательно, особенно сейчас, когда она почти не поддерживается.

Это хорошее начало для тех, кто хочет использовать ActiveRecord:

Simple Sinatra MVC

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...