首页 文章

Sinatra Rack路由

提问于
浏览
1

我有一个看起来像这个ws_app.rb的app文件:

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

modules / 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}

但我需要在切诺基网络服务器上部署这个,所以我想为此制作一个机架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

但后来我得到了着名的,“Sinatra不知道这个小曲 - 尝试得到'/battery/1.json'做”Hello World“结束

如果我从controller / BatteryController.rb文件中获取第一个路径并将其放在ws_app.rb文件中的HMIMPT类中,如下所示:

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 回答

  • 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'sinatrara / respond_to'

    class BatteryController < Sinatra::Base
      register Sinatra::RespondTo
    
      get '/battery/:id' do 
         # ...
      end
    
      get '/batteries' do 
        # ...
      end
    end
    

    这也是您扩展的地方 - 在您需要的课程中 .

    现在我们已经了解 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 --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
    

相关问题