Question

J'ai un système de templates assez ancien écrit sur ERB. Il s'appuie sur les modèles ERB stockés dans la base de données. Ceux-ci sont lus et rendus. Lorsque je souhaite transmettre des données d'un modèle à un autre, j'utilise le paramètre: locals de la méthode de rendu Rails. Pour définir les variables par défaut de ces variables dans certains modèles, j'utilise le paramètre défini? méthode qui me dit simplement si une variable locale a été définie et sinon, je l'initialise avec une valeur par défaut comme ceci:

unless defined?(perex)
  perex = true
end

Je suis en train de mettre à niveau l'application vers la dernière version de Rails et je constate un comportement étrange. Fondamentalement, cela fonctionne parfois (perex n’est parfois pas défini) et parfois non (perex est défini et défini sur nil). Cela se produit sans autre changement.

J'ai deux questions: Existe-t-il un meilleur moyen que d'utiliser défini? qui se révèle peu fiable (était fiable pendant plusieurs années sur Rails 1.6)? Cela ne devrait pas me conduire à réécrire tous les modèles. Je suis passé par Ruby docs et n'ai pas pu trouver quoi que ce soit défini? méthode. Était-ce obsolète ou suis-je simplement aveugle?

Éditer: Le problème a été causé par ce qui semble être un bogue Ruby / eRB. Parfois, l'instruction à moins que ne fonctionne pas, mais parfois pas. Ce qui est étrange, c'est que même si la deuxième ligne a été exécutée, perex stil est resté nul pour le reste du monde. Supprimer défini? résolu que.

Était-ce utile?

La solution

Premièrement: défini? est un opérateur .

Deuxièmement: si je comprends bien votre question, le moyen de le faire est avec cet idiome de Ruby:

perex ||= true

Cela affectera la valeur true à perex s'il n'est pas défini ou à nil . Ce n’est pas exactement ce que fait votre exemple, car le vôtre n’évalue pas l’affectation lorsque la valeur est nil , mais si vous vous en remettez, à mon avis, sans le voir, vous n'êtes pas écrire du code clair.

Éditer : Comme Honza l’a noté, la déclaration ci-dessus remplacera la valeur de perex si elle est false . Ensuite, je propose ce qui suit pour réécrire le nombre minimum de lignes:

perex ||= perex.nil?  # Assign true only when perex is undefined or nil

Autres conseils

Le moyen le plus sûr de tester si un local est défini dans un modèle Rails est:

local_assigns[:perex]

Ceci est documenté dans l'API Rails avec l'explication que define? ne peut pas être utilisé en raison d'une restriction d'implémentation.

Par réponse, j'ai cherché cette documentation dans l'API Rails et je l'ai trouvée dans Classe ActionView :: Base (sous la rubrique "Transmission de variables locales à des sous-modèles"). La recherche n'en valait cependant pas la peine, car elle ne disait presque rien de plus que mislav. Sauf qu'il recommande ce modèle:

if local_assigns.has_key? :perex

Compte tenu des réponse originale de mislav et L'élaboration de KenB , je pense que la meilleure approche est absolue (bien que Je suis ouvert à l'opinion). Il utilise la Hash # fetch de Ruby. méthode de repliement sur une autre valeur si la clé n’existe pas dans le hachage d’origine.

perex = local_assigns.fetch(:perex, true)

C'est encore mieux que la méthode || = proposée par la plupart des utilisateurs, car vous souhaiterez parfois autoriser les valeurs false . Par exemple, le code suivant jamais autorisera la transmission d'une valeur false :

perex = local_assigns[:perex] || true
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top