Unexpected Method Call - ruby

I'm using mongomapper to store pages in a db, and I index them first. In the index method, I loop through each word, and check to see if it is already in the words hashmap. If not, I add an empty array to the hash, then push its location to the array.
def index_words
#words = self.body.split(" ")
#words.each_with_index do |word,i|
if self.words[word.stem].nil?
self.words[word.stem] = []
end
puts "Called from #{caller[0]}"
self.words[word.stem].push(i)
end
end
When I run this, I get an undefined method error, saying that self.words[word.stem] is nil. Furthermore, this method is actually being called from the loop, when it's only called once in the constructor:
def initialize(*args)
super
index_words
end
The error message is:
p = Page.new({author: 'Michael',url: 'michaelfine.me',title: 'Michael Fine',body: 'Body Text'})
called fromPage.rb:19:in `each'
NoMethodError: undefined method `push' for nil:NilClass
from Page.rb:24:in `block in index_words'
from Page.rb:19:in `each'
from Page.rb:19:in `each_with_index'
from Page.rb:19:in `index_words'
from Page.rb:14:in `initialize'
from (irb):103:in `new'
from (irb):103
from /Users/Michael/.rvm/rubies/ruby-1.9.3-p286/bin/irb:16:in `<main>'

Related

I am getting an error on line 13. It says that the `<<` method is undefined. how do I fix this? I am using Ruby

This is the code:
def self.scrape_shoe
#doc.css("div.product-card__body").each do |nike|
name = nike.css("div.product-card__title").text.strip
price = nike.css("div.product-card__price").text.strip
shoes = self.new
#all << shoes #having error here
end
end
This is the error:
Traceback (most recent call last):
7: from bin/new_nikes:7:in `<main>'
6: from /home/merkonical/new_nikes/lib/new_nikes/cli.rb:17:in `call'
5: from /home/merkonical/new_nikes/lib/new_nikes/cli.rb:11:in `list_price'
4: from /home/merkonical/new_nikes/lib/new_nikes/scraper.rb:9:in `scrape_shoe'
3: from /home/merkonical/.rvm/gems/ruby-2.6.1/gems/nokogiri-1.10.4/lib/nokogiri/xml/node_set.rb:237:in `each'
2: from /home/merkonical/.rvm/gems/ruby-2.6.1/gems/nokogiri-1.10.4/lib/nokogiri/xml/node_set.rb:237:in `upto'
1: from /home/merkonical/.rvm/gems/ruby-2.6.1/gems/nokogiri-1.10.4/lib/nokogiri/xml/node_set.rb:238:in `block in each'
/home/merkonical/new_nikes/lib/new_nikes/scraper.rb:13:in `block in scrape_shoe': undefined method `<<' for nil:NilClass (NoMethodError)
What are possible fixes I can do for this?
I am working on Ruby
What are possible fixes I can do for this?
#all is nil. nil doesn't have a method named <<. Make sure #all is not nil.
Getting error because you are pushing shoes object into undefined instance variable.
Define #all in action.
def self.scrape_shoe
#doc.css("div.product-card__body").each do |nike|
#all = []
name = nike.css("div.product-card__title").text.strip
price = nike.css("div.product-card__price").text.strip
shoes = self.new
#all << shoes #having error here
end
end
Hope this helps you

How to fix a NoMethodError :undefined method `<<' for nil:NilClass

I have 3 error messages which I believe all relate to one thing - me calling a method on an object that has not been defined properly.
I've checked over for typos, white spacing, syntax, naming. I'm following the same process as other methods in this program which all tested OK.
I've narrowed the loop down and believe the issue is here:
def add(param)
#param << param
Heres the code in full context:
class Todo
def initialize(param)
#param = param
end
def text
return #param
end
end
class TodoList
def initialize
#item_list = []
end
def add(param)
#param << param
end
def print
#item_list.each do |param|
puts "* #{param.text}" #=> .text?
end
end
end
Error Messages:
Here are the error messages I'm trying to resolve. As I mentioned earlier they all look to be pointing to a method I've not defined properly but I've not yet been able to work out why that may be.
1) Q1. Todo list TodoList adding todos adds a todo without raising an error
Failure/Error: expect { todo_list.add(todo) }.to_not raise_error
expected no Exception, got #<NoMethodError: undefined method `<<' for nil:NilClass> with backtrace:
# ./questions/question_1.rb:43:in `add'
# ./spec/question_1_spec.rb:31:in `block (5 levels) in <top (required)>'
# ./spec/question_1_spec.rb:31:in `block (4 levels) in <top (required)>'
# ./spec/question_1_spec.rb:31:in `block (4 levels) in <top (required)>'
2) Q1. Todo list TodoList printing todos one todo prints a single todo with a bullet point
Failure/Error: todo_list.add(todo)
NoMethodError:
undefined method `<<' for nil:NilClass
# ./questions/question_1.rb:43:in `add'
# ./spec/question_1_spec.rb:41:in `block (5 levels) in <top (required)>'
3) Q1. Todo list TodoList printing todos many todos prints the todos, separated by newlines
Failure/Error: todo_list.add(todo_1)
NoMethodError:
undefined method `<<' for nil:NilClass
# ./questions/question_1.rb:43:in `add'
# ./spec/question_1_spec.rb:59:in `block (5 levels) in <top (required)>'
Thanks!
ruby do not know what #param is in your TodoList class, you have to initialize it in your constructor like this #param = [] that fix your issue
By default instance variables are initialized to nil, hence the error. So in your TodoList class, you need to initialize #param to an object that can respond to <<, which in your own case, is an array []
class TodoList
def initialize
#param = []
end
end

undefined method 'execute' for nil:NilClass

I am making a tool in ruby which can interact with databases.
I am using amalgalite as an adapter for sqlite3.
Code:
require 'amalgalite'
# this is class RQuery
class RQuery
def db_open(db_name)
#db = Amalgalite::Database.new "#{db_name}.db"
make_class
end
def exec_this(query)
#db.execute(query)
end
def make_class
tables_list = exec_this("select name from sqlite_master where type='table'")
tables_list.each do |table|
#class_created = Object.const_set(table[0].capitalize, Class.new)
#class_created.class_eval do
define_singleton_method :first do
RQuery.new.exec_this("select * from #{table[0]} order by #{table[0]}.id ASC limit 1")
end
end
end
end
def eval_this(input)
instance_eval(input)
end
def code
print '>>'
input = gets
exit if input =~ /^q$/
puts eval_this(input)
code
end
end
Now when I am running the code everything works fine until I call table_name.first
It gives output
vbhv#fsociety ~/git/R-Query/bin $ ruby main.rb
Enter the code or q for quit
>>db_open('vbhv')
users
persons
people
programmers
>>Users.first
/home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval': undefined method `execute' for nil:NilClass (NoMethodError)
Did you mean? exec
from /home/vbhv/git/R-Query/lib/r-query.rb:29:in `block (3 levels) in make_class'
from (eval):1:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `instance_eval'
from /home/vbhv/git/R-Query/lib/r-query.rb:36:in `eval_this'
from /home/vbhv/git/R-Query/lib/r-query.rb:43:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from /home/vbhv/git/R-Query/lib/r-query.rb:44:in `code'
from main.rb:4:in `<main>'
Now the 'execute' function it is talking about is inside amalgalite. What am I doing wrong here?? Thanks in Advance!
The problem in this was that the new class formed dynamically doesn't know about the connection variable '#db'. Hence the code solves the problem.
#class_created.instance_variable_set(:#database, #db)
A big thanks to Jagdeep Singh.

Celluloid 0.17.3 giving unexpected "undefined method" error

I have started using Celluloid gem this morning for that first time. I am following this Railscasts tutorial and trying to figure things out.
I have a class called "SomeClass" and it has only one method. Here is the code:
require 'celluloid'
class SomeClass
include Celluloid
def initialize(name)
#name = name
end
def assholify()
puts "#{#name} has become an ASSHOLE."
end
end
When I create new instances of the class and call its method (with a bang i.e. "assholify!"), I am getting the undefined method 'assholify!', error. But Celluloid is supposed to trigger the method asynchronously when it is called with a bang. So here is how I am calling the method:
names = ['John', 'Tom', 'Harry']
names.each do |name|
n = SomeClass.new name
n.assholify!
end
Here is the full backtrace of the error:
I, [2016-09-09T11:28:02.488618 #3682] INFO -- : Celluloid 0.17.3 is running in BACKPORTED mode. [ http://git.io/vJf3J ]
/home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/calls.rb:42:in `rescue in check': undefined method `assholify!' for #<SomeClass:0x10897dc> (NoMethodError)
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/calls.rb:39:in `check'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/calls.rb:26:in `dispatch'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:16:in `dispatch'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/cell.rb:50:in `block in dispatch'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/cell.rb:76:in `block in task'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/actor.rb:339:in `block in task'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/task.rb:44:in `block in initialize'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/task/fibered.rb:14:in `block in create'
from (celluloid):0:in `remote procedure call'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/call/sync.rb:45:in `value'
from /home/railsdev/.rvm/gems/ruby-2.3.1/gems/celluloid-0.17.3/lib/celluloid/proxy/sync.rb:22:in `method_missing'
from some_class.rb:18:in `block in <main>'
from some_class.rb:16:in `each'
from some_class.rb:16:in `<main>'
Why am I getting this error? Is it the right way to call the function? Also how do I get rid of Celluloid 0.17.3 is running in BACKPORTED mode. warning?
The undefined method error occurred because actor methods are not called with a bang in the recent versions of celluloid gem. Instead you call the method like this: n.async.assholify. So here is what the code should look like:
names = ['John', 'Tom', 'Harry']
names.each do |name|
n = SomeClass.new name
n.async.assholify # Instead of "n.assholify!"
end
For "Celluloid 0.17.0 is running in BACKPORTED mode" warning, take a look at this wiki. Backported Mode is the default, for a limited time. If you use require 'celluloid/current' instead of require 'celluloid', you should not see this warning.

Confusion with IRB output in Ruby when object#initialize is overloaded

What I actually trying to see when no 'initialize' method is given to an class definition then the class as you said should call the "Object#initialize",which here I tried to customize and see if it has been called or not. With that approach I reached to a conclusion(although that's wrong), when I typed "ob = A .new" that yes I can overload the Object#initialize method.But all has been ended up with the below exception. Then I thought I did something wrong in my customization.So I tried to create the object creation within an exception block and when I typed "begin" and pressed "ENTER" - i got the same error.
>> class A
>> def Object.new initialize
>> p "hi"
>> rescue
>> end
>> end
=> nil
>> begin # <~~~ Here I have pressed on ENTER
"hi" #<~~~~ How was it print out?
/usr/lib/ruby/1.9.1/irb/ruby-token.rb:94:in `Token': undefined method `set_backtrace' for "hi":String (NoMethodError)
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:348:in `block in lex_init'
from /usr/lib/ruby/1.9.1/irb/slex.rb:236:in `call'
from /usr/lib/ruby/1.9.1/irb/slex.rb:236:in `match_io'
from /usr/lib/ruby/1.9.1/irb/slex.rb:221:in `match_io'
from /usr/lib/ruby/1.9.1/irb/slex.rb:75:in `match'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:286:in `token'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:262:in `lex'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:233:in `block (2 levels) in each_top_level_statement'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `loop'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:229:in `block in each_top_level_statement'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `catch'
from /usr/lib/ruby/1.9.1/irb/ruby-lex.rb:228:in `each_top_level_statement'
from /usr/lib/ruby/1.9.1/irb.rb:155:in `eval_input'
from /usr/lib/ruby/1.9.1/irb.rb:70:in `block in start'
from /usr/lib/ruby/1.9.1/irb.rb:69:in `catch'
from /usr/lib/ruby/1.9.1/irb.rb:69:in `start'
from /usr/bin/irb:12:in `<main>'
#ubuntu:~$
Now my questions are -
How has the "hi" been printed?
What is the cause of the error as printed above?
If such initialize definition is not allowed,then why has the error not come after I ended with the class definition?
EDIT
As per #casper I tried below:
>> def Object.new
>> p "hi"
>> end
=> nil
>> begin
/usr/lib/ruby/1.9.1/irb/ruby-token.rb:96: stack level too deep (SystemStackError)
But here no "hi" printed back.
So what made the "hi" to print back in the first case?
What exactly are you trying to do? You just redefined Object.new, so there is no surprise you make everything go haywire.
You can basically get the same effect by just:
>> def Object.new
>> end
>> [press enter]
KABOOM
The reason "hi" is printed is that someone just called Object.new, probably the irb REPL loop, and it expected an object, but instead it gets gobledygook.
You can also try this:
def Object.new *args
p args
end
And you will see funny stuff. However you won't be able to quit irb or do anything useful with it after that. Again: you just broke Object.
To make some sense of it you should read this:
In Ruby, what's the relationship between 'new' and 'initialize'? How to return nil while initializing?
And then you can try this:
class Object
class << self
alias :old_new :new
end
end
Now you can do:
def Object.new *args
p args
old_new *args
end
This won't break new because you are still calling the old version of it. However you will now be printing out stuff every time someone calls new.

Resources