Ruby NoMethodError (undefined method ''...' for '....:Class' - ruby

require_relative 'json_lookup'
require_relative 'csv_lookup'
require_relative 'error'
BASE_RATE = 'EUR'
class CurrencyExchange
def initialize(file:, date:, from:, to:)
#file = file
#date = date
#from = from
#to = to
end
def rate
lookup = find_lookup
lookup.to_currency / lookup.from_currency
end
private
def find_lookup
case File.extname(#file)
when ".json"
JsonLookup.new(#file, #date, #from, #to)
when ".csv"
CsvLookup.new(#file, #date, #from, #to)
else raise FileError
end
end
end
I keep on getting this error for when i run the CurrencyExchange.rate in irb so I am guessing something is going wrong with the rate method but can't figure it out as to why. But I may be missing something completely obvious... As I am a complete beginner at Ruby, would appreciate any help :)
The traceback is as follows..
irb(main):003:0> CurrencyExchange.rate(Date.new(2018, 11, 22), "USD", "GBP") Traceback (most recent call last):
5: from C:/Ruby26-x64/bin/irb.cmd:31:in `<main>'
4: from C:/Ruby26-x64/bin/irb.cmd:31:in `load'
3: from C:/Ruby26-x64/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
2: from (irb):3
1: from (irb):3:in `rescue in irb_binding'
NoMethodError (undefined method `rate' for CurrencyExchange:Class)

rate is an instance method in your example but CurrencyExchange.rate tries to call a class method.
To solve this, initialize an instance first and call then rate on that instance. Furthermore rate doesn't accept arguments, you need to pass the variables to the initializing method.
currency_exchange = CurrencyExchange.new(
file: file, date: Date.new(2018, 11, 22), from: "USD", to: "GBP"
)
currency_exchange.rate
Note take the initializer expects 4 named arguments. You will need to pass a file to the new method too.

Related

Wrong number arguments error when using unpacked keyword args along with send

I noticed that attempting to use the send method while passing in unpacked keyword args as a variable led to some unexpected behavior.
First the setup:
class SomeClass
def some_method
true
end
end
kwargs = {}
c = SomeClass.new
c.some_method
=> true
c.some_method(**kwargs)
=> true
c.send(:some_method, **{})
=> true
All of the above works as expected. However, if I attempt to use send in conjunction with passing key word args via a variable (as oppose to a literal), I suddenly get a 'wrong number of arguments' error
c.send(:some_method, **kwargs)
Traceback (most recent call last):
5: from /Users/rs/.rvm/rubies/ruby-2.6.7/bin/irb:23:in `<main>'
4: from /Users/rs/.rvm/rubies/ruby-2.6.7/bin/irb:23:in `load'
3: from /Users/rs/.rvm/rubies/ruby-2.6.7/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>'
2: from (irb):9
1: from (irb):2:in `some_method'
ArgumentError (wrong number of arguments (given 1, expected 0))
Is this intended behavior?

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 access element in array via command line in ruby?

Given a simple code in file test.rb:
def todo_list(todo_selector)
library = ["Get a cat", "Get a dog", "Build a fighting ring"]
puts "Your current step in todo-list is:\n#{library[todo_selector]}"
end
ARGV.each { |todo| todo_list(todo_selector) }
How am I able to call this method with an index via command line?
Normally I would use test.rb 1, but I am getting this error:
Traceback (most recent call last):
2: from test.rb:17:in `<main>'
1: from test.rb:17:in `each'
test.rb:17:in `block in <main>': undefined local variable or method `todo_selector' for main:Object (NameError)
Did you mean? todo_list
What am I doing wrong?
Try this way for one element, take care to convert String into Integer in order to access the Array by index.
selector = ARGV[0].to_i
todo_list(selector)
For an array of arguments: ARGV.each{ |i| todo_list(i.to_i) }

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.

Resources