2015-03-09 12 views
7

Sto provando a scrivere una piccola funzionalità in un'app Rails che utilizza lo random-word gem per generare un nome casuale, quindi pluralizzarlo. Sono riuscito a farlo funzionare la prima volta che visito la pagina in fase di sviluppo, ma voglio che lo script venga eseguito di nuovo su ogni caricamento della pagina. In questo momento, i successivi carichi di pagina (fino a quando non rimbalzo sul server) mi danno FiberError in WelcomeController#randomwords, fiber called across threads. Ho provato a risolverlo da solo, ma sono abbastanza nuovo nella programmazione e non capisco veramente come funzioni Fibre. Ho provato a usare Queue, ma non sono riuscito a capire come farlo funzionare, ancora perché non capisco completamente la classe. Come andrei a risolvere questo problema specifico?FiberError - Fibra chiamata attraverso i thread

Fonte: 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 

risposta

1

Il problema, come si potrebbe avere scoperto ormai, è che la gemma random-word non è thread-safe. Più precisamente, RandomWord.nouns è un module-level Enumerator e accessing enumerators across threads is not safe

Tuttavia, ad es. Queue è thread-safe, quindi per un'alternativa thread-safe a questa funzionalità è possibile prendere nouns.dat from the random-word gem e mescolare casualmente tutte le sue parole in un oggetto Queue durante l'inizializzazione dell'applicazione. Ora, diciamo che questa coda è accessibile tramite random_words_queue nell'ambito del tuo metodo random. Quindi è possibile implementare il metodo random come

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 

Si noti che attualmente appena ritorna nil se la coda è vuota, che probabilmente non si vuole. Come volete che si comporti in questo caso dipende dalle vostre esigenze:

  • Se le parole che sono in qualche modo prevedibile non è un problema di sicurezza, e non è probabile che infastidire gli utenti, quindi vorrei solo spingere noun alla parte posteriore della la coda subito dopo averla aperta.
  • Altrimenti, dovresti rimescolare le parole.

(In ogni caso, tornando nil non è probabilmente quello che qualcuno vuole.)