undefined local variable or method `res' for main:Object (NameError) - ruby

I have the following little script that connects to a host, and gets some output.
#!/usr/bin/env ruby
require 'net/http'
require 'net/https'
require 'timeout'
serverurl = "http://www.google.com/"
uri = URI(serverurl)
res = Net::HTTP.post_form(uri, 'method' => 'login', 'username' => 'admin', 'password' => 'MySup3rDup3rp#55w0rd')
cookie = res['set-cookie']
if cookie.nil?
puts "No cookie"
end
I want to use some timeout so I do:
#!/usr/bin/env ruby
require 'net/http'
require 'net/https'
require 'timeout'
serverurl = "http://www.google.com/"
uri = URI(serverurl)
begin
timeout(10) do
res = Net::HTTP.post_form(uri, 'method' => 'login', 'username' => 'admin', 'password' => 'MySup3rDup3rp#55w0rd')
end
rescue StandardError,Timeout::Error
puts "#{server} Timeout"
exit(1)
end
cookie = res['set-cookie']
if cookie.nil?
puts "No cookie"
end
Now I get some error:
test.rb:20:in `<main>': undefined local variable or method `res' for main:Object (NameError)
I don't know why, because a similar test code works without error:
require "timeout"
begin
timeout(6) do
sleep
end
#rescue # under ruby >= 1.9 is ok
rescue StandardError,Timeout::Error # workaround for ruby < 1.9
p "I'm sorry, Sir. We couldn't make it, Sir."
end
Any idea what am I doing wrong?

This is about scope. In Ruby, variables are only visible within the same scope where they are defined (exceptions are instance-, class-, and global variables as well as constants).
So in your example, res is only visible within the timeout-block. Add res = nil before the begin-block to make sure res is defined in the scope you actually need the value.

Related

Where to put auth information

So I'm making a small program in VisualRuby that can tweet. So here's what my main.rb looks like:
#!/usr/bin/ruby
require 'vrlib'
require 'twitter_oauth'
#make program output in real time so errors visible in VR.
STDOUT.sync = true
STDERR.sync = true
#everything in these directories will be included
my_path = File.expand_path(File.dirname(__FILE__))
require_all Dir.glob(my_path + "/bin/**/*.rb")
LoginWindow.new.show
and my LoginWindow.rb looks like this
require 'twitter_oauth'
class LoginWindow #(change name)
include GladeGUI
client = TwitterOAuth::Client.new(
:consumer_key => '****',
:consumer_secret => '****',
:token => '****-****',
:secret => '****'
)
def show()
load_glade(__FILE__) #loads file, glade/MyClass.glade into #builder
set_glade_all() #populates glade controls with insance variables (i.e. Myclass.label1)
show_window()
end
def button1__clicked(*argv)
if client.authorized?
puts "true"
end
end
end
And finally my window looks like this:
Now when I run this and click the login button, VR spits this out
C:/Users/*/visualruby/Test/bin/LoginWindow.rb:22:in `button1__clicked': undefined local variable or method `client' for #<LoginWindow:0x3f56aa8>
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.33/lib/GladeGUI.rb:146:in `call'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.33/lib/GladeGUI.rb:146:in `block (3 levels) in parse_signals'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.33/lib/GladeGUI.rb:331:in `call'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.33/lib/GladeGUI.rb:331:in `main'
from C:/Ruby193/lib/ruby/gems/1.9.1/gems/vrlib-0.0.33/lib/GladeGUI.rb:331:in `show_window'
from C:/Users/*/visualruby/Test/bin/LoginWindow.rb:17:in `show'
from main.rb:14:in `<main>'
I don't think I'm supposed to put the client = Twitter.... stuff inside the LoginWindow class but I can't think of anywhere else to put it. Any ideas on how to fix this issue?
This is a quick solution for what you need.
in your LoginWindow.rb
def initialize
#client = TwitterOAuth::Client.new(
:consumer_key => '****',
:consumer_secret => '****',
:token => '****-****',
:secret => '****'
)
end
def button1__clicked(*argv)
if #client.authorized?
puts "true"
end
end
The problem with this solution is now you can't call button1_clicked without initializing LogginWindow before, so be careful.

Ruby NoMethodError (undefined method `map') in Post Request

I'm trying to do a POST request from a ruby app and I'm getting the following error.
Here is the code:
def action_reply(token,action_id,reply_text)
require 'uri'
require 'net/http'
require 'net/https'
#reply = { 'ACTION_ID' => action_id, 'text' => reply_text }.to_json
#A token is required to do this post
#token_url = 'https://example.com/reply?oauth_token=' + token
uri = URI.parse(#token_url)
response = Net::HTTP.post_form(uri,#reply)
end
I'm getting an error in the last step that says:
NoMethodError (undefined method `map' for #<String:0x000000063798e8>)
Any idea why this is?
Thanks!
Because you're passing a string to a method expecting a hash: remove the to_json call.
Unrelated, but is it necessary to have those instance variables be instance variables?

Daemonizing Mailman app

Starting my mailman app by running rails runner lib/daemons/mailman_server.rb works fine.
When starting with my daemon script and command bundle exec rails runner script/daemon run mailman_server.rb, the script generates an error:
.rvm/gems/ruby-1.9.3-p194/gems/mailman-0.5.3/lib/mailman/route/conditions.rb:21:in `match': undefined method `each' for nil:NilClass (NoMethodError)
My code is as follows:
lib/daemons/mailman_server.rb
require 'mailman'
# Config Mailman
Mailman.config.ignore_stdin = false
Mailman.config.graceful_death = true
Mailman.config.poll_interval = 15
Mailman.config.logger = Logger.new File.expand_path("../../../log/mailman.log", __FILE__)
Mailman.config.pop3 = {
:username => 'alias#mygoogleapp.com',
:password => 'password',
:server => 'pop.gmail.com',
:port => 995,
:ssl => true
}
# Run the mailman
Mailman::Application.run do
from('%email%').to('alias+q%id%#mygoogleapp.com') do |email, id|
begin
# Get message without headers to pass to add_answer_from_email
if message.multipart?
reply = message.text_part.body.decoded
else
reply = message.body.decoded
end
# Call upon the question to add answer to his set
Question.find(id).add_answer_from_email(email, reply)
rescue Exception => e
Mailman.logger.error "Exception occured while receiving message:\n#{message}"
Mailman.logger.error [e, *e.backtrace].join("\n")
end
end
end
and my script/daemon file is:
#!/usr/bin/env ruby
require 'rubygems'
require "bundler/setup"
require 'daemons'
ENV["APP_ROOT"] ||= File.expand_path("#{File.dirname(__FILE__)}/..")
script = "#{ENV["APP_ROOT"]}/lib/daemons/#{ARGV[1]}"
Daemons.run(script, dir_mode: :normal, dir: "#{ENV["APP_ROOT"]}/tmp/pids")
Any insight as to why it fails as a daemon?

Ruby namespacing issues

I'm attempting to build a gem for interacting w/ the Yahoo Placemaker API but I'm running into an issue. When I attempt to run the following code I get:
NameError: uninitialized constant Yahoo::Placemaker::Net
from /Users/Kyle/.rvm/gems/ruby-1.9.2-p290/gems/yahoo-placemaker-0.0.1/lib/yahoo-placemaker.rb:17:in `extract'
from (irb):4
from /Users/Kyle/.rvm/rubies/ruby-1.9.2-p290/bin/irb:16:in `<main>'
yahoo-placemaker.rb
require "yahoo-placemaker/version"
require 'json'
require 'ostruct'
require 'net/http'
module Yahoo
module Placemaker
def self.extract (text = '')
host = 'wherein.yahooapis.com'
payload = {
'documentContent' => text,
'appid' => APP_ID,
'outputType' => 'json',
'documentType' => 'text/plain'
}
req = Net::HTTP::Post.new('/v1/document')
req.body = to_url_params(payload)
response = Net::HTTP.new(host).start do |http|
http.request(req)
end
json = JSON.parse(response.body)
Yahoo::Placemaker::Result.new(json)
end
end
end
I have yet to figure out how exactly constant name resolution works in Ruby (I think the rules are a bit messy here), but from my experience it could well be that Net is looked up in the current namespace instead of the global one. Try using the fully qualified name:
::Net::HTTP::Post.new
A similar problem could occur in this line:
Yahoo::Placemaker::Result
You should replace it with either ::Yahoo::Placemaker::Result or better Result (as it lives in the current namespace).
Try requiring net/http before. Ruby is falling back to find it in the module if it isn't defined.
require 'net/http'

Ruby Net:LDAP- NoMethodError for attributes that don't exist

I'm doing a simple Net:LDAP search and when I'm outputting an entry's attribute that may not exist for every entry, I get an error "NoMethodError: undefined method 'some_attribute'"
Here is the code:
require 'rubygems'
require 'net/ldap'
ldap = Net::LDAP.new
ldap.host = 'ldap.example.com'
ldap.port = 389
if ldap.bind
filter = Net::LDAP::Filter.eq( "sn", "Smith" )
treebase = "ou=people,o=company"
ldap.search( :base => treebase, :filter => filter, :return_result => false) do |entry|
puts #{entry.some_attribute}
end
end
else
puts "bind unsuccessful"
end
I tried also doing:
if entry.respond_to?(some_attribute)
puts "#{entry.some_attribute}"
end
That didn't work, it returns as false for every entry (when some entries have the attribute).
Ruby is expecting a symbol in the respond_to? method call.
ruby-1.8.7-p299 > class Foo
ruby-1.8.7-p299 ?> attr_accessor :some_attr
ruby-1.8.7-p299 ?> end
=> nil
ruby-1.8.7-p299 > Foo.new.respond_to?(some_attr)
NameError: undefined local variable or method `some_attr' for #<Object:0xb77ce950>
from (irb):4
ruby-1.8.7-p299 > Foo.new.respond_to?(:some_attr)
=> true

Resources