Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
1.0k views
in Technique[技术] by (71.8m points)

ruby - Sinatra does not start with twitter gem

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.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

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'

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...