Sinatra + Rack маршрутизация
У меня есть файл приложения, который выглядит следующим образом ws_app.rb:
require 'rubygems'
require 'sinatra'
require 'sinatra/respond_to'
require 'dm-core'
require 'dm-migrations'
require 'dm-timestamps'
require 'json'
require 'csv'
load 'models/Battery.rb'
Sinatra::Application.register Sinatra::RespondTo
DataMapper::setup(:default,"sqlite3://#{Dir.pwd}/mpt_hmi.sqlite3")
class MPTHMI < Sinatra::Base
load 'controller/BatteryController.rb'
end
Модули /Battery.rb выглядят так:
class Battery
include DataMapper::Resource
property :id, Serial
property :i_battery_manager_id, Integer
property :c_battery_number, String
property :c_battery_state, String
property :c_voltage_byte, String
property :i_voltage_int, Integer
property :i_temperature, Integer
property :i_resistance, Integer
property :i_capacity, Integer
property :i_cell_balancing_duration, Integer
property :i_total_cell_balancing_duration, Integer
property :i_age, Integer
property :i_time_to_service, Integer
property :created_at, DateTime
property :updated_at, DateTime
def to_my_json
{
:i_battery_manager_id => self.i_battery_manager_id,
:c_battery_number => self.c_battery_number,
:c_battery_state => self.c_battery_state,
:c_voltage_byte => self.c_voltage_byte,
:i_voltage_int => self.i_voltage_int,
:i_temperature => self.i_temperature,
:i_resistance => self.i_resistance,
:i_capacity => self.i_capacity,
:i_cell_balancing_duration => self.i_cell_balancing_duration,
:i_total_cell_balancing_duration => self.i_total_cell_balancing_duration,
:i_age => self.i_age,
:i_time_to_service => self.i_time_to_service
}
end
end
Файл controller/BatteryController.rb выглядит следующим образом:
get '/battery/:id' do
@battery = Battery.get(params[:id])
respond_to do |wants|
wants.html { erb :battery } # html
wants.json { @battery.to_my_json.to_s } # json
end
end
get '/batteries' do
@batteries = Battery.all
respond_to do |wants|
wants.html { erb :batteries } # html
wants.json {
@batteries.all.inject({}) { |hsh, obj|
hsh[obj.id] = obj.to_my_json
hsh
}.to_json
}
end
end
Это прекрасно работает, когда я запускаю Sinatra нормально, вот так:
$ ruby ws_app.rb
== Sinatra/1.3.2 has taken the stage on 4567 for development with backup from Thin
>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:4567, CTRL+C to stop
Тогда иди сюда:
http://0.0.0.0:4567/battery/5.json
Я получаю JSON, который я ожидаю:
{:i_battery_manager_id=>1, :c_battery_number=>"5", :c_battery_state=>"3", :c_voltage_byte=>"145", :i_voltage_int=>191, :i_temperature=>107, :i_resistance=>81, :i_capacity=>228, :i_cell_balancing_duration=>127, :i_total_cell_balancing_duration=>37, :i_age=>111, :i_time_to_service=>211}
но мне нужно развернуть это на веб-сервере Cherokee, поэтому я хочу сделать для этого файл стойки config.ru...
Итак, у меня есть файл mpthmiws.rb, который содержит
load 'ws_app.rb'
MPTHMI.run
И файл config.ru, который содержит
load 'mpthmiws.rb'
run MPTHMI.new
Когда я бегу
$ rackup config.ru
>> Thin web server (v1.3.1 codename Triple Espresso)
>> Maximum connections set to 1024
>> Listening on 0.0.0.0:9292, CTRL+C to stop
и иди сюда:
http://0.0.0.0:9292/battery/1.json
но потом я получаю знаменитое: "Синатра не знает эту пустышку - попробуйте завершить" /battery/1.json ""Hello World"
Если я беру первый маршрут из файла controller/BatteryController.rb и помещаю его в класс HMIMPT в файле ws_app.rb следующим образом:
require 'rubygems'
require 'sinatra'
require 'sinatra/respond_to'
require 'dm-core'
require 'dm-migrations'
require 'dm-timestamps'
require 'json'
require 'csv'
load 'models/Battery.rb'
Sinatra::Application.register Sinatra::RespondTo
DataMapper::setup(:default,"sqlite3://#{Dir.pwd}/mpt_hmi.sqlite3")
class MPTHMI < Sinatra::Base
get '/battery/:id' do
@battery = Battery.get(params[:id])
respond_to do |wants|
wants.html { erb :battery } # html
wants.json { @battery.to_my_json.to_s } # json
end
end
end
Я получаю эту ошибку:
undefined method `respond_to' for #<MPTHMI:0x00000001240a80>
Как я могу решить это? Спасибо
1 ответ
Прежде всего, эта вещь с mpthmiws.rb и config.ru слишком сложна. Удалите mpthmiws.rb и используйте этот config.ru для использования с rackup config.ru
:
require './ws_app'
run MPTHMI
Если вы хотите запустить приложение с простым старым ruby ws_app.rb
, используйте этот файл run.rb:
require './ws_app'
MPTHMI.run!
Что приводит нас к следующему пункту: НИКОГДА НЕ ИСПОЛЬЗОВАТЬ load
! Он выполняет код в загруженном файле, но не переносит никаких определенных переменных, функций и т. Д. require
вместо! Здесь вы должны префикс пути ./
или добавить ./
в $LOAD_PATH
, но в свою очередь вы можете опустить .rb
расширение.
Далее ваш файл BatteryController.rb. Это должно выглядеть так: require 'sinatra/response_to'
class BatteryController < Sinatra::Base
register Sinatra::RespondTo
get '/battery/:id' do
# ...
end
get '/batteries' do
# ...
end
end
И это также точка, где вы register
ваши расширения - в классе, где вам это нужно.
Теперь, когда мы понимаем, как load
работает, вы, возможно, уже заметили, что вы на самом деле не загружали get
блокирует в MPTHMI
класс, а скорее их выполнение вне класса. Это единственная причина, почему ваше приложение все равно работало со старым ruby ws_app.rb
!
Вы можете правильно включить свой контроллер в класс с use
:
# require all your gems
# ...
require './models/Battery'
require './controller/BatteryController'
DataMapper::setup(:default,"sqlite3://#{Dir.pwd}/mpt_hmi.sqlite3")
class MPTHMI < Sinatra::Base
use BatteryController
end
Вы также можете оставить register
здесь. Не стесняйтесь комментировать, если у вас есть дополнительные вопросы!
И вот полный diff:
diff --git a/config.ru b/config.ru
index eaa15fe..1568544 100644
--- a/config.ru
+++ b/config.ru
@@ -1,3 +1,3 @@
-load 'mpthmiws.rb'
+require './ws_app'
-run MPTHMI.new
+run MPTHMI
diff --git a/controller/BatteryController.rb b/controller/BatteryController.rb
index 31e4910..c500c48 100644
--- a/controller/BatteryController.rb
+++ b/controller/BatteryController.rb
@@ -1,20 +1,27 @@
-get '/battery/:id' do
- @battery = Battery.get(params[:id])
- respond_to do |wants|
- wants.html { erb :battery } # html
- wants.json { @battery.to_my_json.to_s } # json
- end
-end
+require 'sinatra/respond_to'
-get '/batteries' do
- @batteries = Battery.all
- respond_to do |wants|
- wants.html { erb :batteries } # html
- wants.json {
- @batteries.all.inject({}) { |hsh, obj|
- hsh[obj.id] = obj.to_my_json
- hsh
- }.to_json
- }
+class BatteryController < Sinatra::Base
+ register Sinatra::RespondTo
+
+ get '/battery/:id' do
+ @battery = Battery.get(params[:id])
+ respond_to do |wants|
+ wants.html { erb :battery } # html
+ wants.json { @battery.to_my_json.to_s } # json
+ end
end
-end
+
+ get '/batteries' do
+ @batteries = Battery.all
+ respond_to do |wants|
+ wants.html { erb :batteries } # html
+ wants.json {
+ @batteries.all.inject({}) { |hsh, obj|
+ hsh[obj.id] = obj.to_my_json
+ hsh
+ }.to_json
+ }
+ end
+ end
+
+end
\ No newline at end of file
diff --git a/mpt_hmi.sqlite3 b/mpt_hmi.sqlite3
index e69de29..9897cd9 100644
Binary files a/mpt_hmi.sqlite3 and b/mpt_hmi.sqlite3 differ
diff --git a/mpthmiws.rb b/mpthmiws.rb
deleted file mode 100644
index 87f3406..0000000
--- a/mpthmiws.rb
+++ /dev/null
@@ -1,3 +0,0 @@
-load 'ws_app.rb'
-
-MPTHMI.run
diff --git a/ws_app.rb b/ws_app.rb
index 1cab867..4a6e332 100644
--- a/ws_app.rb
+++ b/ws_app.rb
@@ -1,19 +1,18 @@
require 'rubygems'
require 'sinatra'
-require 'sinatra/respond_to'
require 'dm-core'
require 'dm-migrations'
require 'dm-timestamps'
require 'json'
require 'csv'
-load 'models/Battery.rb'
+require './models/Battery'
+require './controller/BatteryController'
-Sinatra::Application.register Sinatra::RespondTo
DataMapper::setup(:default,"sqlite3://#{Dir.pwd}/mpt_hmi.sqlite3")
class MPTHMI < Sinatra::Base
-
- load 'controller/BatteryController.rb'
+
+ use BatteryController
end