I'm trying to write a small feature in a Rails app that uses the random-word gem to generate a random noun, then pluralize it. I've been able to get it working the first time I visit the page in development, but I want the script to run again on each page load. Right now, subsequent page loads (until I bounce the server) give me FiberError in WelcomeController#randomwords
, fiber called across threads
. I attempted to solve this myself, but I'm pretty new to programming and don't really understand how Fibers work. I tried using Queue, but couldn't figure out how to get it to work, again because I don't totally understand the class. How would I go about solving this specific problem?
Source: 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
The problem, as you might have found out by now, is that the random-word
gem is not thread safe. More precisely, RandomWord.nouns
is a module-level Enumerator, and accessing enumerators across threads is not safe
However, e.g. Queue
is thread safe, so for a thread-safe alternative to this functionality you could take nouns.dat
from the random-word gem, and randomly shuffle all its words into a Queue
object when you initialize your application. Now, say this queue can be accessed via random_words_queue
in the scope of your random
method. Then you can implement the random
method as
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
Note that it currently just returns nil
if the queue is empty, which you probably don't want. How you want it to behave in this case depends on your requirements:
noun
to the back of the queue right after popping it.(In any case, returning nil
is probably not what anybody wants.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With