2015-03-09 1 views
7

Я пытаюсь написать небольшую функцию в приложении Rails, которое использует random-word gem для генерации случайного существительного, а затем его размножение. Я смог заставить его работать при первом посещении страницы в разработке, но я хочу, чтобы сценарий снова запускался при каждой загрузке страницы. Прямо сейчас, последующая загрузка страницы (пока я откажу сервер) даю мне FiberError in WelcomeController#randomwords, fiber called across threads. Я попытался решить это сам, но я довольно новичок в программировании и не понимаю, как работают Fibers. Я попытался использовать Queue, но не мог понять, как заставить его работать, опять же, потому что я не совсем понимаю класс. Как мне решить эту конкретную проблему?FiberError - Fiber, вызываемый по потокам

Источник: 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 

ответ

1

Проблема, как вы, возможно, обнаружили в настоящее время, является то, что random-word камень не поточно. Точнее, RandomWord.nouns является module-level Enumerator, и accessing enumerators across threads is not safe

Однако, например, Queue является потокобезопасным, поэтому для альтернативы этой функциональности можно использовать nouns.dat from the random-word gem и случайным образом перетасовывать все его слова в объект Queue при инициализации приложения. Теперь, скажем, эту очередь можно получить через 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, вероятно, не то, что кто-то хочет.)