ถามข้อมูลผู้ใช้และไม่ต้องถามอีก

ฉันต้องการขอให้ผู้ใช้ป้อนข้อมูล แต่ฉันอยากทำเพียงครั้งเดียว (อาจบันทึกข้อมูลภายในโปรแกรม) ความหมายประมาณนี้:

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

person 13aal    schedule 06.05.2016    source แหล่งที่มา
comment
คำถามของคุณยังเร็วเกินไป คุณได้ลองอะไร? ทำไมมันไม่ทำงาน? หากคุณยังไม่ได้ลองทำไมไม่? ตัวอย่างของคุณไม่แสดงความพยายาม และนั่นคือสิ่งที่เราต้องเห็น โปรดอ่านวิธีถาม รวมถึงลิงก์ในหน้านั้น และ ตัวอย่างที่ทำซ้ำได้น้อยที่สุด ตามที่เป็นอยู่ คุณกำลังขอบทช่วยสอน แต่เราไม่รู้ว่าความเชี่ยวชาญของคุณคืออะไร ดังนั้นเราจึงต้องเริ่มจากด้านล่างสุดและทำงานกันต่อไป ซึ่งอยู่นอกหัวข้อ ผู้ใช้หลายคน/ครั้ง? จากระบบที่แตกต่างกัน? จากระบบเดียว? ใช้เบราว์เซอร์? จากบรรทัดคำสั่ง? มีข้อมูลที่ขาดหายไปมากมาย   -  person the Tin Man    schedule 06.05.2016
comment
@theTinMan เป็นยังไงบ้าง?   -  person 13aal    schedule 06.05.2016
comment
มันเป็นการปรับปรุง ข้อมูลที่ถูกบันทึกมีประโยชน์เฉพาะกับบุคคลในเครื่องนั้นเท่านั้น หรือมีประโยชน์สำหรับทุกคนในทุกเครื่องหรือไม่ เหตุผลก็คือ การบันทึกไฟล์เป็นผลดีต่อบุคคลในเครื่องเฉพาะเท่านั้น หากคุณต้องการแบ่งปันข้อมูล คุณต้องใช้พื้นที่เก็บข้อมูลที่ใช้ร่วมกัน ซึ่งโดยทั่วไปแล้วจะเป็นฐานข้อมูล   -  person the Tin Man    schedule 06.05.2016
comment
@theTinMan ฉันเข้าใจว่ามันดีสำหรับผู้ใช้บนเครื่องนั้นเท่านั้น ผลลัพธ์สุดท้ายก็คือนี่จะกลายเป็นลายเซ็นของผู้ใช้ในส่วนท้ายของอีเมล   -  person 13aal    schedule 06.05.2016
comment
คุณไม่สามารถใช้ Tempfile เพื่อวัตถุประสงค์ของคุณได้ ได้รับการออกแบบมาเพื่อสร้างไฟล์ชั่วคราวที่มีอยู่เฉพาะในระหว่างการเรียกใช้สคริปต์เท่านั้น ทันทีที่สคริปต์ออกจากไฟล์จะถูกลบออก SO ไม่ใช่ที่ที่จะถามสิ่งนี้ คุณต้องอ่านบทช่วยสอนเกี่ยวกับไฟล์ ทำความเข้าใจเกี่ยวกับวิธีการต่างๆ ในการบันทึกข้อมูล (ไฟล์ข้อความธรรมดา เทียบกับฐานข้อมูลแบบธรรมดาในเครื่อง เทียบกับโครงสร้างซีเรียลไลซ์โดยใช้ YAML หรือ JSON) ให้ลองทำสิ่งต่างๆ จากนั้นเมื่อคุณมี ปัญหาเกี่ยวกับรหัสถามคำถาม   -  person the Tin Man    schedule 06.05.2016
comment
ฉันไม่รู้ว่า การใช้ไฟล์ข้อความเป็นวิธีที่ง่ายที่สุดในการดำเนินการนี้จริงหรือ   -  person 13aal    schedule 06.05.2016
comment
meta.stackoverflow.com/questions/254572/ อาจเป็นหน้าที่มีประโยชน์สำหรับคุณ ณ จุดนี้   -  person the Tin Man    schedule 06.05.2016


คำตอบ (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.yml หรือ C:\Documents and Settings\MyUserName\Application Data\MyProgramName\ ซึ่งสามารถทำได้ค่อนข้างง่ายและยังมีความช่วยเหลืออีกมากมาย เช่น ตำแหน่งที่จะใส่ไฟล์การกำหนดค่าผู้ใช้ใน Windows และ ตำแหน่งของ ini /config ไฟล์ใน linux/unix

ต่อไป เราจะตรวจสอบว่ามีไฟล์อยู่จริงหรือไม่ และหากเป็นเช่นนั้น เราจะพยายามอ่านเนื้อหา YAML จากไฟล์นั้น เมธอด YAML.load_file() จัดการงานหนักทั้งหมดที่นี่ ดังนั้นคุณเพียงแค่ต้องถามแฮชการกำหนดค่าที่ส่งคืนมาสำหรับคีย์ที่คุณสนใจ ซึ่งในกรณีนี้คือคีย์ "name"

หากเกิดข้อผิดพลาดขณะอ่านไฟล์ YAML แสดงว่าไฟล์อาจเสียหาย ดังนั้นเราจึงพยายามจัดการกับสิ่งนั้น ไฟล์ YAML แก้ไขได้ง่ายด้วยมือ แต่เมื่อทำเช่นนั้น อาจทำให้เกิดข้อผิดพลาดที่ทำให้การโหลดไฟล์ YAML ล้มเหลวได้อย่างง่ายดาย รหัสการจัดการข้อผิดพลาดที่นี่จะทำให้ผู้ใช้สามารถยกเลิกโปรแกรมและกลับไปแก้ไขไฟล์ YAML ได้ เพื่อไม่ให้ถูกเขียนทับ

หลังจากนั้น เราพยายามดูว่าเรามีชื่อที่ถูกต้องจากการกำหนดค่า YAML หรือไม่ และหากไม่ใช่ เราจะดำเนินการต่อและยอมรับจากผู้ใช้ เมื่อพวกเขาป้อนชื่อแล้ว เราจะเพิ่มมันลงในแฮชการกำหนดค่า แปลงแฮชเป็นสตริงที่จัดรูปแบบ YAML จากนั้นเขียนสตริงนั้นลงในไฟล์กำหนดค่า

และนั่นคือทั้งหมดที่ต้องใช้ อะไรก็ได้ที่คุณสามารถเก็บไว้ใน Ruby hash คุณก็เก็บเป็นไฟล์ YAML ได้ นั่นเป็นพลังอย่างมากในการจัดเก็บข้อมูลการกำหนดค่า และหากคุณจำเป็นต้องเพิ่มตัวเลือกการกำหนดค่าเพิ่มเติมในภายหลัง คุณจะมีคอนเทนเนอร์อเนกประสงค์ที่คุณสามารถใช้เพื่อวัตถุประสงค์นั้นได้อย่างแน่นอน

หากคุณต้องการอ่านเพิ่มเติมเกี่ยวกับ YAML คุณสามารถหาข้อมูลดีๆ ได้ที่นี่:

แม้ว่าบทความเหล่านี้จะเก่าไปบ้าง แต่ก็ยังมีความเกี่ยวข้องมากและเป็นจุดเริ่มต้นในการอ่านเพิ่มเติม สนุก!

person Michael Gaskill    schedule 07.05.2016
comment
นี่อาจเป็นหนึ่งในคำตอบที่ดีที่สุดที่ฉันเคยเห็น - person 13aal; 07.05.2016

หากคุณต้องการให้ชื่อคงอยู่กับผู้ใช้ที่เรียกใช้สคริปต์หลายครั้ง คุณจะต้องใช้ที่เก็บข้อมูลบางประเภท แม้ว่าฉันจะเกลียดไฟล์แฟลตก็ตาม หากสิ่งที่คุณจัดเก็บคือชื่อผู้ใช้ ฉันคิดว่านี่เป็นตัวเลือกที่ถูกต้อง

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}"
person erahm    schedule 06.05.2016
comment
มันจะทำงานอย่างไร? โปรแกรมนี้จะทำงานหลายครั้งตลอดทั้งวัน ฉันต้องการให้พวกเขาป้อนชื่อ หนึ่งครั้ง และไม่ต้องทำซ้ำอีก โซลูชันนี้กำหนดให้ผู้ใช้ป้อนชื่อทุกครั้งที่รันโปรแกรม - person 13aal; 06.05.2016
comment
คุณควรระบุสิ่งเหล่านี้ในคำถามของคุณ คุณไม่พูดอะไรเกี่ยวกับการเรียกใช้สคริปต์หลายครั้ง เพียงแต่ว่าคุณไม่ต้องการถามชื่อของพวกเขาหลายครั้ง ฉันคิดว่านี่กำลังวนซ้ำอยู่ ในการทำสิ่งที่คุณต้องการ คุณจะต้องมีที่เก็บข้อมูลบางประเภท ฉันจะแก้ไขคำตอบเพื่อแสดงให้คุณเห็นว่าฉันกำลังพูดถึงอะไร - person erahm; 06.05.2016
comment
ฉันเห็นนั่นคือสิ่งที่ฉันคิด แต่ฉันไม่แน่ใจว่ามีวิธีที่จะทำมันภายในหน่วยความจำ Ruby หรือไม่ - person 13aal; 06.05.2016
comment
ทุกครั้งที่สคริปต์ของคุณสิ้นสุดลง หน่วยความจำจะถูกล้าง หากข้อมูลจะถูกจัดเก็บสำหรับผู้ใช้แต่ละรายที่รันสคริปต์เท่านั้น และจะถูกเรียกใช้จากเครื่องเดียวกันเสมอ ไม่จำเป็นต้องตั้งค่าฐานข้อมูลจริง มันจะเป็นเพียงค่าใช้จ่ายที่ไม่จำเป็น - person erahm; 06.05.2016