TemplateError incompréhensible

Bonjour,

je rencontre depuis quelques jours une erreur assez incompréhensible
lors du rendu d’un template.
Je dis incompréhensible car elle se reproduit de façon erratique.

J’ai un modèle Body qui possède dans sa table plusieurs champs pouvant
nommer un body :
name, preliminary_designation, iau_id

Et je définis une méthode designation qui me renvoie le premier
attribut non-nul.

Voilà le code simplifié (j’ai supprimé les méthodes de validation)

class Body < ActiveRecord::Base
has_many :bodies_encounters
has_many :encounters, :through => :bodies_encounters

def designation
possible_designations = [‘name’, ‘preliminary_designation’,
‘iau_id’]

possible_designations.each { |d|
  return self.attributes[d] unless self.attributes[d].blank?
}

# ne devrait pas arriver grâce aux validations
return nil

end
end

La méthode marche très bien lorsque je l’applique à un Body. Et si je
liste (dans le template index)
tous les Bodies et que j’applique la méthode à tous, ça fonctionne
encore très bien.

Mais lorsque je liste les Encounters liés à ces Bodies, c’est là que
ça coince de façon aléatoire :
ActionView::TemplateError (NaN) on line #29 of app/views/encounters/
_table.html.erb:

26:
27:

<% if b1.class.to_s.eql?(‘Planet’) %> </
td><% end %>
28:
29: <%= link_to b1.designation, b1 %>
30:
31: <% if b1.class.to_s.eql?(‘Tno’) %> <%
end %>
32:
/usr/pkg/lib/ruby/1.8/date.rb:422:in `floor'
/usr/pkg/lib/ruby/1.8/date.rb:422:in `jd_to_civil'
/usr/pkg/lib/ruby/1.8/date.rb:1066:in `__18057__'
(eval):4:in `civil'
/usr/pkg/lib/ruby/1.8/date.rb:1081:in `year'
app/models/body.rb:40:in `designation'
app/models/body.rb:39:in `each'
app/models/body.rb:39:in `designation'
app/views/encounters/_table.html.erb:29
app/views/encounters/_table.html.erb:21:in `each'
app/views/encounters/_table.html.erb:21
app/views/encounters/index.html.erb:3
app/controllers/encounters_controller.rb:11:in `index'

Les Encounters sont très nombreux (+ de 7000), et le rendu plante
parfois dès le début, parfois
plutôtvers la fin (je le vois aux “select bodies.* …” qui sont fait dans
la base)

Par contre, quand je change ma méthode en :

def designation
return self.name unless self.name.blank?

return self.preliminary_designation unless

self.preliminary_designation.blank?

return self.iau_id unless self.iau_id.blank?

return nil

end

là, je n’ai plus aucun plantage.

Je dois avouer que l’erreur concernant la date me laisse perplexe, car
il n’est question de
date nulle part. J’ai bien un attribut de type date dans la table
Body, mais elle n’est
pas en jeu ici.

Est-ce que l’un d’entre-vous aurait déjà rencontré une telle erreur ?

Merci d’avance

Salut,

si la référence à la date apparaît, on doit faire confiance à Ruby et
considérer que c’est un problème de date.

Es-tu absolument sûr et certain (oui, j’ai lu ton message) qu’aucun
des trois attributs que tu affiches ne contient une date ?

Lorsqu’il plante sur l’affichage d’un objet, arrives-tu à récupérer
ses données pour “l’étudier” ?

Est-ce que cette autre variante fonctionne :

class Body < ActiveRecord::Base

POSSIBLE_DESIGNATIONS = [:name, :preliminary_designation, :lau_id]

def designation
POSSIBLE_DESIGNATIONS.each do |d|
next if self.send(d).blank?
return self.send(d)
end
end

end

Tiens nous au courant

Le 15 sept. 09 à 17:03, olfhen a écrit :

possible_designations = ['name', 'preliminary_designation',

26:
/usr/pkg/lib/ruby/1.8/date.rb:422:in jd_to_civil' app/controllers/encounters_controller.rb:11:in index’
return self.preliminary_designation unless
il n’est question de
date nulle part. J’ai bien un attribut de type date dans la table
Body, mais elle n’est
pas en jeu ici.

Est-ce que l’un d’entre-vous aurait déjà rencontré une telle erreur ?

Merci d’avance

Guillaume D.
Membre de l’association Ruby France
http://www.rubyfrance.org/

On 15 sep, 17:03, olfhen [email protected] wrote:

end %>
app/views/encounters/_table.html.erb:29
app/views/encounters/_table.html.erb:21:in each' app/views/encounters/_table.html.erb:21 app/views/encounters/index.html.erb:3 app/controllers/encounters_controller.rb:11:in index’

Les Encounters sont très nombreux (+ de 7000), et le rendu plante
parfois dès le début, parfois plutôt
vers la fin (je le vois aux “select bodies.* …” qui sont fait dans
la base)

Bonjour,

Je pencherai pour un problème de ressources / performances pour
plusieurs raisons :

  • l’aspect aléatoire
  • le “ActionView::TemplateError”
  • “self.attributes[…]” qui délègue en réalité à
    “self.read_attribute(…)”
  • le fait qu’il y ait un has_many de has_many de 7000
    résultats… :slight_smile:

Deux petites questions :

  • quelle version de Rails ?
  • lors d’un rendu, tes logs sont-ils polués par N fois le même type
    de requête ?

Même si je me trompe, les points suivants ne feront pas de mal :

  • vérifier la relation entre Body et Encounters, on est bien au
    final sur du 1-N ?
  • vérifier que tes “include” sont bien en place, ex :
    Body.all(:include => { :bodies_encounters => :encounters })
  • éviter “self.attributes”

Note : “b1.class.to_s.eql?(‘Planet’)” peut s’écrire “b1.instance_of?
(Planet)” (voir aussi la méthode “is_a?”)

Bon courage !


Julien Vignolles

On 18 sep, 10:14, olfhen [email protected] wrote:

Oui, elle marche très bien. Quelle est cette méthode send() ? Je ne la
vois pas
dans la doc de Rails.

Il faut regarder dans la doc Ruby :
http://corelib.rubyonrails.org/classes/Object.html#M001077


Julien Vignolles

Bonjour,

On 16 sep, 07:48, Guillaume D. [email protected]
wrote:

si la référence à la date apparaît, on doit faire confiance à Ruby et
considérer que c’est un problème de date.

Es-tu absolument sûr et certain (oui, j’ai lu ton message) qu’aucun
des trois attributs que tu affiches ne contient une date ?

oui. voilà un extrait de mon schéma:

create_table “bodies”, :force => true do |t|
t.string “iau_id”
t.string “preliminary_designation”
t.string “name”
end

Lorsqu’il plante sur l’affichage d’un objet, arrives-tu à récupérer
ses données pour “l’étudier” ?

oui. et ça ne plante jamais sur le même objet…

                    next if self.send(d).blank?
                    return self.send(d)
            end
    end

end

Oui, elle marche très bien. Quelle est cette méthode send() ? Je ne la
vois pas
dans la doc de Rails.

Ce serait donc la méthode attributes() qui pose problème ?

Bonjour,

On 16 sep, 22:06, Meshak [email protected] wrote:

  • quelle version de Rails ?
    2.3.2
  • lors d’un rendu, tes logs sont-ils polués par N fois le même type
    de requête ?

Oui et non. Lorsque j’ai rencontré le pb pour la première fois, en
effet, mes
logs étaient remplis de
SELECT “bodies”.* FROM “bodies” INNER JOIN “bodies_encounters” ON
“bodies”.id = “bodies_encounters”.body_id WHERE
((“bodies_encounters”.encounter_id = 14275))

J’ai suspecté alors un problème de surcharge, et j’ai transformé mon

@encounters = Encounter.all
en
@encounters = Encounter.all(:include => :bodies)

mais cela n’a pas changé grand chose : ça plante toujours avec la
version
originale de mon code. au lieu de planter à la suite d’un select,
çaplante
pendant le rendu (à un endroit indéterminé…)

Par contre, j’avais le même type d’erreur (plantage sur la méthode
designation
avec cascade sur les dates) à un autre endroit de mon application, et
ce plantage
a disparu quand j’ai ajouté les (:include => :bodies)

Même si je me trompe, les points suivants ne feront pas de mal :

  • vérifier la relation entre Body et Encounters, on est bien au
    final sur du 1-N ?

Non. on est sur du N-N (une Encounter contient 2 Bodies et un Body
peut être dans N Encounters)

class Body < ActiveRecord::Base
has_many :bodies_encounters
has_many :encounters, :through => :bodies_encounters

class Encounter < ActiveRecord::Base
has_many :bodies_encounters
has_many :bodies, :through => :bodies_encounters

  • vérifier que tes “include” sont bien en place, ex :
    Body.all(:include => { :bodies_encounters => :encounters })

Pour les .all oui.

  • éviter “self.attributes”

Grande question : pourquoi ?

Note : “b1.class.to_s.eql?(‘Planet’)” peut s’écrire “b1.instance_of?
(Planet)” (voir aussi la méthode “is_a?”)

Merci !