1

我有一个看起来像这样 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

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 

控制器/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 不知道这个小曲 - 尝试 get '/battery/1.json' do "Hello World" end

如果我从控制器/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>

我该如何解决这个问题?谢谢

4

1 回答 1

1

First of all, that thing with mpthmiws.rb and config.ru is overly complicated. Delete mpthmiws.rb and use this config.ru for use with rackup config.ru:

require './ws_app'

run MPTHMI

If you want to run the App with plain old ruby ws_app.rb, use this run.rb file:

require './ws_app'

MPTHMI.run!

Which brings us to the next point: NEVER EVER USE load! It executes the code in the loaded file, but it does not bring over any defined variables, functions etc. Use require instead! Here you must prefix the path with ./ or add ./ to $LOAD_PATH, but in turn you can omit the .rb extension.

Next is your BatteryController.rb file. It should look like this: require 'sinatra/respond_to'

class BatteryController < Sinatra::Base
  register Sinatra::RespondTo

  get '/battery/:id' do 
     # ...
  end

  get '/batteries' do 
    # ...
  end
end

And this is also the point where you register your extensions — in the class where you need it.

Now that we understand how load works, you may already have noticed that you were not actually loading the get blocks into the MPTHMI class, but rather executing them outside of the class. That is the only reason why your app worked anyway with plain old ruby ws_app.rb!

You can properly include your controller into a class with 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

You can also leave off the register in here. Feel free to comment if you have further questions!


And here's the full 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
于 2012-07-02T10:34:33.450 回答