What is causing this error? It doesn't matter whether or not self. is specified.
class Testmethod < ApplicationController
def add_a_file(files, next1, f)
true
end
next1 = 0
files = Array.new
Dir.chdir("db/testdir")
Dir["*.xls*"].each do |f|
self.add_a_file(files, next1, f) # Error thrown here.
next1 += 1
end
Dir["*.csv*"].each do |f|
self.add_a_file(files, next1, f)
next1 += 1
end
sfiles = files.sort { |first, second| first[1] <=> second[1] } # ASC by mdate
puts sfiles.inspect
end
You try to call add_a_file method on Testmethod class (Testmethod.add_a_file) instead of on its instance. Either you should create this class' instance with:
instance = self.new
or make add_a_file a singleton method (class method):
def self.add_a_file(files, next1, f)
true
end
Related
I can't understand how can I solve this error since the method do really exists, I have tested it with the 'Hi' method.
irb(main):001:0> require 'yaml'
=> true
irb(main):002:0> require 'tm'
=> true
irb(main):003:0> Tm.hi
Hey Tm here for duty!
=> nil
irb(main):004:0> hashfile = YAML.load_file('fr.yaml')
=> {"fr"=>{"colors"=>{"yellow"=>"Jaune", "white"=>"Blanc"}, "hello"=>"Bonjour"}}
irb(main):005:0> t = load_translation(hashfile)
Traceback (most recent call last):
2: from /Users/abderrahmane/.rbenv/versions/2.5.1/bin/irb:11:in `<main>'
1: from (irb):5 NoMethodError (undefined method `load_translation' for main:Object)
With my class:
class Tm
def self.hi
puts "Hey Tm here for duty!"
end
def auxload(hash, lang, concat='')
ans = {}
hash.each do |key, val|
if val.class == Hash
aux = auxload(val, lang, concat+key+'.')
aux.each do |k, v|
ans[k]=v
end
else
ans[concat+key]={lang => val}
end
end
return ans
end
# load the translation from the yaml files
def load_translation(hash)
key,value = hash.first
return auxload(value,key)
end
end
To call the method on your class you first need to create an instance of the class and then call the method on that instance. e.g.
tm = Tm.new
t = tm.load_translation(hashfile)
You are not calling the load_translation method from the object of class Tm.
You need an instance of the class:
tm = Tm.new
tm.load_translation(hashfile)
It is needed to call the load_translation method at first by creating an instance of the class ~
tm = Tm.new
tm.load_translation(hashfile)
When I run code below it raise error:
implicit argument passing of super from method defined by define_method() is not supported. Specify all arguments explicitly. (RuntimeError).
I am not sure what is the problem.
class Result
def total(*scores)
percentage_calculation(*scores)
end
private
def percentage_calculation(*scores)
puts "Calculation for #{scores.inspect}"
scores.inject {|sum, n| sum + n } * (100.0/80.0)
end
end
def mem_result(obj, method)
anon = class << obj; self; end
anon.class_eval do
mem ||= {}
define_method(method) do |*args|
if mem.has_key?(args)
mem[args]
else
mem[args] = super
end
end
end
end
r = Result.new
mem_result(r, :total)
puts r.total(5,10,10,10,10,10,10,10)
puts r.total(5,10,10,10,10,10,10,10)
puts r.total(10,10,10,10,10,10,10,10)
puts r.total(10,10,10,10,10,10,10,10)
The error message is quite descriptive. You need to explicitly pass arguments to super when you call it inside of define_method block:
mem[args] = super(*args)
I am a complete beginner to Ruby. I am working on Lesson 45 of Learn Ruby the Hard Way currently and am creating a game similar to Zork and Adventure.
I have created a structure where I am creating 'scenes' in different files and requiring all the scenes in one file where I have an engine/map that ensures if the current scene does not equal 'finished' that it runs 'X' scene's 'enter' method.
However I have two issues:
1) I keep getting a error saying 'Warning class variable access from top level'
2) Even though the script is running I get
ex45.rb:30:in `play': undefined method `enter' for nil:NilClass (NoMethodError) from ex45.rb:59:in
The following is all of my code from each file. My apologies if it's a long read, but I would love to know why I am getting these two errors and what I can do to fix them.
Ex45.rb:
require "./scene_one.rb"
require "./scene_two.rb"
require "./scene_three.rb"
##action = SceneOne.new
##action_two = SceneTwo.new
##action_three = SceneThree.new
class Engine
def initialize(scene_map)
#scene_map = scene_map
end
def play()
current_scene = #scene_map.opening_scene()
last_scene = #scene_map.next_scene('finished')
while current_scene != last_scene
next_scene_name = current_scene.enter()
current_scene = #scene_map.next_scene(next_scene_name)
end
current_scene.enter()
end
end
class Map
##scenes = {
'scene_one' => ##action,
'scene_two' => ##action_two,
'scene_three' => ##action_three
}
def initialize(start_scene)
#start_scene = start_scene
end
def next_scene(scene_name)
val = ##scenes[scene_name]
return val
end
def opening_scene()
return next_scene(#start_scene)
end
end
a_map = Map.new('scene_one')
a_game = Engine.new(a_map)
a_game.play()
scene_one.rb:
class SceneOne
def enter
puts "What is 1 + 2?"
print "> "
answer = $stdin.gets.chomp
if answer == "3"
puts "Good job"
return 'scene_two'
else
puts "try again"
test
end
end
end
scene_two.rb
class SceneTwo
def enter
puts "1 + 3?"
print "> "
action = $stdin.gets.chomp
if action == "4"
return 'scene_three'
else
puts "CANNOT COMPUTE"
end
end
end
scene_three.rb
class SceneThree
def enter
puts "This is scene three"
end
end
Thanks in advance!
Answer to your first question:
You need to move the class variable definitions inside your Map class to get rid of these warnings:
Ex45.rb:5: warning: class variable access from toplevel
Ex45.rb:6: warning: class variable access from toplevel
Ex45.rb:7: warning: class variable access from toplevel
So, your Map class would look like this:
class Map
##action = SceneOne.new
##action_two = SceneTwo.new
##action_three = SceneThree.new
##scenes = {
'scene_one' => ##action,
'scene_two' => ##action_two,
'scene_three' => ##action_three
}
def initialize(start_scene)
#start_scene = start_scene
end
def next_scene(scene_name)
val = ##scenes[scene_name]
return val
end
def opening_scene()
return next_scene(#start_scene)
end
end
To answer your 2nd question:
You are getting undefined method 'enter' for nil:NilClass (NoMethodError) because your current_scene becomes nil at some point and then you try to call: current_scene.enter() i.e. nil.enter and it fails with that error message.
To solve this problem, you have to make sure you always have some value in your current_scene i.e. make sure it's not nil.
I think, you can just remove current_scene.enter() line from the end of your play method in the Engine class. So, your Engine class will look like this:
class Engine
def initialize(scene_map)
#scene_map = scene_map
end
def play()
current_scene = #scene_map.opening_scene()
last_scene = #scene_map.next_scene('finished')
while current_scene != last_scene
next_scene_name = current_scene.enter()
current_scene = #scene_map.next_scene(next_scene_name)
end
# current_scene.enter()
end
end
And, you won't get that error anymore.
Just so you know:
##y = 20
p Object.class_variables
--output:--
1.rb:1: warning: class variable access from toplevel
[:##y]
And:
class Object
def self.y
##y
end
end
puts Object.y
--output:--
20
But:
class Dog
##y = "hello"
def self.y
##y
end
end
puts Dog.y #=>hello
puts Object.y #=>What do you think?
The output of the last line is the reason that class variables are not used in ruby. Instead of class variables, you should use what are known as class instance variables:
class Object
#y = 10 #class instance variable
def self.y
#y
end
end
puts Object.y
class Dog
#y = "hello"
def self.y
#y
end
end
puts Dog.y #=> hello
puts Object.y #=> 10
A class instance variable is just an #variable that is inside the class, but outside any def. And instead of there being one ##variable that is shared by all the subclasses, each subclass will have its own #variable.
I created multiple classes with one test method to test wither the ruby objects get serialized correctly.
The error returned:
undefined method `[]=' for nil:NilClass
from /Users/horse/workspace/queryapi/app/models/query_model.rb:193:in `serialize'
I run the below test_query method through the rails console by initializing QueryModelTester and then invoking test_query() method on that object.
My code:
class QueryModelTester
def test_query
must = Must.new
range_criteria = RangeCriteria.new
range_criteria.gte = 20140712
range_criteria.lte = 1405134711
range = RangeBuilder.new
range.search_field = "created_time"
range.range_criteria = range_criteria
must.range = range
bool = Bool.new
bool.must = must
main_query = bool.serialize
puts main_query
end
end
Here are the model classes the above class is testing:
class RangeCriteria
#query_hash = Hash.new
attr_accessor :gte, :lte
def serialize
if(#gte.present?)
#query_hash[:gte] = #gte
end
if(#lte.present?)
#query_hash[:lte] = #lte
end
if(#gte.present? || #lte.present?)
return #query_hash
end
end
end
class RangeBuilder
#query_hash = Hash.new
attr_accessor :search_field, :range_criteria
def serialize
if(#search_field.present?)
#query_hash[#search_field] = #range_criteria.serialize
return #query_hash[:range] = #query_hash
end
end
end
class Bool
#query_hash = {}
attr_accessor :must
def serialize
if( #must.present? )
#query_hash[:must] = #must.serialize
return #query_hash[:bool] = #query_hash
end
end
end
The problem is when you initialize your #query_hash. In all your classes they are initialized in wrong scope. To fix it, you should move #query_hash = Hash.new to initialize method, like:
class RangeCriteria
def initialize
#query_hash = Hash.new
end
# ...
end
class RangeBuilder
def initialize
#query_hash = Hash.new
end
# ...
end
class Bool
def initialize
#query_hash = Hash.new
end
# ...
end
Hope that helps.
Good luck!
Why does the following code result in the error 'undefined local variable or method `foo_client' for Foo::People:Class'
class Foo::People
class << self
def get_account_balance(account_num)
foo_client.request :get_account_balance, :body => {"AccountNum" => account_num}
end
end
def foo_client
##client ||= Savon::Client.new do|wsdl, http|
wsdl.document = PEOPLE_SERVICE_ENDPOINT[:uri] + "?WSDL"
wsdl.endpoint = PEOPLE_SERVICE_ENDPOINT[:uri]
end
end
end
def get_account_balance is inside the class << self block, so it's a class method. def foo_client is not, so it's an instance method. So you can't call foo_client from get_account_balance because you're not calling it on an instance of People.