Ruby类的未识别方法“add”

Ruby类的未识别方法“add”,ruby,Ruby,这是一个伪造的银行应用程序: class Bank private def initialize $login = Hash.new puts "Welcome to HEIDI BANK!" end def add(keyVal) keyVal.each do |key, value| $login[key] = value end end def NewUser

这是一个伪造的银行应用程序:

class Bank
    private def initialize
        $login = Hash.new
        puts "Welcome to HEIDI BANK!"
    end

    def add(keyVal)
        keyVal.each do |key, value|
            $login[key] = value
        end
    end

    def NewUser
        puts "What is the name of the user you would like to add?"
        user = gets.chomp
        puts "What is the password you would add?"
        pass = gets.chomp
        passsym = pass.to_sym
        $login.add(user => passsym)
    end
end

you_bank = Bank.new
you_bank.NewUser
当我尝试运行它时,我得到:

Welcome to HEIDI BANK!
What is the name of the user you would like to add?
12
What is the password you would add?
13
然后出现一个错误:

in `NewUser': undefined method `add' for {}:Hash(NoMethodError)

如何修复此错误?看来我得想办法打电话给银行。添加什么。散列是否有内置的
add
函数,如
samp\u数组。为数组推送

您将
add
定义为
Bank
的一个实例方法,但您在
$login
上调用它,这是
散列
的一个实例。在
Bank
自身的实例上调用它,可以省略:

def NewUser
  ...
  add(user => passsym)
end

我已经在评论中提供了答案,但我想做一个较长的回答来帮助您。看来你是个年轻的程序员,对Ruby还不熟悉,所以我想帮助你养成健康的习惯。因此,我对您的代码进行了重构,并包含了解释更改的注释,以及指向资源的链接,您可以阅读这些链接来帮助理解更改的原因

这些都是小问题,但在编写任何类型的生产代码或编写其他人将来可能不得不阅读或使用的代码时,它们都很重要

# Allows the use of STDIN.noecho which will not echo text input back to the console:
# https://stackoverflow.com/a/29334534/3784008
require 'io/console'

# Use two spaces of indentation for Ruby, not tabs and not 4 spaces:
# https://github.com/rubocop-hq/ruby-style-guide#source-code-layout
class Bank
  # The initialize method is not a private method:
  # https://stackoverflow.com/q/1567400/3784008
  def initialize
    # Use single quotes for non-interpolated strings
    # https://github.com/rubocop-hq/ruby-style-guide#strings
    puts 'Welcome to HEIDI BANK!'

    # Don't instantiate the `login` variable here; it should be lazily instantiated:
    # http://blog.jayfields.com/2007/07/ruby-lazily-initialized-attributes.html
  end

  # Use snake_case for method names
  # https://github.com/rubocop-hq/ruby-style-guide#naming
  def new_user
    puts 'What is the name of the user you would like to add?'
    user = gets.chomp

    puts 'What is the password you would add?'
    # Suppress local echo of the password as it is typed
    # https://stackoverflow.com/a/29334534/3784008
    pass = STDIN.noecho(&:gets).chomp

    # Do not call .to_sym on pass; if pass == an Integer then it will raise an exception,
    # e.g., 1.to_sym => NoMethodError: undefined method `to_sym' for 1:Integer
    { user => pass }
  end
end
然后像以前一样运行它:

you_bank = Bank.new
Welcome to HEIDI BANK!
=> #<Bank:0x00007f8cc9086710>
you_bank.new_user
What is the name of the user you would like to add?
foo
What is the password you would add?
=> {"foo"=>"bar"}
对于您关于将用户名和密码与用户键入的内容进行比较的其他问题,我建议您仔细考虑这个问题,如果您仍然不确定,请发布一个新问题。你问的问题不够清楚,我无法给你一个好答案。现在,您正在使用代码进行实验,以了解一切是如何工作的,当您在进行实验和学习时,可以做一些不完全符合面向对象编程设计模式的事情。但是,我根据你到目前为止告诉我的内容给你的任何答案要么与这些模式背道而驰,要么过于超前。(例如,在Rails等框架中使用数据库和相关模型)

我不会做第一件事,因为那是一个糟糕的建议,我不会做第二件事,因为你首先应该更牢固地掌握Ruby和编程。因此,我建议您仔细考虑以下几点:

  • 你的总体目标是什么
  • 如何用面向对象逻辑来描述这种解释
  • 您可以编写什么代码来封装该逻辑
  • 您描述逻辑的能力和为该逻辑编写代码的能力之间有什么差距

  • 然后你可以开始问一些具体的问题来填补这些空白。

    大家都想知道,海蒂是我妹妹的名字。这就是为什么它被称为HEIDI bank。
    $login.merge(用户:passsym)
    。看,我在另一篇文章中读到,这将删除旧的键和值。这是真的吗?
    hash.merge(key:value)
    使用
    hash
    作为包含新键值对的模板创建一个新的
    hash
    。如果密钥已存在于
    散列
    中,则当
    合并
    创建新的
    散列
    时,新的
    散列
    将具有新的键值对,而不是旧的键值对。这都在我之前的评论中包含的链接中:“返回一个包含其他散列内容和hsh内容的新散列”或更改
    $login.add(user=>passsym)
    self.add(user=>passsym)
    什么是延迟实例化?这是一个我不熟悉的概念。我应该把它作为一个实例变量来初始化吗,例如,@login?我刚刚记起来了!当在check balance方法中输入的用户名和密码与散列中的用户/密码匹配时,我将如何检查?@Nathatibbitts我已更新我的答案以提供其他信息。
    # Bad; don't do this
    class Foo
      def initialize
        # This variable is instantiated when calling `Foo.new`, 
        # before it needs to be used, and so takes up memory right 
        # away vs. only once it's needed
        @variable_used_by_example_method = 'foobar'
      end
    
      def example_method
        puts @variable_used_by_example_method
      end
    end
    
    # Better; okay to do this
    class Foo
      def initialize
      end
    
      def example_method
        # This variable is lazily instantiated, that is, it is not 
        # instantiated until `Foo.new.example_method` is called
        @variable_used_by_example_method = 'foobar'
        puts @variable_used_by_example_method
      end
    end