Ruby "Undefined method 'length' for #<NetAddr::CIDRv4..." - ruby

I have an array of three NetAddr::CIDR objects and am attempting to sort them using the cidr_sort method of the NetAddr module (http://rubydoc.info/gems/netaddr/1.5.0/NetAddr#cidr_sort-class_method)
When I call the sort method from within my Class as follows:
Class IPv4SummaryNet
attr_accessor :component_nets
#component_nets = []
def add_net(net)
#component_nets = component_nets.to_a.push(net)
end
def sort_component_nets
component_nets_sorted = #component_nets.sort
end
...
end
I get the following error: /usr/local/lib/ruby/gems/2.1.0/gems/netaddr-1.5.0/lib/cidr_shortcuts.rb:216:in 'cidr_sort': undefined method 'length' for #<NetAddr::CIDRv4:0x007f55cbae0088> (NoMethodError)
But if I print the array length from within my program, I get the correct value of 3.
I have also tried using sort_by and NetAddr::cidr_sort(#component_nets) and get the same error.
Why is Ruby telling me length is undefined when the cidr_sort method tries to call it, yet I can call it in my code with no problem?

def sort_component_nets
component_nets_sorted = #component_nets.sort
end
Here Ruby thinks you are trying to create a local variable within the method block, but I assume that you actually want to access the method component_nets_sorted that is outside the block. To do this: you must add the self. prefix to it.
def sort_component_nets
self.component_nets_sorted = #component_nets.sort
end

Related

Ruby - constant initialisation with some function produces NoMethodError

Let's consider following code:
class Try
CONST = xxx("42")
private_class_method def self.xxx(str)
str.to_i
end
end
puts Try::CONST
It produces an error: undefined method `xxx' for Try:Class (NoMethodError)
It seems that I cannot use a class private method to initialise a constant. The example is doing nothig actually, but it is a reproduction of an error I am facing trying to read data from file into the class constant.
Is it becuse ruby tries to initialize a constant before it get know about all methodes, or am I doing something wrong?
Not really. What you can't do is to assign the value of something that still hasn't been defined to something else in order to hold its value.
It has nothing to do with the method visibility because this works:
class Try
private_class_method def self.xxx(str)
str.to_i
end
CONST = xxx("42")
end
p Try::CONST
# 42

Why am I getting an error calling instance_eval with to_proc and not with Proc.new?

I'm doing this and it works:
class B
def value
"X"
end
end
class A
def initialize(context)
#context = context
end
def m
Proc.new do
value
end
end
def execute
#context.instance_eval(&m)
end
end
A.new(B.new).execute #=> "X"
But calling m.to_proc is not working...
class B
def value
"X"
end
end
class A
def initialize(context)
#context = context
end
def m
value
end
def execute
#context.instance_eval(&m.to_proc)
end
end
A.new(B.new).execute #=> NameError: undefined local variable or method `value' for #<A:0x007fae2ab02040 #context=#<B:0x007fae2ab02108>>
I want to know why these two examples are different and how to make it work with to_proc
In the second snippet, you are calling m, which returns the result of calling value, which is undefined. (And even if if were somehow magically calling B#value, then B#value returns a String and Strings don't respond to to_proc, so you would get a NoMethodError there.) In the first snippet, you call m, which returns a Proc.
It looks like you are trying to pass the method m itself instead of the result of calling it. In Ruby, methods aren't objects, so you can't just grab them and pass them around (and even if methods were objects, then m is still the syntax for calling m, not for referencing it). You have to ask Ruby's reflection API for a reflective proxy for the method first, using the Object#method method, which returns a Method object representing the method:
#context.instance_eval(&method(:m).to_proc)
Note that the call to to_proc is completely redundant here, since & will call to_proc anyway if the argument isn't a Proc already. (You may have seen something like foo.map(&:bar) before, which will invoke Symbol#to_proc.)
#context.instance_eval(&method(:m))

Defining a method in Rubymine returns "undefined method" error

I am executing a class with only this code in rubymine:
def saythis(x)
puts x
end
saythis('words')
It returns an error: undefined method `saythis', rather than printing the string 'words'. What am I missing here? Replicating this code in irb prints the string 'words'.
I assume you wrote a class like the one below and did not write that code into a irb console. The problem is that you define an instance method, but try to call the method from the class level.
class Foo
def say_this(x) # <= defines an instance method
puts x
end
say_this('words') # <= calls a class method
end
There a two ways to "fix" this:
Define a class method instead of an instance method: def self.say_this(x)
Call the instance method instead of the class method call: new.say_this(x)

NoMethodError ; private or undefined method?

class Array
def my_uniq(array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless arr.include(element)
end
end
end
Array.my_uniq([1,2,3,3])
I am using ruby calc1.rb in terminal to call the program. Terminal is in the correct folder and the file is saved in the correct folder.
Output
calc1.rb:9:in `<main>': undefined method `my_uniq' for main:Object (NoMethodError)
It appears previous answers were about either calling the method before it was defined or look, to me, like my solution that calls the class, then invokes the method on an array. Is there a private or undefined method going on here?
You need to create the method as a class method to work. But you created the method as an instance method of the class Array and calling on the Array class object, not on the instance of the Array, thus you got the error.
Below will work :
class Array
def self.my_uniq(array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless new_array.include(element)
end
new_array
end
end
Array.my_uniq([1,2,3,3])
Looking also at the error, it seems, you called the method my_uniq from top level. But in that case also, it wouldn't work, as on toplevel self is main, instance of Object class.But the method is not defined inside the Object class as an instance method, so bare method call from toplevel also wouldn't work.
Here's the script that I got it to work with in case anyone is wondering
class Array
def self.my_uniq (array_taken)
new_array=[]
array_taken.each do |element|
new_array << element unless new_array.include?(element)
end
new_array
end
end
p Array.my_uniq([1,2,3,3,3])

Unable to Create a Ruby Hash inside a Class

I am trying to create a simple Ruby class but I am getting stuck. This is my code:
#!/usr/bin/ruby
class Dock
#ships = Hash.new(false)
def initialize()
end
def store(ship, pier)
#ships[pier] = ship
end
end
yathi = Dock.new
yathi.store("test", 12)
But when I try to run this by running this in Terminal:
ruby test.rb
This is the error message I am getting:
test.rb:8:in `'store': undefined method `'[]=' for nil:NilClass (NoMethodError)
from test.rb:13
It does work when if I rewrite it like this:
#ships = {pier => ship}
But this creates a new hash everytime with just one value which I don't want. Can someone please tell me what I am doing wrong?
Put the #ships = Hash.new(false) inside the initialize method. When you put it outside the initialize method you are defining a class level instance variable instead. Check out this writeup if you want to know more.
Try initializing the hash inside the "initialize" method so that it is a member of instances of the Dock class instead of a member of the Dock class itself:
class Dock
def initialize()
#ships = Hash.new(false) # <-- Define #ships as an instance variable.
end
def store(ship, pier)
#ships[pier] = ship
end
end

Resources