Ruby error: undefined method `each' for nil:NilClass (NoMethodError) - ruby

I am ruby beginner. I am use proc class but I am getting error.
class Timeline
attr_accessor :tweets
def each(&block) # Block into the proc
tweets.each(&block) # proc back into the block
end
end
timeline = Timeline.new(tweets)
timeline.each do |tweet|
puts tweet
end
Getting error :-
`each': undefined method `each' for nil:NilClass (NoMethodError)
How to solve this error? Please tell us!

When you define attr_accessor :tweets, you just define 2 instance methods:
def tweets
#tweets
end
def tweets=(tweets)
#tweets = tweets
end
When you call tweets inside the each method, you just call method with this name, not a local variable, so you should set #tweets in the initialize method because right now your #tweets variable is not set:
class Timeline
attr_accessor :tweets # this is just a nice syntax for instance variable setter
# and getter
def initialize(tweets)
#tweets = tweets
end
def each(&block) # Block into the proc
tweets.each(&block) # proc back into the block
end
end

Related

undefined method `[]' for nil:NilClass (NoMethodError) in ruby

My class is
class LineAnalyzer
attr_reader :highest_wf_words,:highest_wf_count,:content,:line_number
def initialize(content ="",line_number)
#content = content
#line_number = line_number
end
def calculate_word_frequency
end
end
When I make object of class like this
l = LineAnalyzer.new("", 2)
l.calculate_word_frequency
It gives me this error.HOw to avoid this?

array push pop in ruby

This is my main code. I am using rspec
require_relative "rpn_calculator"
describe RPNCalculator do
let(:calculator) {RPNCalculator.new}
it "adds two numbers" do
calculator.push(1)
calculator.push(3)
calculator.plus
expect(calculator.value).to eq 4
end
And this is my code in rpn_calculator
class RPNCalculator
#arr=[]
#ans=0
def push(val)
#arr.push(val)
end
def plus
while #arr.size>=1 do
#ans=#ans+#arr.pop
end
end
def value
return #ans
end
end
And this is the error I am getting
RPNCalculator adds two numbers
Failure/Error: calculator.push(1)
NoMethodError:
undefined method push' for nil:NilClass
# ./rpn_calculator.rb:5:inpush'
# ./spec.rb:7:in `block (2 levels) in '
But I think Push is a method for arrays
Those variables needs to be in initialize method:
class RPNCalculator
def initialize
#arr=[]
#ans=0
end
def push(val)
#arr.push(val)
end
def plus
while #arr.size>=1 do
#ans=#ans+#arr.pop
end
end
def value
return #ans
end
end
Explanation: initialize is private by default and is called as obj.send(:initialize, *args, &block) in Class#new method's implementation. Have a look at this answer for more information.
So, when you define an initialize method in your class to override or overwrite its implementation according to yours. Ruby will invoke and run your defined version of initialize method instead. Since, initialize is an instance method, whatever variables(variables with #) you have defined, will also be shared/accessible in other instance methods, in this case: #arr, and #ans. In your case they are class variables and not instance variables, and that's why #arr is nil in push instance method and #arr in plus instance method.
It would be perfectly fine if you do not want to put those variables in initialize and instead write them in your own defined method, let's call it initialize_variables:
class RPNCalculator
def initialize_variables
#arr=[]
#ans=0
end
....
..
end
It's just that now you have to always call initialize_variables after initializing the class object. Which is an extra overhead in your code, and not considered as a good practice. Hence use initialize method instead.

instance_eval doesn't work as expected

I'm trying to build a tinny DSL using the approach that Russ Olsen exposes in his book, Eloquent Ruby. However it is not working for me. Let's consider the following code:
class SayHello
def initialize
#message = "Hello."
instance_eval(yield) if yield
end
def say_it
puts #message
end
end
SayHello.new { say_it }
The error I get is:
say_hello.rb:12:in `block in <main>': undefined local variable or method `say_it' for main:Object (NameError)
from say_hello.rb:4:in `initialize'
from say_hello.rb:12:in `new'
from say_hello.rb:12:in `<main>'
But... when you use instance_eval method, the value of self shouldn't be assigned to the object that calls the method?
Thanks in advance!
When the block runs, you want self to be equal to your SayHello instance instead of the main object.
I Googled for "ruby change self for a block" and found a good answer which makes me think you should change your code to:
class SayHello
def initialize(&p)
#message = "Hello."
instance_eval(&p) if block_given?
end
def say_it
puts #message
end
end
SayHello.new { say_it }

Accessing variable defined inside block

I have this snippet:
class MyClass
def self.callWithBlock (&block)
print block.blockVar
end
end
MyClass::callWithBlock do
blockVar = 'Hello'
end
which gives me an error:
in `callWithBlock': undefined method `blockVar' for #<Proc:0x000000017ed168#./block-test.rb:9> (NoMethodError)
from ./block-test.rb:9:in `<main>'
How to access this blockVar?
If you add binding at the end of the block, that would become the result of call-ing the block, and you can eval whatever local variables assigned in that block within the context of the binding.
class MyClass
def self.callWithBlock (&block)
print block.call.eval('blockVar')
end
end
MyClass::callWithBlock do
blockVar = 'Hello'
binding
end
# => Hello

Ruby Proc object as public member variable doesn't work?

I am a bit of a Ruby noob when it comes to the more advanced features. Currently I am experiencing with Proc objects. Can someone tell me what is wrong with this code sample?
class Tester
#printer = Proc.new do |text|
puts text
end
attr_accessor :printer
end
t = Tester.new
t.printer.call("Hello!")
It gives me the following error:
Test.rb:10: undefined method `call' for nil:NilClass (NoMethodError)
I don't immediately see why it shouldn't work. Can someone enlighten me?
You're not setting #printer in the class's initialize method. This'll work:
class Tester
def initialize
#printer = Proc.new { |t| puts t }
end
attr_accessor :printer
end

Resources