undefined method `run' for main:Object (NoMethodError) Sinatra - sinatra

require 'sinatra/base'
class Foo < Sinatra::Base
get('/foo') { 'foo' }
end
class Bar < Sinatra::Base
get('/bar') { 'bar' }
end
run Rack::Cascade, [Foo, Bar]
I just can't guess what is wrong with this code.
When I ran: ruby server.rb, it throws an error

First of all, the last line should read
run Rack::Cascade.new [Foo, Bar]
But you can only use this in a Rackup File. So second, you need to create a File called config.ru (Rackup File) with the following contents:
require './app'
run Rack::Cascade.new [Foo, Bar]
and a file called app.rb with your actual app:
require 'sinatra/base'
class Foo < Sinatra::Base
get('/foo') { 'foo' }
end
class Bar < Sinatra::Base
get('/bar') { 'bar' }
end
then you can start the server by typing in the command line
$ rackup
>> 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
after that, open a second command line window and test your app:
$ curl 0.0.0.0:9292/foo
foo%
$ curl 0.0.0.0:9292/bar
bar%

Related

rails calling get request twice

I am using rails 5 and I am trying to save an object to my db with some parameters on a get request. But for some reason my object is getting saved twice.
here is my code in controller
class ParticipantCardController < ApplicationController
before_action :authenticate_user!
before_action :authenticate_current_user_profile
def participate
# byebug
params.permit(:event_id, :_method, :authenticity_token)
event_id=params[:event_id].to_i
byebug
#new_participant = ParticipantCard.new
#new_participant.user=current_user
#new_participant.event_id=event_id
#new_participant.name=" "
#new_participant.description=" "
#new_participant.save
# end
# flash[:error] = #new_participant.errors.messages
end
this is code calls the insert sql query twice, like so:
terminal query

Sinatra + Rack routing

I have an app file that looks like this 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
The modules/Battery.rb looks like this:
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
The controller/BatteryController.rb file looks like this:
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
This works perfectly when I run Sinatra normally, like so:
$ 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
Then go here:
http://0.0.0.0:4567/battery/5.json
I get the JSON I'm expecting:
{: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}
but I need to deploy this on a Cherokee web server, so I want to make a rack config.ru file for this...
So I have a file mpthmiws.rb which contains
load 'ws_app.rb'
MPTHMI.run
And a config.ru file which contains
load 'mpthmiws.rb'
run MPTHMI.new
When I run
$ 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
and go here:
http://0.0.0.0:9292/battery/1.json
but then I get the famous, "Sinatra doesn't know this ditty - try get '/battery/1.json' do "Hello World" end
If I take the first route from the controller/BatteryController.rb file and put it inside HMIMPT class in the ws_app.rb file like this:
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
I get this error:
undefined method `respond_to' for #<MPTHMI:0x00000001240a80>
How can I resolve this?
Thanks
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

Rails Tutorial Chapter 8 - undefined local variable or method `signin_path'

I'm getting the following rSpec failed tests error.
What did I do wrong?
Many thanks..
1) Authentication signin page Failure/Error: before { visit signin_path } NameError: undefined local variable or method signin_path' for # # ./spec/requests/authentication_pages_spec.rb:8:inblock (3 levels) in '
2) Authentication signin page Failure/Error: before { visit signin_path } NameError: undefined local variable or method signin_path' for # # ./spec/requests/authentication_pages_spec.rb:8:inblock (3 levels) in '
session_controller.rb:
class SessionsController < ApplicationController
def
new
end
def
create
end
def
destroy
end
end
routes.rb:
SampleApp::Application.routes.draw do
resources :users
resources :sessions, only: [:new, :create, :destroy]
root to: 'static_pages#home'
match '/signup', to: 'users#new'
match '/signin', to: 'sessions#new'
match '/signout', to: 'sessions#destroy', via: :delete
authentication_pages_spec.rb:
require 'spec_helper'
describe "Authentication" do
subject { page }
describe "signin page" do before { visit signin_path }
it { should have_selector('h1', text: 'Sign in') }
it { should have_selector('title', text: 'Sign in') }
end
end
I had this same issue and restarting guard/spork after I created my routes solved the problem
Did you add the signin route to routes.rb and not restart spork (assuming you're using it) before running your tests?
Can you run rake routes from your console and show the output

Sinatra streaming app + em::periodic timer at launch

I need to create a streaming webapp with Sinatra, I try to use a single "source" of streaming when i have multiples connections open, what's the best way to do it?
I can't test before fews days but my primary idea is something like this :
set :server, :thin
connections = []
configure do
EventMachine::PeriodicTimer.new(1) do
connections.each { |out| out << "test" << "\n" }
end
end
get '/' do
stream(:keep_open) { |out| connections << out }
end
In case you didn't manage to make it work:
require 'sinatra/base'
class MyApp < Sinatra::Base
set :path, '/tmp'
set :environment, 'production'
def initialize
#connections = []
EM::next_tick do
EM::add_periodic_timer(1) do
#connections.each do |out|
out << "test" << "</br>"
end
end
end
end
get '/' do
stream(:keep_open) do |out|
#connections << out
end
end
end
run MyApp.new
I always prefer to use a proper class for sinatra applications, in this case it allows storing the connections without relying on global or pseudo global variables.

Setting env when using rspec to test omniauth callbacks

I'm having a strange problem when trying to set a callback for Facebook Authentication via Omniauth. In my controller (simplified to just the code necessary to show the error) I have:
class Users::OmniauthCallbacksController < Devise::OmniauthCallbacksController
def facebook
raise env.inspect
# auth_hash = env["omniauth.auth"]
end
end
this works in production mode, showing me the hash. However in test mode env is set to nil.
I have the following set in my spec_helper.rb file
OmniAuth.config.test_mode = true
OmniAuth.config.add_mock(:facebook, {"credentials" => {
"token" => "foo-token"
}
})
and my spec looks like this:
require 'spec_helper'
describe Users::OmniauthCallbacksController do
describe "Facebook" do
before(:each) do
request.env["devise.mapping"] = Devise.mappings[:user]
request.env["omniauth.auth"] = OmniAuth.config.mock_auth[:facebook]
end
it "should be a redirect" do
get :facebook
response.should redirect_to(root_path)
end
end
end
Can anyone enlighten me on what I need to do to have env not be nil when running my tests?
I use the following in my spec_helper.rb :
RACK_ENV = ENV['ENVIRONMENT'] ||= 'test'
I don't use Rails or Devise though so YMMV. I've also seen various threads saying that someone had to do this before their requires to get it to work.