web-dev-qa-db-fra.com

ActiveModel :: MissingAttributeError se produit après le déploiement, puis disparaît après un certain temps

J'ai une application Rails 3.0.9 qui, une fois déployée, souffre d'un tas d'ActiveModel :: MissingAttributeErrors qui surgit, provoquant des 500. Les erreurs se produisent de manière assez aléatoire, parfois une page se charge , d'autres fois, ce n'est pas le cas, mais les attributs sont tous des attributs existants dans la base de données et doivent être trouvés.

La partie étrange est qu'après un certain temps, les erreurs disparaissent. Du coup, ils arrêtent de causer un problème.

J'ai cherché une solution à ce problème, mais cette erreur se produit principalement lorsque quelqu'un a fait Model.all(:select => 'column_x,column_y') et appelle column_z ou lorsqu'ils utilisent cache_money. Je ne fais rien de tout cela.

Quelqu'un peut-il aider?

47
philnash

Vous avez probablement une requête qui ne retourne pas toutes les colonnes (c'est-à-dire utilise :select), Puis cache_money; ou un autre plugin ActiveRecord utilise un rappel after_initialize, qui s'exécute chaque fois qu'un nouvel objet ActiveRecord est créé (c'est-à-dire lorsqu'il est extrait de la base de données).

Dans ce rappel d'initialisation, quelque chose essaie d'accéder ou d'utiliser un attribut qui n'était pas inclus dans le :select. Vous vous attendriez à ce que cela renvoie nil pour cet attribut, mais une ActiveRecord :: MissingAttributeError est levée à la place.

Vous pouvez sauver ActiveRecord :: MissingAttributeError comme le suggère l'article, ou patcher le (s) plugin (s) pour utiliser has_attribute?(:attribute_name) avant d'essayer d'accéder ou de modifier l'attribut.

123
randomguy

Si vous rencontrez ce problème uniquement directement après la mise à jour de votre base de données sans aucun déploiement ou redémarrage du serveur, alors ce qui a fonctionné pour moi peut fonctionner pour vous:

Courir heroku restart et il devrait être corrigé. Avant que le dynamomètre ne redémarre, les anciennes données restent parfois mises en cache sur le serveur, donc le redémarrer effacera toutes ces données et l'empêchera de provoquer des erreurs de ce type. J'espère que cela t'aides.

7
rmtsukuru

J'ai corrigé cela en ajoutant .to_json jusqu'à la fin du rendu de mon contrôleur.

2
Robbie Guilfoyle

J'ai trouvé une interprétation intéressante à ce sujet qui a entraîné la même erreur. Dans une tentative de réutilisation du code, nous sous-classons une classe de présentateurs avec une classe de présentateurs qui a effectué un regroupement à utiliser dans une vue graphique.

Pour simplifier, c'était quelque chose comme:

class PostPresenter 
  def query
    Post.where(...stuff....).includes(:wombat)
  end
end

L'agrégateur a fait quelque chose comme ce qui suit pour créer un tableau de messages par jour:

class AggregatePostPresenter < PostPresenter
  def group_query
    query.select('count(*) as cnt, date(created_at)').group('date(created_at)')
  end
end

Un appel à "group_query" entraîne une ActiveModel :: MissingAttributeError car, je pense, la tentative "d'inclure" Wombat échoue parce que "wombat_id" n'était pas dans les attributs inclus dans le "select".

Ce n'est probablement pas votre réponse, car cela se produit, que le cache soit activé ou non.

2
GSP

J'ai rencontré ce problème. Assurez-vous que votre select: inclut tous les champs référencés dans votre vue, y compris tout ID de relation et tout attribut appelé dans vos méthodes.

L'attribut manquant peut être difficile à identifier lorsque vos vues et relations sont complexes. La façon la plus simple de déboguer cela est de supprimer la partie select de votre clause where et de voir si la requête/portée/méthode s'exécute correctement. Si tel est le cas, ajoutez tous les attributs à select et supprimez les attributs inutiles une par une jusqu'à ce que vous trouviez l'attribut incriminé.

2
scarver2