User.find avec conditions retourne "Couldn't find User witho

Bonjour,

C’est mon premier message sur la liste, et c’est ma première semaine de
programmation avec Ruby on Rails.

Dans mon application, j’ai des Users pour lesquels sont renseignés 2
champs nommés “latitude” et “longitude”. Je souhaite sélectionner les
users qui ont leur latitude comprise entre 49.00 et 60.00. Pour ce
faire, j’ai ceci dans app/helpers/user_helper.rb:

57: def find_nearest_users(user_latitude, user_longitude)
58:   return User.find(:conditions => [ "latitude BETWEEN ? AND ?",
49.00, 60.00 ], :limit => 5)
59: end

Et dans app/views/user/show.rhtml, je récupère les users trouvés pour
afficher diverses infos:

<% for nearest_user in find_nearest_users(@user.latitude,
@user.longitude) %>
  <%= nearest_user.id %><br />
<% end %>

Et le résultat est l’erreur suivante:

ActionView::TemplateError (Couldn't find User without an ID) on line
#57 of app/views/user/show.rhtml

Il y a bien 2 users dans la DB qui ont leur “latitude” comprise entre
49.00 et 60.00.
Où est mon erreur?

Cordialement,

Michael

Le Jeu 5 octobre 2006 16:54, Michael H. a écrit :

j’ai ceci dans app/helpers/user_helper.rb:

57: def find_nearest_users(user_latitude, user_longitude)
58:   return User.find(:conditions => [ "latitude BETWEEN ? AND ?",
49.00, 60.00 ], :limit => 5)
59: end

Ce que tu cherche n’est un find(:all, :conditions => [ “latitude BETWEEN
?
AND ?”, 49.00, 60.00 ], :limit => 5) ?

En premier argument il attend :

  • un identifiant de clé primaire
  • ou un tableau d’identifiants de clé primaire
  • ou :first
  • ou :all

Dans ton cas c’est :all

Sinon, si je puis me permettre, tu devrais simplifier tes noms de
variables et tes noms de méthode (sauf si ton cas est plus complexe que ce
que tu nous montre).

Il serait par exemple avantageux de pouvoir faire dans ta vue quelque
chose du style :

<% for neighbour in nearest_users(@user.latitude,@user.longitude) %>
<%= neighbour.id %>

<% end %>

Au lieu de dire “pour chaque utilisateur_le_plus_proche dans
recherche_les_utilisateurs_les_plus_proches …”, tu as un “pour chaque
voisin dans les utilisateurs les plus proches …”. Ca devrait être plus
simple et naturel à lire/utiliser.

Tu peux te passer du préfixe “find_” pour le nom de ta fonction. Si tu
posais une question ou si tu voulais faire une assignation (un set), tu
aurais de toutes façons avantage à avoir un suffixe “?” ou “=” sur le nom
de la méthode. Tu sais donc que tu vas faire une récupération (get, find,
ou similaire). Le fait que ce soit une recherche, un calcul, ou une
variable directe, c’est la sauce interne de la méthode, tu n’as pas besoin
de le savoir en l’appelant, tu n’as donc pas besoin de le mettre dans le
nom.
Récap de ce que ça peut donner :

def nearest_users(user_latitude, user_longitude)
User.find( :all,
:conditions => [ “latitude BETWEEN ? AND ?”, 49.00, 60.00
],
:limit => 5
)
end

  • et *

<% for neighbour in nearest_users(@user.latitude,@user.longitude) %>
<%= neighbour.id %>

<% end %>


Eric D.

Bonjour,

C’est mon premier message sur la liste, et c’est ma première semaine de
programmation avec Ruby on Rails.

Bonjour et bienvenu!

Dans mon application, j’ai des Users pour lesquels sont renseignés 2

champs nommés “latitude” et “longitude”. Je souhaite sélectionner les
users qui ont leur latitude comprise entre 49.00 et 60.00. Pour ce
faire, j’ai ceci dans app/helpers/user_helper.rb:

57: def find_nearest_users(user_latitude, user_longitude)
58:   return User.find(:conditions => [ "latitude BETWEEN ? AND ?",
49.00, 60.00 ], :limit => 5)
59: end

Quand find est appelé avec un unique paramètre, ActiveRecord considère
que
c’est son ID.

Si tu souhaites obtenir tous les enregistrements qui vérifient ces
conditions, il faut utiliser:

User.find(:all,:conditions => [ “latitude BETWEEN ? AND ?”, 49.00, 60.00
],
:limit => 5)

Si tu veux uniquement le premier:

User.find(:first,:conditions => [ “latitude BETWEEN ? AND ?”, 49.00,
60.00], :limit => 5)

a+!

Thibaut

Quand find est appelé avec un unique paramètre, ActiveRecord considère que
c’est son ID.

Je m’autofouette pour la coquille, sur ce point précis c’est faux bien
sûr
(on peut aussi appeler avec :first, :all etc en paramètre unique).

Pour tous les détails:
http://ar.rubyonrails.com/classes/ActiveRecord/Base.html#M000344

a+

Thibaut