Развертывание приложения Sinatra на Heroku
Я озадачен тем, что на самом деле не является практической проблемой - просто концептуальной головоломкой - о развертывании приложения Sinatra на Heroku.
У меня есть два приложения, идентичных практически во всех отношениях, за исключением того, что одно помещает большую часть своей логики в файл, который не содержит класс Sinatra::Base, и использует 'require otherfilename', чтобы выбрать нужную логику. Этот Синатра: Базовый класс называется Kincalc.
Для приложения со всей логикой в одном файле (то есть в том же файле, который содержит класс Sinatra:Base), в моем файле config.ru последняя строка гласит "Запустите Sinatra::Application", и он нормально запускается. Но в другом приложении, если я добавлю это в качестве последней строки, приложение будет загружено правильно и сообщит, что оно "развернуто в Heroku", но выдает сообщение "Not found". Когда у меня есть последняя строка "запустить Kincalc", он загружается нормально.
Я проверил это взад и вперед, и нет ничего особенного в том, как эти два приложения построены, за исключением того факта, что одно использует второй файл для логики (который также находится в корне). Почему это должно быть проблемой, или это действительно проблема? Когда я пытаюсь поместить второй файл (тот, у которого нет класса Sinatra) в отдельную папку lib, он все равно работает, когда я вызываю имя класса, но не когда я называю "Sinatra::Application".
1 ответ
Код на верхнем уровне будет делегирован Sinatra::Application
, так что это будет сценарий для запуска классического приложения:
# app.rb
require 'sinatra'
get '/' do
'hi'
end
# config.ru
require './app'
run Sinatra::Application
Если вы определите модульное приложение, вы запустите его так:
# app.rb
require 'sinatra/base'
class Kincalc < Sinatra::Base
get '/' do
'hi'
end
end
# config.ru
require './app'
run Kincalc
Теперь я предполагаю, что вы пытаетесь сделать это:
# otherfilename.rb
require 'sinatra'
get '/' do
'hi'
end
# app.rb
require 'sinatra/base'
class Kincalc < Sinatra::Base
require './otherfilename'
end
# config.ru
require './app'
run Kincalc # Sinatra::Application seems to work
Поведение, которое вы испытываете (получение файла 404 Not Found) на самом деле правильно, так как require
не заботится о лексической области, в которой он вызывается. Посмотрите на следующий пример
# a.rb
puts "in a, top level: #{self.inspect}"
module Example
puts "in a, nested: #{self.inspect}"
require 'b'
end
# b.rb
puts "in b: #{self.inspect}"
Полученный результат должен быть:
in a, top level: main
in a, nested: Example
in b: main
Итак, если вы хотите использовать одно модульное приложение, вы должны сделать что-то вроде этого:
# otherfilename.rb
Kincalc.get '/' do
'hi'
end
Или снова откройте класс:
# otherfilename.rb
class Kincalc
get '/' do
'hi'
end
end
Или вы могли бы на самом деле иметь otherfilename.rb
сделать его определения на Sinatra::Application
и использовать это в Kincalc
,
# app.rb
require 'sinatra/base'
require './otherfilename'
class Kincalc < Sinatra::Base
use Sinatra::Application
end
Или вы можете изменить место делегирования методов DSL верхнего уровня:
# app.rb
require 'sinatra/base'
class Kincalc < Sinatra::Base
Sinatra::Delegator.target = self
require './otherfilename'
end