Ruby error with CSV and << - ruby

Well, I think the code speaks out for itself :)
# book_in_stock.rb
class BookinStock
attr_reader :isbn, :price
def initialize(isbn, price)
#isbn = isbn
#price = Float(price)
end
end
# csv_reader.rb
require 'csv'
class CsvReader
def initialize
#book_in_stock = []
end
def read_in_csv_data(csv_file_name)
CSV.foreach(csv_file_name, headers: true) do |row|
#books_in_stock << BookinStock.new(row["ISBN"], row["Amount"])
end
end
# later we'll see how to use inject to sum a collection
def total_value_in_stock
sum = 0.0
#books_in_stock.each { |book| sum += book.price }
sum
end
def number_of_each_isbn
# ...
end
end
# stock_stats.rb
reader = CsvReader.new()
ARGV.each do |csv_file_name|
STDERR.puts "[+] Processing #{csv_file_name}"
reader.read_in_csv_data(csv_file_name)
end
puts "[+] Total value = #{reader.total_value_in_stock}"
When running I get:
# +search/pickaxe/csv $ ruby1.9.1 test.rb data.csv
# [+] Processing data.csv
# test.rb:23:in `block in read_in_csv_data': undefined method `<<' for nil:NilCla
# ss (NoMethodError)
# from /usr/lib/ruby/1.9.1/csv.rb:1760:in `each'
# from /usr/lib/ruby/1.9.1/csv.rb:1196:in `block in foreach'
# from /usr/lib/ruby/1.9.1/csv.rb:1334:in `open'
# from /usr/lib/ruby/1.9.1/csv.rb:1195:in `foreach'
# from test.rb:22:in `read_in_csv_data'
# from test.rb:46:in `block in <main>'
# from test.rb:44:in `each'
# from test.rb:44:in `<main>'
What've I done wrong?

'#books_in_stock' != '#book_in_stock' # !
(typo)

You have a typo in the initialize function (#book_in_store insteadn of #books_in_store). Is that it?
By the way, the sum of the prices can be done with inject in one line
#books_in_stock.inject(0) { |sum, book| sum + book.price }

If you run the command with ruby -w, it'll turn on warnings, and the interpreter will explain what went wrong:
$ ruby -w book_in_stock.rb
book_in_stock.rb:28: warning: instance variable #books_in_stock not initialized
book_in_stock.rb:28:in `total_value_in_stock': undefined method `each' for nil:NilClass (NoMethodError)
from book_in_stock.rb:47:in `<main>'

Related

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.

Ruby logger is nil

When I try to use Ruby's logger, it comes up as nil. Is an instance variable the correct way to do this?
require 'logger'
class LogStuff
# Log to STDOUT and `tee` it to a file
#logger = Logger.new("| tee output.log")
#logger.level = :debug
def run
(1..10).each do |n|
#logger.debug('l1') { #logger.debug "proceessing #{n}" }
end
['a', 'b', 'c', 'd', 'e'].each do |letter|
#logger.debug('letters') { #logger.debug "proceessing #{letter}" }
end
end
end
if __FILE__ == $0
lggr = LogStuff.new
lggr.run
end
Error message:
$ ruby script.rb
script.rb:11:in `block in run': undefined method `debug' for nil:NilClass (NoMethodError)
from script.rb:10:in `each'
from script.rb:10:in `run'
from script.rb:23:in `<main>'
Try this one
def initialize
# Log to STDOUT and `tee` it to a file
#logger = Logger.new("| tee output.log")
#logger.level = :debug
end
Obviously into the LogStuff class. Basically, otherwise your #logger variable is defined in another scope.

Getting an error when using "require" in ruby

I just started Ruby. This is what I tried:
require'F:\RubymineProjects\practice122013\Coordinatev2'
class XYZCoordinate < Coordinate
attr_accessor :z
##newtotal=0
def initialize(x,y,z)
super(x,y)
#z=z
##newtotal+=1
end
def to_s
return "(##x, ##y, ##z)"
end
def XYZCoordinate.total
return "Number of 3D-coordinates are: ###newtotal"
end
end
p1=XYZCoordinate.new(0,0,0)
puts p1.to_s
p2=XYZCoordinate.new(1,5,5)
puts p2.to_s
puts XYZCoordinate.total
and this is the error I get:
C:\Ruby193\bin\ruby.exe -e $stdout.sync=true;$stderr.sync=true;load($0=ARGV.shift) F:/RubymineProjects/practice122013/XYZCoordinate.rb
F:/RubymineProjects/practice122013/XYZCoordinate.rb:3:in `<top (required)>': uninitialized constant Coordinate (NameError)
(0, 0)
from -e:1:in `load'
2
from -e:1:in `<main>'
3
Can anyone help me please.
This is what I did to correct the problem.
require"F:\\RubymineProjects\\practice122013\\Coordinatev2"
require"F:\\RubymineProjects\\practice122013\\Coordinate"
I had to specify where those 2 files were.

NoMethodError: undefined method `split' for #<Proc: ...> with Faraday

I want to send a get request with a JSON body (for search) using Faraday, but am getting the above error. I thought that self inside the Proc was messing things up, but that had nothing to do with it. I'm following the documentation on the [faraday github page][1] but have gotten stuck on this.
def perform_query
response = self.database.connection.get do |request|
request.url self.path
request.headers['Content-Type'] = 'application/json'
request.body(self.to_json)
end
end
def terms_to_json
terms_array = self.terms.keys.inject([]) do |terms_array, field|
value = self.terms[field]
terms_array.tap do |ary|
if value
ary << "\"#{field}\": \"#{value}\""
end
end
end
"{ #{terms_array.join ','} }"
end
def to_json
"{ \"queryb\" : #{self.terms_to_json} }"
end
Here is the stack trace, with the error coming somewhere in the get Proc in #perform_query :
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/request.rb:60:in `url'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/connection.rb:219:in `block in run_request'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/connection.rb:237:in `block in build_request'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/request.rb:35:in `block in create'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/request.rb:34:in `tap'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/request.rb:34:in `create'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/connection.rb:233:in `build_request'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/connection.rb:218:in `run_request'
from /Users/chrismaddox/.rvm/gems/ruby-1.9.3-p125/gems/faraday-0.8.1/lib/faraday/connection.rb:87:in `get'
from /Users/chrismaddox/Dropbox/LivingSocial/Hungry Academy/Projects/hackchat/search_ruby/elastic.rb:83:in `method_missing'
from /Users/chrismaddox/Dropbox/LivingSocial/Hungry Academy/Projects/hackchat/search_ruby/elastic.rb:112:in `perform_query'
from /Users/chrismaddox/Dropbox/LivingSocial/Hungry Academy/Projects/hackchat/search_ruby/elastic.rb:61:in `send_query'
UPDATE:
the path method returns a string of the path to the search for a given index. Eg /wombats/animals/_search
Elastic::Database#path calls Elastic::Index#index_path:
module Elastic
ELASTIC_URL = "http://localhost:9200"
class Index
attr_reader :index_name, :type_name, :last
def initialize(type)
#index_name = "#{type}-index"
#type_name = type
#last = 0
add_to_elastic
end
def add_to_elastic
index_url = URI.parse "#{ELASTIC_URL}#{index_path}/"
Connection.new(index_url).put()
end
def index_path
"/#{self.index_name}"
end
def search_path
"#{type_path}/_search/"
end
def type_path
"#{self.index_path}/#{type_name}/"
end
end
end
A call to search_path = "#{type_path}/_search/"
A call to type_path = "#{self.index_path}/#{type_name}/"
A call to index_path = "/#{self.index_name}"
So if index name is wombat and type name is animal, search_path evaluates to /wombat/animal//_search
It turns out that this wasn't the problem showing the error, but was caused because Faraday's methods are inconsistent. Faraday::Request#url and Faraday::Request#headers are themselves setter methods, whereas Faraday::Request#body= is the setter method for body.

How do I debug an undefined method for nil class error?

I'm trying to create a classifier using the cardmagic classifier gem. This is my code:
require 'classifier'
classifications = '1007.09', '1006.03'
traindata = Hash["1007.09" => "ADAPTER- SCREENING FOR VALVES VBS", "1006.03" => "ACTUATOR- LINEAR"]
b = Classifier::Bayes.new classifications
traindata.each do |key, value|
b.train(key, value)
end
But when I run this I get the following error:
Notice: for 10x faster LSI support, please install http://rb-gsl.rubyforge.org/
c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:27:in `block in train': undefined method `[]' for nil:NilClass (NoMethodError)
from c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:26:in `each'
from c:/Ruby192/lib/ruby/gems/1.9.1/gems/classifier-1.3.3/lib/classifier/bayes.rb:26:in `train'
from C:/_Chris/Code/classifier/smdclasser.rb:13:in `block in <main>'
from C:/_Chris/Code/classifier/smdclasser.rb:11:in `each'
from C:/_Chris/Code/classifier/smdclasser.rb:11:in `<main>'
This is the source from the gem code:
# Provides a general training method for all categories specified in Bayes#new
# For example:
# b = Classifier::Bayes.new 'This', 'That', 'the_other'
# b.train :this, "This text"
# b.train "that", "That text"
# b.train "The other", "The other text"
def train(category, text)
category = category.prepare_category_name
text.word_hash.each do |word, count|
#categories[category][word] ||= 0
#categories[category][word] += count
#total_words += count
end
end
I am lost where to go to troubleshoot this error, what is the next step I should take?
Classifier::Bayes.new expects an exploded array of values, rather than a single parameter. For example, notice that the sample code uses:
b = Classifier::Bayes.new 'This', 'That', 'the_other'
rather than:
b = Classifier::Bayes.new ['This', 'That', 'the_other']
Pass in the splat version of your classifications array and it should work:
b = Classifier::Bayes.new *classifications

Resources