Accessing instance variables from outside the class - ruby

I'm having issues understanding this encapsulation. I have instance variables defined with attr_accessor. I'm trying to access them outside class. But they are always nil and returns undefined method.
NoMethodError: undefined method `has_key?' for nil:NilClass
Please help me understand.
class TrieNode
attr_reader :value, :next, :children
def initalize
#value = nil
#children = Hash.new
#next = nil
end
end
class Trie
attr_accessor :root
def initialize
#root = TrieNode.new
end
def build_trie(strs)
cur = #root
strs.each do |str|
str.chars.each do |char|
if cur.children.has_key? char
cur = cur.children[char]
next
else
new_node = TrieNode.new
cur.children[char] = new_node
cur = new_node
end
end
cur = #root
end
end
end

Yes, it is not encapsulation, it is because your object is not instantiated properly, which is caused by a typo
def initalize
#value = nil
#children = Hash.new
#next = nil
end
should be initialize not initalize

Related

NoMethodError while adding node in Ruby

I am trying to print a linked list in ruby but getting the error add': undefined method `next=' for #<Node:0x000001c5c0738688 #data=1, #next=nil> (NoMethodError)
any idea what i should do ?
class Node
def initialize data
#data = data
#next = nil
end
end
class LinkedList
def initialize
#head = nil
end
def add data
temp = #head
#head = Node.new(data)
#head.next = temp
end
def printList
temp = #head
while temp
puts temp.data
temp = temp.next
end
end
end
list = LinkedList.new
list.add(1)
list.add(2)
list.add(3)
list.printList()
In order to access the setter for the next attribute I'd propose adding an attribute_accessor to Node.
class Node
attr_accessor :next
def initialize(data)
#data = data
end
end
This will generate both a setter and a getter for the next attribute within your Node instance.
Additionally I would also add an attr_reader to Node so that you can access data from outside of the instance.
class Node
attr_accessor :next
attr_reader :data
def initialize(data)
#data = data
end
end

Add hash argument or string argument in a method to a hash (Ruby)

If the argument "entry" to the method add is a hash I need to add it to the :entries hash. If "entry" is a string "entry" needs to be set as a key in the hash and its value to nil. I have a solution below but is there a cleaner way to do this?
class Test
attr_accessor :entries
def initialize
#entries = {}
end
def add(entry)
if entry.is_a?(Hash)
entry.each do |word, definition|
#entries[word] = definition
end
else
#entries[entry] = nil
end
end
end
#test = Test.new
#test.add("the")
#{"the" => nil}
#test.add("the" => "one")
#{"the"=>"one"}
I refactored the code:
class Test
attr_accessor :entries
def initialize
#entries = {}
end
def add(entry)
entry.is_a?(Hash) ? #entries.merge!(entry) : #entries[entry] = nil
end
end

Why are none of my node children getting set?

I have the following code, and was wondering if someone can tell me why, after running it, the value of #left_child and #right_child are still nil.
I think I know why, but I am asking for confirmation to the community. Also, is there a way I can make this work in a way like this?
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
create_child(value, #right_child)
else
create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
end
end
end
node = BinaryTree::Node.new(50)
node.add_child(20)
node.left_child # => nil
node.add_child(70)
node.right_child # => nil
They are still nil because you've never assign values to them. Instead, you should change to this:
module BinaryTree
class Node
attr_accessor :left_child, :right_child
def initialize(value)
#value = value
#left_child = nil
#right_child = nil
end
def add_child(value)
if value > #value
#right_child = create_child(value, #right_child)
else
#left_child = create_child(value, #left_child)
end
end
private
def create_child(value, which_child)
if which_child.nil?
which_child = Node.new(value)
else
which_child.add_child(value)
end
which_child
end
end
end
which_child is a variable local to create_child. The value of #right_child is being copied to it when you call the method. Your code is basically the same as
right_child = nil
which_child = right_child
which_child = true
# right_child is still nil!
Variables in Ruby store pointers to objects, and Ruby passes around those pointers by value. See also:
Ruby - Parameters by reference or by value?
Is Ruby pass by reference or by value?

Singly linked list in Ruby using part of code

I got a question for implementation methods like get_item(index), or find(value) with used classes.
class SinglyLinkedListItem
attr_accessor :object, :next
attr_reader :list
def initialize(object, list)
#object = object
#list = list
end
end
class SinglyLinkedList
attr_reader :length
def initialize
#length = 0
#head = nil
#tail = nil
end
got some methods like
def each
if #length > 0
item = #head
begin
yield item.object
item = item.next
end until item.nil?
end
end
I tried with many ways, but im still getting this error:
NoMethodError: undefined method `object' for nil:NilClass
You have to define method #object on nil:
def nil.object; self end
The error will not appear that way.
I had this problem before with attr_accessor.
Try replacing the
##
with
self.#
And you might want to check the item class as a precaution.
yield item.object unless item.nil?
For Ex:
def each
if self.length > 0
item = self.head
begin
yield item.object unless item.nil? #Check if item turned nil or not
item = item.next
end until item.nil?
end
end
And there might be some more handling that you need to do, but your given data doesn't provide me enough information.

Ruby undefined method `+' for nil:NilClass (NoMethodError)

New to Ruby. Receiving error: undefined method `+' for nil:NilClass (NoMethodError)
I do not understand why I am receiving an error for such a simple task of incrementing a value. However, perhaps the error is caused by something else.
What is the cause?
class LinkedList
class Node
attr_accessor :data, :nextNode
def initialize(data = nil, nextNode = nil)
#data = data
#nextNode = nextNode
end
end
#member variables
#head = nil
#size = 0
def initialize
#head = Node.new()
end
def add(val)
curr = #head
while curr.nextNode != nil
curr = curr.nextNode
end
curr.nextNode = Node.new(val)
#size += 1 #<<<-------------------------------------ERROR LINE----------
end
end
list = LinkedList.new()
list.add(0)
Move the declaration for #size into the initialize method:
def initialize(data = nil, nextNode = nil)
#data = data
#nextNode = nextNode
#size = 0
end

Resources