여러 파일을 통해 더 큰 프로젝트에 Sinatra 사용


184

Sinatra에서는 모든 경로 처리기가 단일 파일로 작성되고있는 것으로 보입니다. 올바로 이해하면 하나의 큰 / 작은 컨트롤러 역할을합니다. 별도의 독립 파일로 분할 할 수있는 방법이 있습니까? 따라서 누군가가 "/"를 호출한다고 가정하면-한 동작이 실행되고 "/ posts / 2"와 같은 smth가 수신되면 다른 동작-PHP에 적용되는 유사한 논리 ?

답변:


394

내가 사용하는 Sinatra 앱의 기본 템플릿은 다음과 같습니다. (나의 더 큰 앱에는 공급 업체의 보석을 제외하고 75-100 개의 명시 적 경로를 포함하는 200 개 이상의 파일이 있습니다.이 경로 중 일부는 추가 50 개 이상의 경로 패턴을 포함하는 Regexp 경로입니다.) 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
도우미 /
  init.rb
  partials.rb
모델 /
  init.rb
  user.rb
노선 /
  init.rb
  login.rb
  main.rb
견해/
  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'

 
모델 /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

11
특히 뛰어난 점 중 하나는 상기 구조-특히 퍼팅 require "sequel"DB의 초기화 models/init.rb및 사용 require_relative모두를 위해 당신이 당신에 CD 할 수있는 파일-입니다 models디렉토리, IRB 콘솔을 열고 다음을 입력 require './init'하고 당신은 당신의 전체 데이터베이스 및 모델 설정 대화 형 탐사로드가 .
Phrogz 2019

1
나 같은 Sinatra 멍청한 놈에게 완벽한 훌륭한 예시 구조.
Barry Jordan

27
다른 접근법을 사용했습니다. 'sinatra'를 요구하지 않고 사용자 및 서비스와 같은 모든 비즈니스 로직을 루비로 코딩하십시오. 이것은 논리를 독자적으로 만듭니다. 그런 다음 단일 앱 파일을 사용하여 다양한 클래스에 대한 책임을 처리하므로 경로 당 약 3 줄의 코드를 작성합니다. 일반적인 응용 프로그램에는 많은 경로가 없으므로 내 응용 프로그램 파일이 실제로 그렇게 길지는 않습니다.
Tom Andersen

1
여러 파일로 클래스를 정의하는 것이 일반적입니까? 모든 파일에서 'MyApp'을 반복해서 재정의하고 있습니다. 나는 루비를 처음 사용하므로 나에게는 이상하게 보인다. 이것의 이유는 무엇입니까?
0xSina

5
@ 0xSina 루비에서는 드문 일이 아닙니다. 수업을 "정의"하지 않고 "다시 열어야합니다". 예를 들어, Array클래스는 코어 라이브러리에 의해 정의되지만 나중에 class Array; def some_awesome_method; enda) 이전의 모든 Array 기능을 유지하고 b) 모든 Array 인스턴스는 새 코드를 가져 와서 "monkeypatch"를 정의 할 수 있습니다 . Ruby의 클래스는 객체 일 뿐이며 언제든지 기능을 보강하고 변경할 수 있습니다.
Phrogz

10

물론. 이에 대한 예를 보려면 여기에 설명 된 Monk gem을 다운로드하는 것이 좋습니다.

https://github.com/monkrb/monk

rubygems.org를 통해 'gem install'할 수 있습니다. gem이 있으면 위에 링크 된 지침을 사용하여 샘플 앱을 생성하십시오.

원하지 않는 한 실제로 개발하기 위해 Monk를 사용할 필요는 없습니다 (사실 현재 최신 버전이 아닐 수도 있음). 요점은 원하는 경우 별도의 컨트롤러와 같은 경로 파일을 사용하여 MVC 스타일로 앱을 쉽게 구성하는 방법을 보는 것입니다.

Monk가 처리하는 방식을 살펴보면 매우 간단합니다. 주로 별도의 디렉토리에 파일이 필요합니다 (root_path를 정의해야 함).

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

7
init.rb위와 명시적인 것을 사용하는 한 가지 좋은 점 은 상호 의존적 인 파일이있는 경우로드 순서를 제어 할 수 있다는 것입니다.
Phrogz 2019

10

Google에서 "Sinatra 상용구"를 검색하여 다른 사람들이 Sinatra 애플리케이션을 어떻게 배치하고 있는지에 대한 아이디어를 얻으십시오. 그로부터 당신은 아마 당신의 필요에 맞는 것을 찾거나 단순히 자신을 만들 수 있습니다. 너무 어렵지 않습니다. 더 많은 Sinatra 앱을 개발할 때 상용구에 추가 할 수 있습니다.

다음은 모든 프로젝트에서 만들고 사용한 것입니다.

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


7

나는 이것이 오래된 쿼리라는 것을 알고 있지만 여전히 아무도 Padrino를 언급하지 않았다. Sinatra 위에 프레임 워크로 사용하거나 관심있는 보석 만 추가 할 수 있습니다. 엉덩이 10 개를 찼습니다!


동의합니다. Padrino를 살펴 봐야합니다.
NicoPaez

2

같은 사이트에서 다른 프로젝트를 호스팅하는 나의 접근 방식 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

여기에서 문서를 읽으십시오.

시나트라 확장

Sinatra를 사용하면 Sinatra "register"메소드 또는 "helpers"메소드를 통해 애플리케이션을 Ruby 모듈로 분해 할 수 있습니다.

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

수도사가 나를 위해 일하지 않았을 때, 나는 스스로 템플릿 작업을 시작했다.

그것에 대해 생각하면 파일 세트를 묶는 데 특별한 것이 없습니다. 수도사 철학은 2011 년 초 RedDotRubyConf 기간 동안 나에게 설명되었으며 특히 유지 관리가 거의되지 않기 때문에 특히 사용하는 것이 선택 사항이라고 구체적으로 말했습니다.

이것은 ActiveRecord를 사용하려는 사람들에게 좋은 시작입니다.

간단한 시나트라 MVC

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


1

대규모 프로젝트를위한 Sinatra 모듈화의 핵심은 기본 도구를 사용하는 방법을 배우는 것입니다.

SitePoint에는 모듈 식 Sinatra 앱 및 도우미를 볼 수있는 훌륭한 자습서 가 있습니다. 그러나 한 가지 중요한 세부 사항에 특별한주의를 기울여야합니다. 여러 개의 Sinatra 앱을 유지 하고 Rackup으로 마운트 합니다. 기본 앱을 작성하는 방법을 알고 있으면 해당 자습서 의 config.ru 파일을보고 독립적 인 Sinatra 앱을 마운트하는 방법을 관찰하십시오.

Sinatra를 Rack과 함께 실행하는 법을 배우면 완전히 새로운 모듈화 전략의 세계가 열립니다. 이것은 실제로 유용한 것을 시도하도록 초대합니다. 이제 각 하위 응용 프로그램 마다 개별 Gems를 사용하여 모듈을 쉽게 버전 화 할 수 있습니다.

앱에 gem 모듈을 사용하는 힘을 과소 평가하지 마십시오. 잘 구분 된 환경에서 실험 변경 사항을 쉽게 테스트하고 쉽게 배포 할 수 있습니다. 문제가 발생하면 되돌릴 수 있습니다.

코드를 구성하는 수천 가지 방법이 있으므로 Rails와 비슷한 레이아웃을 얻는 데 어려움이 없습니다. 그러나 자신의 구조를 사용자 정의하는 방법에 대한 훌륭한 게시물 도 있습니다 . 이 게시물은 대부분의 웹 개발자의 다른 빈번한 요구를 다룹니다.

시간이 있다면 루비 기반 웹 애플리케이션의 일반적인 기반 인 Rack에 대해 더 배우는 것이 좋습니다. 작업 수행 방식에 훨씬 적은 영향을 줄 수 있지만 대부분의 사람들이 항상 랙 미들웨어로 더 적합한 앱에서 수행하는 특정 작업이 있습니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.