8

我正在尝试在 Rails 应用程序中编写一个小功能,该功能使用随机词 gem生成随机名词,然后将其复数。我第一次访问开发中的页面时已经能够让它工作,但我希望脚本在每个页面加载时再次运行。现在,后续页面加载(直到我弹回服务器)给了我FiberError in WelcomeController#randomwords, fiber called across threads. 我试图自己解决这个问题,但我对编程很陌生,并不真正了解 Fibers 是如何工作的。我尝试使用 Queue,但无法弄清楚如何让它工作,再次因为我不完全理解这个类。我将如何解决这个特定问题?

来源:welcome_helper.rb

def random
  noun = RandomWord.nouns.next.split('_').sample.pluralize
  if noun.include? "_"
    noun = noun.split("_").join.pluralize
  else
    noun.pluralize!
  end      
  return noun
end
4

1 回答 1

4

正如您现在可能已经发现的那样,问题在于random-wordgem 不是线程安全的。更准确地说,RandomWord.nouns模块级 Enumerator跨线程访问枚举器是不安全的

但是,egQueue是线程安全的,因此对于此功能的线程安全替代方案,您可以nouns.dat从 random-word gemQueue中获取,并在初始化应用程序时将其所有单词随机洗牌到一个对象中。现在,假设可以在您的方法random_words_queue范围内访问此队列。random然后您可以将该random方法实现为

def random
  unless random_words_queue.empty?
    noun = random_words_queue.pop
    if noun.include? "_"
      noun = noun.split("_").join.pluralize
    else
      noun.pluralize!
    end      
    return noun
  end
end

请注意,nil如果队列为空,它当前只会返回,这可能是您不想要的。在这种情况下,您希望它的行为方式取决于您的要求:

  • 如果有些可预测的词不是安全问题,并且不太可能惹恼您的用户,那么我会noun在弹出它后立即推到队列的后面。
  • 否则,你应该重新洗牌。

(无论如何,回归nil可能不是任何人想要的。)

于 2015-08-04T21:30:28.910 回答