Оценка маршрутов Синатры, относящихся к динамическим маршрутам - PullRequest
3 голосов
/ 28 октября 2011

Надеюсь, это будет простой ответ, я новичок в Ruby и Sinatra.

Я смотрю на написание приложения sinatra с использованием модульного подхода, однако я хочу иметь возможность добавлять новые маршрутыв виде плагина.

В настоящее время у меня есть мой класс SinatraApp, который наследуется от Sinatra :: Base, теперь у меня есть там метод load_plugins, который проходит через папку плагинов и включает все файлы routing-definition.rb,которые являются модулями, содержащими больше маршрутов.

Итак, учитывая этот контекст вопроса, мне интересно, как Синатра управляет своей маршрутизацией.Является ли это случаем, когда он сначала инициализирует, загружает SinatraApp, а затем сохраняет его в памяти внутри процесса стойки (или независимо от того, где вы его запускаете), или SinatraApp переоценивает каждый запрос?

TakeВ этом сценарии UserA загружает маршрут, который возвращает HTML-страницу, UserA щелкает ссылку и возвращает 404, так как плагин не существует, AdminA затем добавляет новый плагин в папку плагинов, UserA затем обновляет свою страницу, и они получаютhtml-страница, а не 404. Как плагин добавил маршрут.

Произойдет ли это выше, или мне нужно будет перезапустить сервер Sinatra, чтобы он взял новый файл плагина?

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

== EDIT ==

Добавил пример того, что я имею в виду ниже.Я не уверен, должен ли он быть структурирован как модуль или оставлен встроенным, как показано ниже, если включить буквально дампы кода в текущую область видимости, чтобы get "" знал, что он должен вызывать get в рамках приложения SinatraMain, в любом случаедает вам представление о том, что мне нужно.

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

Таким образом, идея заключается в том, что всякий раз, когда эти файлы plugin добавляются в папку плагинов, он должен затем добавлять маршруты в приложение,и когда они будут удалены, выведите их из маршрутизации (хотя последний момент пока не так важен).

1 Ответ

2 голосов
/ 28 октября 2011

Из моего прочтения источника (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

Если вы запустите это, вы увидите, что приложение получает новый object_id при каждом запросе, но хэш App.routes - это один и тот же объект повсюду.

...