Развертывание приложения 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
Другие вопросы по тегам