I would like to user Redis in my Sinatra app. Though I can access Redis instance in the console on local and remote (heroku), when I want to use it in a rake task, an error is triggered and I don t seem to get why is that.
app.rb:
class MyApp < Sinatra::Base
configure do
uri = URI.parse(ENV["REDISCLOUD_URL"])
$redis = Redis.new(:host => uri.host, :port => uri.port, :password => uri.password)
end
end
config.ru:
require 'rubygems'
require 'sinatra'
require './app'
run MyApp
Gemfile
gem 'redis'
Rakefile.rb
desc 'Try Redis'
task :try_redis do
puts $redis.set("try", 0)
end
rake aborted! NoMethodError: undefined method `set' for nil:NilClass
I am not really used to Sinatra, and nothing looks particularly wrong to me. I do not understand why my global variable $redis would not be accessible from everywhere in my app...
If you can enlighten me, thank you by advance!
I do not understand why my global variable $redis would not be
accessible from everywhere in my app
Your rake task is not related to your app. The $redis variable available only when you run sinatra server and not available when you run your rake task. The rake task run in own thread.
Related
This is my web app:
class Front < Sinatra::Base
configure do
set :server, :puma
end
get '/' do
'Hello, world!'
end
end
I start it like this (don't suggest to use Rack, please):
Front.start!
Here is my configuration object for Puma, which I don't know how to pass to it:
require 'puma/configuration'
Puma::Configuration.new({ log_requests: true, debug: true })
Seriously, how?
Configuration is tightly connected to a way in which you run puma server.
The standard way to run puma - puma CLI command. In order to configure puma config file config/puma.rb or config/puma/<environment>.rb should be provided (see example).
But you asked how to pass Puma::Configuration object to puma. I wonder why you need it but AFAIK you need to run puma server programmatically in your application code with Puma::Launcher(see source code)
conf = Puma::Configuration.new do |user_config|
user_config.threads 1, 10
user_config.app do |env|
[200, {}, ["hello world"]]
end
end
Puma::Launcher.new(conf, events: Puma::Events.stdio).run
user_config.app may be any callable object (compatible with Rack interface) like Sinatra application.
Hope it's helpful.
Do you want to pass exactly an object or just a configuration in general? For the last option it's possible, but Puma will not log anything anyway (I'm not sure, but seems like you worry exactly about logging settings for Puma).
#!/usr/bin/env ruby
# frozen_string_literal: true
require 'bundler/inline'
gemfile(true) do
gem 'sinatra'
gem 'puma'
gem 'openssl'
end
require 'sinatra/base'
class Front < Sinatra::Base
configure do
set :server, :puma
set :server_settings, log_requests: true, debug: true, environment: 'foo'
end
get '/' do
'Hello, world!'
end
end
Front.start!
I've only been able to find rails answers to this question. Whenever I run rake db:migrate I am getting the aforementioned error. As far as I am aware, I have setup everything correctly so have no idea what's wrong.
config/environment.rb
ENV['SINATRA_ENV'] ||= "development"
require 'bundler/setup'
Bundler.require(:default, ENV['SINATRA_ENV'])
configure :develpoment do
set :database, 'sqlite3:db/database.db'
end
require './app'
Rakefile
require "./config/environment"
require "sinatra/activerecord/rake"
when i try to start sinatra, i'm getting following error
/var/lib/gems/1.9.1/gems/sinatra-1.4.4/lib/sinatra/base.rb:1488:in start_server': undefined methodrun' for HTTP:Module (NoMethodError)
require 'sinatra/base'
require_relative "twt.rb"
class SinatraApp < Sinatra::Base
set :static, true
set :public_folder, File.dirname(__FILE__) + '/static'
get '/getuserinfo' do
#user = twit.getuserinfo
erb :userInfo
end
end
SinatraApp.run!
in "twt.rb" i require twitter (5.7.1)
require 'twitter'
class Twit
attr_accessor :client
def initialize(consumer_key,consumer_secret,access_token,access_token_secret)
#client = Twitter::REST::Client.new do |config|
config.consumer_key = consumer_key
config.consumer_secret = consumer_secret
config.access_token = access_token
config.access_token_secret = access_token_secret
end
end
def getUserInfo
return user = {
"name"=> client.current_user.name,
"id" => client.current_user.id
}
end
def showAllFriends
client.friends.each { |item| puts item.name }
end
def showFollowers
client.followers.each { |item| puts item.screen_name }
end
def showAllTweets
client.user_timeline.each {|item| puts item.text}
end
def showAllUserTweets(userScreenName)
client.user_timeline(userScreenName).each {|item| puts item.text}
end
def sendTweet(content)
client.update(content)
end
end
if i remove require_relative "twt.rb" line sinatra works fine.
When you run a Sinatra app using the built-in web server (as you do with SinatraApp.run!), Sinatra tries to determine which server to use by checking a list of servers in turn to see which is available. The actual list depends on the version of Ruby you are using, but one server that it always checks is net-http-server, which is simply named HTTP.
The way Sinatra checks for the availability of a server is by using a rack method that calls const_get to try and find the constant Rack::Handler::<server-name>. However, due to the way const_get works, if that constant is not available, but a top level constant with the same name as server-name is, then that will be returned, whatever class it is. (This is arguably a bug in Rack).
The Twitter gem depends on the http gem, and that in turn defines a HTTP module. (Naming a top-level module with something as generic as HTTP is arguably not a good idea).
So what is happening in this case is Sinatra is checking to see if the HTTP server is available, but Rack is returning the HTTP module from the http gem, which isn’t a server. Not being a Rack server it doesn’t have a run method, so when Sinatra tries to use it as one you get the error start_server': undefined method `run' for HTTP:Module.
One workaround is not to use the built-in server, such as the way you have discovered using a config.ru file and starting the app with rackup.
Another solution is to explicitly specify the server to use in your Sinatra app. For example you could install Thin, and then use:
set :server, 'thin'
In fact simply installing Thin would be sufficient as Thin is searched for before HTTP, but you are probably better explicitly setting the server to use. If you cannot install any other server for any reason you could use Webrick instead:
set :server, 'webrick'
i found the solution.
i launch sinatra with config.ru and it works now.
rack config.ru
I'm having trouble using the Ruby URI module's encode_www_form method in a modular Sinatra app. For some reason, URI is interpreted as being the URI::Parser subclass, and so the method call understandably fails.
I've reduced this to a minimal test case. The Gemfile:
source 'https://rubygems.org'
ruby '1.9.3'
gem 'sinatra'
And app.rb:
require 'sinatra/base'
class Frontend < Sinatra::Base
get '/test/' do
URI.encode_www_form(:a => 1, :b => 2)
end
run! if app_file == $0
end
If I then run ruby app.rb and access /test/ I get:
NoMethodError - undefined method `encode_www_form' for #<URI::Parser:0x007fa9221ca868>:
app.rb:6:in `block in <class:Frontend>'
If I convert it to a classic-style Sinatra app, so that app.rb is like this:
require 'sinatra'
get '/test/' do
URI.encode_www_form(:a => 1, :b => 2)
end
Then call ruby app.rb and access /test/, the page shows "a=1&b=2" as desired.
So what's going wrong in the modular format that means something's up with URI?
The class Sinatra::Base redefines URI on line 856 of https://github.com/sinatra/sinatra/blob/master/lib/sinatra/base.rb, which is why your URI reference gets evaluated as that value.
If you want to avoid this problem, you can change your reference to ::URI.
As of Sinatra 1.4.4, the URI module is no longer overwritten.
I tried to reproduce this in irb. This may sound stupid, but require 'uri' did the trick there.
I use Sinatra modular style, i don't know what going bad. I serach google but didn't find anything
require 'sinatra/base'
class App < Sinatra::Base
get '/' do
haml '%h1 Test'
end
end
run App
And a see test.rb:12:in <main>': undefined methodrun' for main:Object (NoMethodError)
What going wrong?
did you run it via ruby -rubygems hi.rb (assuming this code is in hi.rb). If so, you don't need run App. Unless you are running it through another framework built on/with Sinatra.
Also might want to include haml...
You have a config.ru:
# config.ru
require 'my_app'
run MyApp
and a my_app.rb:
# my_app.rb
require 'sinatra/base'
require 'haml'
class MyApp < Sinatra::Base
get('/') { haml '%h1 Test' }
# start the server if ruby file executed directly
run! if app_file == $0
end
then in the folder where the my_app.rb is run this to start the app on localhost:4657:
rackup -p 4567
Regarding the comment above where the error below is displayed:
`start_tcp_server': no acceptor (RuntimeError)
This appears when you are trying to bind to an already bound port. Trying a different port number should resolve.