【问题标题】:Asking user for information, and never having to ask again向用户询问信息,无需再次询问
【发布时间】:2016-09-02 00:01:24
【问题描述】:

我想询问用户输入,但我只想做一次(可能将信息保存在程序中),意思是这样的:

print "Enter your name (you will only need to do this once): "
name = gets.chomp

str = "Hello there #{name}" #<= As long as the user has put their name in the very first 
# time the program was run, I want them to never have to put thier name in again

我怎样才能在 Ruby 程序中做到这一点?

该程序将由多个用户全天在多个系统上运行。我试图将它存储到内存中,但显然失败了,因为据我了解,每次 Ruby 程序停止执行时都会擦除内存。

我的尝试:

def capture_user
  print 'Enter your name: '
  name = gets.chomp
end
#<= works but user has to put in name multiple times

def capture_name      
  if File.read('name.txt') == ''
    print "\e[36mEnter name to appear on email (you will only have to do this once):\e[0m "
    @esd_user = gets.chomp
    File.open('name.txt', 'w') { |s| s.puts(@esd_user) }
  else
    @esd_user = File.read('name.txt')
  end
end
#<= works but there has to be a better way to do this?

require 'tempfile'

def capture_name
  file = Tempfile.new('user')
  if File.read(file) == ''
    print "\e[36mEnter name to appear on email (you will only have to do this once):\e[0m "
    @esd_user = gets.chomp
    File.open(file, 'w') { |s| s.puts(@esd_user) }
  else
    @esd_user = File.read(file)
  end
end
#<= Also used a tempfile, this is a little bit over kill I think,
# and doesn't really help because the users can't access their Appdata

【问题讨论】:

  • 你的问题为时过早。你试过什么?为什么它不起作用?如果你还没有尝试过,为什么不呢?您的示例没有显示任何尝试,这就是我们需要看到的。请阅读“How to Ask”(包括该页面中的链接)和“minimal reproducible example”。照原样,您要求提供教程,但我们不知道您的专业知识是什么,因此我们必须从最底层开始工作,这是题外话。多个用户/时间?来自不同的系统?从一个系统?使用浏览器?从命令行?有很多缺失的信息。
  • @theTinMan 怎么样?
  • 这是一个改进。保存的信息是只对那台机器上的个人有用,还是对所有机器上的每个人都有用?原因是,保存文件只对特定机器上的个人有用。如果您需要共享您需要使用共享数据存储库(通常是数据库)的信息。
  • 您不能将 Tempfile 用于您的目的。它旨在创建一个仅在脚本执行期间存在的临时文件。一旦脚本退出,文件就会被删除。所以不是问这个的地方。您需要阅读一些文件教程,了解保存数据的各种方法(平面文本文件,与本地简单数据库,与使用 YAML 或 JSON 的序列化结构),尝试一下,然后当您有代码有问题问一个问题。
  • meta.stackoverflow.com/questions/254572/… 此时可能对您有用。

标签: ruby user-input


【解决方案1】:

如果您需要在多次运行脚本的用户中保留该名称,您将需要使用某种数据存储。尽管我讨厌平面文件,但如果您存储的只是用户名,我认为这是一个有效的选择。

if File.exist?('username.txt')
    name = File.open( 'username.txt', 'r' ) do |file|
        name = file.gets
    end
else
    print "Enter your name (you will only need to do this once): "
    name = gets.chomp

    File.open( 'username.txt', 'w' ) do |file|
        file.puts name
    end
end
str = "Hello there #{name}"

【讨论】:

  • 这将如何工作?这个程序将在一天中运行多次,我希望他们必须输入他们的名字 一次 并且永远不必再这样做。此解决方案将要求用户在每次运行程序时输入他们的姓名
  • 您应该在问题中指定这些内容。您没有说要多次运行脚本,只是您不想多次询问他们的名字——我认为这是在某种循环中运行。为了做你想做的事,你需要某种数据存储。我将编辑我的答案,向您展示我在说什么。
  • 我明白了,这就是我的想法,但我不确定是否有办法在 Ruby 内存中做到这一点。
  • 每次脚本结束时,内存都会被擦除。如果只为每个运行脚本的用户存储数据,并且总是在同一台机器上运行,则不需要设置实际的数据库。这只是不必要的开销。
【解决方案2】:

您需要将用户名存储在本地文件系统上的文件中。 Ruby 提供了许多方法来做到这一点,我们将在这个答案中探索一种:YAML 文件。

YAML 文件是一个结构化的存储文件,可以存储各种不同的数据,是存储配置数据的好地方。事实上,YAML 配置文件是现存最大的 Ruby 项目的关键部分。 YAML 为您提供了一个很好的起点来支持未来的配置需求,超越当前配置需求,这是规划功能开发的好方法。

那么,它是如何工作的?让我们使用 YAML 配置来看看您的要求:

require 'yaml'

config_filename = "config.yml"
config = {}
name = nil

if file_exists(config_filename)
  begin
    config = YAML.load_file(config_filename)
    name = config["name"]
  rescue ArgumentError => e
    puts "Unable to parse the YAML config file."
    puts "Would you like to proceed?"
    proceed = gets.chomp

    # Allow the user to type things like "N", "n", "No", "nay", "nyet", etc to abort
    if proceed.length > 0 && proceed[0].upcase == "N"
      abort "User chose not to proceed.  Aborting!"
    end
  end
end

if name.nil? || (name.strip.length == 0)
  print "Enter your name (you will only need to do this once): "
  name = gets.chomp

  # Store the name in the config (in memory)
  config["name"] = name

  # Convert config hash to a YAML config string
  yaml_string = config.to_yaml

  # Save the YAML config string to the config file
  File.open(config_filename, "w") do |out|
   YAML.dump(config, out)
  end
end

此代码并未向您展示满足您需求的最低要求,而是包含一些错误处理和一些对配置文件的简单安全检查。它可能足够强大,可以立即使用。

首先需要 YAML 标准库。这使得 YAML 函数在您的程序中工作。如果您有加载程序文件或其他类似的常见机制,只需将require 'yaml' 放在那里即可。

之后,我们初始化一些在此过程中使用的变量。你应该注意config_filename里面没有路径信息,所以会从当前目录读取。您可能希望将配置文件存储在一个公共位置,例如~/.my-program-name/config.ymlC:\Documents and Settings\MyUserName\Application Data\MyProgramName\。这可以很容易地完成,并且有很多帮助,例如 Location to Put User Config Files in WindowsLocation of ini/config files in linux/unix

接下来,我们检查文件是否确实存在,如果存在,我们尝试从中读取 YAML 内容。 YAML.load_file() 方法在这里处理所有繁重的工作,因此您只需询问返回的配置哈希以获得您感兴趣的密钥,在本例中为 "name" 密钥。

如果在读取 YAML 文件时发生错误,则表明该文件可能已损坏,因此我们尝试处理该问题。 YAML 文件很容易手动编辑,但是当你这样做时,你也很容易引入一个错误,导致加载 YAML 文件失败。此处的错误处理代码将允许用户中止程序并返回修复 YAML 文件,这样它就不会被简单地覆盖。

之后,我们尝试查看是否从 YAML 配置中获得了一个有效的名称,如果没有,我们继续从用户那里接受它。一旦他们输入了名称,我们将其添加到配置哈希中,将哈希转换为 YAML 格式的字符串,然后将该字符串写入配置文件。

仅此而已。几乎可以存储在 Ruby 哈希中的任何内容,都可以存储在 YAML 文件中。这是存储配置信息的强大功能,如果您以后需要添加更多配置选项,您可以使用一个多功能容器来完全用于此目的。

如果你想进一步阅读 YAML,你可以在这里找到一些很好的信息:

虽然其中一些文章有点老,但它们仍然非常相关,可以为您提供进一步阅读的起点。享受吧!

【讨论】:

  • 这可能是我见过的最好的答案之一。
猜你喜欢
  • 2011-07-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-02-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-02-15
相关资源
最近更新 更多