2011-10-28 8 views
3

これは簡単な答えになると思います。私はRubyとSinatraの両方に新しいです。ダイナミックルートに関するSinatraルーティング評価

私はsinatraアプリをモジュラーアプローチで書いていますが、私はプラグインの方法で新しいルートを追加できるようにしたいと考えています。

現在Sinatra :: Baseから継承したSinatraAppクラスがあります。ここにはプラグインフォルダを経由するload_pluginsというメソッドがあり、より多くのルートを含むモジュールであるすべてのrouting-definition.rbファイルが含まれています。

Sinatraがどのようにルーティングを管理しているのか疑問に思っています。 SinatraAppを最初に初期化し、ラックプロセス内(またはその中で実行しているもの)にメモリ内に保持するか、またはSinatraAppがすべての要求を再評価したかどうか?

シナリオでは、UserAがHTMLページを返すルートをロードし、UserAがリンクをクリックしてプラグインが存在しないため404を返した場合、AdminAはプラグインフォルダに新しいプラグインを追加し、UserAをリフレッシュしますそれらのページは、プラグインがルートを追加したので、404ではなくhtmlページを取得します。

Sinatraサーバーを再起動して新しいプラグインファイルを取得する必要はありますか?

私の一部は、ロードされたプラグインを毎回更新することを望んでいます...しかし、すべてのリクエストでプラグインのディレクトリをスキャンする必要がある場合は、パフォーマンスが低下することがわかります。

== EDITの==

は、私は以下の何を意味するかの例を追加しました。私はそれがモジュールのように構造化されているか、以下のようにインラインに残っているかどうかはわかりませんが、現在のスコープに文字通りコードダンプを入れると、SinatraMainアプリケーションのスコープ内でgetを "あなたが私が何をしているのかを示します。

require 'sinatra' 

class SinatraMain < Sinatra::Base 

    def load_plugins 
     Dir["/plugins/**/routing-plugin.rb"].each do |plugin_file| 
      include plugin_file 
     end 
    end 

    get "/test" do 
    return "This is a test route" 
    end 

get "/plugins/*" do 
    load_plugins 
    return "Plugins refreshed" 
end 
end 

SinatraMain.run! 

# Imagine this was within /plugins/SayHelloPlugin/routing-plugin.rb 
get "/say-hello" 
    return "Saying hello" 
end 

だから、アイデアはいつでもこれらのプラグインファイルをプラグインに追加されていることであるが、それは、アプリケーションへのルートを追加する必要がありますフォルダ、およびそれらが削除される場合、後者の点が(ルーティングの外にそれらを取りますこれほど重要ではない)。

答えて

2

私のソース(https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb)の読みから、SinatraはSinatra :: Baseクラスのクラス変数としてルートを保存しますSinatra/Rackはリクエストごとにアプリケーションの新しいインスタンスを作成しますが、各リクエストでルートの再評価は行われません。

すべてのルートを再ロードせずに、実行時に余分なルートを追加することはできます。私はあなたのプラグインをロードしているのか分からないが、シナトラを再起動せずに、あなたが欲しいものを行うことが可能である必要があり、これは新しいルートを追加し、粗デモ/実験である:

require 'rubygems' 
require 'sinatra/base' 

class App < Sinatra::Base 
    get '/' do 
    "hello [self.object_id: #{self.object_id}, App.routes.object_id: #{App.routes.object_id}]" 
    end 

    get '/add_route' do 
    App.get '/new_route' do 
     "from new route [self.object_id: #{self.object_id}, App.routes.object_id: #{App.routes.object_id}]" 
    end 
    "new route added [self.object_id: #{self.object_id}, App.routes.object_id: #{App.routes.object_id}]" 
    end 

    run! if /app.rb$/ =~ $0 
end 

あなたがこれを実行する場合をアプリケーションは各要求に対して新しいobject_idを取得しているが、App.routesハッシュは全体を通して同じオブジェクトであることがわかります。

+0

私は、私が意味するものの例で私のメインポストを編集します – Grofit

+0

だから、load_pluginsメソッドなどを起動するために、非ブロッキングファイルウォッチャーが必要になると思います。私が自分自身で行ったことではなく、Rubyファイルウォッチャーがいくつか用意されています。 EventMachineには、あなたのアプリに統合できると思うものがあります。あなたのプラグインファイルでは、あなたのSinatraMainクラスを拡張し、それをロードするためにKernel#loadまたはKernel#requireを使用することができます。削除されたプラグインを削除するには、削除するプラグインによってどのルートが追加されたのかを把握する必要があります。 – Steve

+0

現時点では、プラグインを読み込んでアプリケーションを再ロードして削除することに満足しています。現在私の例では、/ plugins/*ルートはすべてのプラグインを更新する必要があります。あなたに答えを与えるだろう! – Grofit