Undefined local variable for hash in method ruby
states
is a local variable (because it starts with a lowercase letter). Local variables are local to the scope they are defined in (that's why they are called local variables, after all). So, states
is defined in the scope of the script, but not in the scope of the method describe_state
.
Method scopes don't nest, the only scopes that do nest are block scopes, so you would need to use a block. Thankfully, there is a method called define_method
which creates a method from a block:
states = {
CA: 'California',
FL: 'Florida',
MI: 'Michigan',
NY: 'New York',
OR: 'Oregon',
}
states[:CO] = 'Colorado'
states[:HI] = 'Hawaii'
cities = {
CA: ['Alameda', 'Apple Valley', 'Exeter'],
FL: ['Exeter', 'Amelia Island', 'Bunnell'],
MI: ['Ann Arbor', 'East China', 'Elberta'],
NY: ['Angelica', 'Apalachin', 'Canadice'],
OR: ['Amity', 'Boring', 'Camas Valley'],
CO: ['Blanca', 'Crestone', 'Dillon', 'Fairplay'],
HI: ['Kailua', 'Hoopili', 'Honolulu'],
}
define_method(:describe_state) do |state|
"#{state} is for #{states[state]}. " \
"It has #{cities[state].length} major cities: #{cities[state].join(', ')}"
end
puts describe_state :CA
#=> CA is for California. It has 3 major cities: Alameda, Apple Valley, Exeter
Undefined local variable or method for a Hash for main:Object (NameError)
If you are trying to use closures, then, function defined using def
does not support closure behavior - it does not remember the variables bound outside its definition.
In your case, you can change variable pushups
to @pushups
to make it instance variable.
Alternatively you may have to use lambda or equivalent. A simplified example is shown below that shows how you can access pushups
within a lambda.
Sample code
pushups = {"2015-04-16-10:05:01" => 25, "2015-04-10-10:05:01" => 150, "2015-04-11-10:05:01" => 99 }
l = ->(timestamp) do
p pushups
end
l.call ("2015-04-16-10:05:01")
Output
{"2015-04-16-10:05:01"=>25, "2015-04-10-10:05:01"=>150, "2015-04-11-10:05:01"=>99}
Reference: https://softwareengineering.stackexchange.com/questions/180579/what-is-a-closure-and-how-is-it-implemented-in-ruby
Ruby: Undefined local variable or method
Try
puts "Name?, eg. Willow Rosenberg"
name = gets.chomp
number = rand(1000..9000) + 1
data = [
{
name: name,
number: number,
email: name.split(' ').last + number.to_s[-3, 3] + "@btvs.com"
}
]
puts data
Ruby on Rails undefined local variable or method in console
There are 2 things that could be happening. First, you meant to list Article.all, referencing the class. Second, you're referencing article.all as a array, in which case it hasn't been defined as such in your code.
Also, please don't post images of code. Just copy/paste and use the code formatting tools. It really helps us understand what is going on.
Also, it helps to give as much background as possible, meaning what the code is supposed to do, why you're doing it, etc. The more thorough you are, the more helpful we can be.
A Ruby NameError, undefined local variable, was defined
Methods introduce new scope. They are not closures: one should not expect that local variables from the parent scope would be accessible there in the nested scope.
Solution 1: Use constant
POSTAL_CODES = {
V: "British Columbia",
# SKIPPED
B: "Nova Scotia"
}
def lookup_code(postal_code)
territory = POSTAL_CODES.fetch(postal_code[0].upcase.to_sym)
puts "Your address is in #{territory}"
end
Solution 2: Use an instance variable
Despite that you have no class, there is main
, which is a special instance of Object
, always defined:
@postal_codes = {
V: "British Columbia",
# SKIPPED
B: "Nova Scotia"
}
def lookup_code(postal_code)
territory = @postal_codes.fetch(postal_code[0].upcase.to_sym)
puts "Your address is in #{territory}"
end
Solution 3: Use a global variable
$postal_codes = {
V: "British Columbia",
# SKIPPED
B: "Nova Scotia"
}
def lookup_code(postal_code)
territory = $postal_codes.fetch(postal_code[0].upcase.to_sym)
puts "Your address is in #{territory}"
end
Solution 4: Abuse OOP
One might (bah!) create a class here and use it’s instance:
class Lookup
def postal_codes
@postal_codes ||= {
V: "British Columbia",
# SKIPPED
B: "Nova Scotia"
}
end
def lookup_code(postal_code)
territory = postal_codes.fetch(postal_code[0].upcase.to_sym)
puts "Your address is in #{territory}"
end
end
Lookup.new.lookup_code("01234")
Solution 5 (credits to @ndn): Inline a hash
def lookup_code(postal_code)
territory = {
V: "British Columbia",
# SKIPPED
B: "Nova Scotia"
}.fetch(postal_code[0].upcase.to_sym)
puts "Your address is in #{territory}"
end
I have a Ruby undefined local variable or method error
Problem
With your current code, you get this error:
undefined local variable or method `chicago' for main:Object (NameError)
because the way you instantiated the Message
class:
my_message = Message.new(chicago, tokyo)
chicago
and tokyo
are interpreted as variable or method that you did not actually define or declare, that's why you got that error.
Solution
I think, you just wanted to pass two string objects (putting chicago
and tokyo
in the quotes) as the arguments of Message.new
call like this:
my_message = Message.new('chicago', 'tokyo')
This will solve your problem.
Hope this makes it clear why you are getting the error and how to solve the problem.
Related Topics
Ruby (And Rails) Nested Module Syntax
What Is the Best Practice When It Comes to Testing "Infinite Loops"
How to Add to a Serialized Array
Why Is Enumerable#Each_With_Object Deprecated
How to Skip Has_Secure_Password Validations
Sinatra Configuring Environments on the Fly
How to Test Exception Raising in Rails/Rspec
How to Set Private Instance Variable Used Within a Method Test
Check If a Constant Is Already Defined
Difference Between Resource and Resources in Rails Routing
Storing Arrays in Database Using Activerecord
Populating an Association with Children in Factory_Girl