動的ルートに関するSinatraルーティング評価

うまくいけば、これは簡単な答えになるでしょう、私はRubyと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

したがって、プラグインフォルダにこれらのプラグインファイルが追加されるたびに、アプリケーションにルートを追加し、それらが削除されたときにルーティングから外してください(後者のポイントは ' tは今のところ重要です)。

3

1 答え

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

すべてのルートを再ロードせずに、実行時に余分なルートを確実に追加することができます。私はあなたのプラグインをどのようにロードしているのか分かりませんが、Sinatraを再起動せずにやりたいことができるはずです。これは新しいルートを追加するためのデモ/実験です:

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

これを実行すると、各リクエストでAppが新しいobject_idを取得していても、App.routesハッシュが同じオブジェクトになっていることがわかります。

2
追加された
私は私が意味するものの例と私のメインポストを編集します
追加された 著者 Grofit,
現時点では、プラグインを読み込んでアプリケーションを再ロードして削除することに満足しています。現在私の例では、/ plugins/*ルートはすべてのプラグインを更新する必要があります。あなたに答えを与えるだろう!
追加された 著者 Grofit,
ですから、load_pluginsメソッドなどをトリガーするには、非ブロッキングファイルウォッチャーが必要になると思います。私が自分自身で行ったことではなく、Rubyファイルウォッチャーがいくつか用意されています。 EventMachineには、あなたのアプリに統合できると思うものがあります。あなたのプラグインファイルでは、あなたのSinatraMainクラスを拡張し、それをロードするためにKernel#loadまたはKernel#requireを使用することができます。削除されたプラグインを削除するには、削除するプラグインによってどのルートが追加されたのかを把握する必要があります。
追加された 著者 Steve,