如何在Ruby中跨类使用用户输入?

问题描述

我正在编写一个抓取genius.com的应用,以向用户显示前十首歌曲。然后,用户可以选择一首歌以查看歌词。

我想知道如何在scraper类的方法中使用在cli类中收集的用户输入。

现在,我有一部分刮板发生在刮板类之外,但我希望明确划分责任。

这是我的代码的一部分:

Class CLI

def get_user_song 
  chosen_song = gets.strip.to_i
  if chosen_song > 10 || chosen_song < 1
  puts "Only the hits! Choose a number from 1-10."
end

我希望能够执行以下操作。

Class Scraper

def self.scrape_lyrics
  page = Nokogiri::HTML(open("https://genius.com/#top-songs")) 
  @url = page.css('div#top-songs a').map {|link| link['href']}
  user_selection = #input_from_cli #<---this is where I'd like to use the output 
  # of the 'gets' method above.

  @print_lyrics = @url[user_selection - 1]
  scrape_2 = Nokogiri::HTML(open(@print_lyrics))
  puts scrape_2.css(".lyrics").text
end 

我基本上想知道如何将所选的歌曲变量传递到Scraper类中。我尝试过一种编写类的方法,但是在编写该类方法时遇到了麻烦,不会破坏程序的其余部分。

感谢您的帮助!

解决方法

我看到了两种解决您问题的方法。哪一种适合此取决于您的设计目标。我将尝试使用每个选项进行解释:

  • 从对代码的简单阅读中,用户输入了数字而没有看到页面的内容(通过您的程序)。在这种情况下,简单的方法是将所选数字作为参数传递给scrape_lyrics方法:

    def self.scrape_lyrics(user_selection)
      page = Nokogiri::HTML(open("https://genius.com/#top-songs")) 
      @url = page.css('div#top-songs a').map {|link| link['href']}
      @print_lyrics = @url[user_selection -1]
      scrape_2 = Nokogiri::HTML(open(@print_lyrics))
      puts scrape_2.css(".lyrics").text
    end 
    

    所有排序都发生在CLI类中,并且在开始时使用所有必需的数据调用刮板。

  • 当以更具交互性的方式想象您的工具时,我想让刮板下载当前的前10名并将列表呈现给用户以供选择可能会很有用。在这种情况下,交互作用要来回多一些。 如果仍然需要严格分开,可以将scrape_lyrics分为scrape_top_tenscrape_lyrics_by_number(song_number)并在CLI类中对其进行排序。 如果您希望交互流程非常动态,那么最好将交互方法注入刮板中并反转依赖关系:

    def self.scrape_lyrics(cli)
      page = Nokogiri::HTML(open("https://genius.com/#top-songs")) 
      titles = page.css('div#top-songs h3:first-child').map {|t| t.text}
      user_selection = cli.choose(titles) # presents a choice to the user,returning the selected number
    
      @url = page.css('div#top-songs a').map {|link| link['href']}
      @print_lyrics = @url[user_selection - 1]
      scrape_2 = Nokogiri::HTML(open(@print_lyrics))
      puts scrape_2.css(".lyrics").text
    end 
    

    有关后一种方法的示例实现,请参见tty-prompt gem