Undefined local variable for hash in method ruby

后端 未结 3 1631
别那么骄傲
别那么骄傲 2020-12-12 05:21

for some reason I\'m getting

NameError: undefined local variable or method `states\' for main:Object

though states is clearly defined. What

相关标签:
3条回答
  • 2020-12-12 06:00

    states and cities are not defined in the function pass them in like

    def describe_state state, states, cities
     ..
    end
    puts describe_state :CA, states, cities
    

    will work

    0 讨论(0)
  • 2020-12-12 06:09

    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
    
    0 讨论(0)
  • 2020-12-12 06:17

    The method can't access the outside variables. You could use instance variables instead. From the documentation:

    Instance variables are shared across all methods for the same object.

    Example:

    @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'],
    }
    
    def describe_state state
      description = "#{state.to_s} is for #{@states[state]}."
      description << " It has #{@cities[state].length} major cities: "
      description << @cities[state].join(', ')
    end
    
    puts describe_state :CA
    #=> CA is for California. It has 3 major cities: Alameda, Apple Valley, Exeter
    

    (I've fixed a minor bug in describe_state)

    0 讨论(0)
提交回复
热议问题