Action Controller

Bonjour,

J’ai un étrange message quand j’essaye de visualiser ma vu contenant ce
code

contenu de votre panier

<% for item in @items product = item.product %> <% end %>
<%= item.quantity %> <%= h(product.title)%> <%=item.unit_price %> <%=item.unit_price * item.quantity %>

voila le message

NoMethodError in Store#display_cart

Showing app/views/store/display_cart.rhtml where line #5 raised:

undefined method `product’ for 5.0:Float

Extracted source (around line #5):

2:


3: <%
4: for item in @items
5: product = item.product
6: %>
7:
8:

RAILS_ROOT:
/Users/bolomichelin/Documents/Creation_Perso/Developement/depot/public/…/config/…

et pourtant quand j’essaye ca
<%= @items.size %>

ca marche

merci

<%= item.quantity %>

Salut,

Il s’agit simplement d’une petit mécompréhension de Ruby :
Ton message derreur est assez clair, il n’y a pas de méthode product
() pour un certain Float. Il n’y a qu’un seul emploie de product() Ã
la ligne 5 (ce qu’il précise d’ailleurs).

Et on voit que c’est la première méthode de ton énumérateur. Et un
énumérateur énumère des tables. @items est une table donc il est
normal qu’elle réponde à size(). item n’est qu’une case de la table
@items. Et il semble bien que ta table soit remplie, sinon du moins
infectée par des Float. Et ça je ne saurais pas te dire pourquoi, le
problème est dans ton controlleur (ou ton modèle mais alors ça
devient louche).

à +
NP

Le 14 août 06 à 17:47, Bolo a écrit :

Il s’agit simplement d’une petit mécompréhension de Ruby :
Ton message derreur est assez clair, il n’y a pas de méthode product()
pour un certain Float. Il n’y a qu’un seul emploie de product() Ã la ligne 5
(ce qu’il précise d’ailleurs).

Pourtant j’ai bien une méthode product
class LineItem < ActiveRecord::Base
belongs_to :product
def self.for_product(product)
item =self.new
item.quantity =1
item.product = product
item.unit_price = product.price
item
end
end
http://lists.rubyonrails.fr/mailman/listinfo/railsfrance
Merci pour tes explications

Salut Bolo !

Tu as mis une methode product() sur un Float, pas sur un LineItem.

Tu as dans ta vue item.product (l.5). Or Ruby te dit que item est un
Float. Et toi tu penses encore que c’est une instance de LineItem. Tu
as bien une méthode product() pour LineItem mais tu n’a pas affaire
avec un LineItem :). Ce qui veut dire que @items est une table
composé de Float (ou de quelques autres bizarreries) ; @items ne
comporte pas la bonne collection d’objets (des instances de
LineItem). En fait je ne comprends pas ton code. Qu’y a-t-il dans ton
contrôleur ??

En tout cas, vraiment, prend 3 heures, 3 heures suffisent, pour
apprendre à tester (en tout cas du test unitaire, bien que là je ne
comprennes pas trop d’où vient l’erreur…). Tu verras que ça ne
prend pas plus de temps et que tu ne te retrouvera pas avec un Float
à la place d’un LineItem dans ta vue. Si tu commences pas apprendre
l’unitaire, tu auras rapidement envie de faire du fonctionnel et
enfin passer au top inclus dans rails, le test d’intégration.

C’est assez emmerdant toutes ces personnes qui parlent de tests quand
on en fait pas, on sent bien que ça doit être bien de tester mais ça
paraît chiant de devoir tester, il faut le dire. Mais je suis un
converti récent, et donc pas encore un emmerdeur fini. Dès que je me
mets à coder sans test maintenant, je perds pied, je ne sais plus
trop où j’en suis et surtout je ne sais pas où je vais. On est
tellement plus serein avec des tests !!! Quand on teste on sait où
l’on va, on voit ce qui marche et ne marche pas et ce qui pourrait
marcher mieux. Au final on ne réécrit pas 5 fois son vrai code parce
qu’on n’arrive pas à faire ce qu’on veut ou parce que ça marche pas etc.

Voici en gros l’idée d’un test : on sait ce qu’on a au départ et on
sait ce qu’on veut à l’arrivée. Entre le départ et l’arrivée, il y a
le code de l’application. Designer par des tests c’est définir ce que
l’on a au départ et ce que l’on compte avoir à l’arriver. Ca permet
de mettre en mot, concrètement, notre conception cérébrale du
problème. Et ce n’est qu’en devenant réel que l’on découvre les
problèmes de nos concepts (qui marchent toujours très bien dans notre
tête !)

Le test unitaire (unit) teste les modèles. Si les modèles sont HS,
comment est-ce que les contrôleurs (et encore plus les vues) peuvent
marcher ?? Après, on monte d’un niveau, on a les tests fonctionnels
(functional), qui testent les contrôleur, un par un (on test toutes
les conditions, les variables…) Et enfin on a les test
d’intégration au plus haut niveau d’abstraction. Là on construit des
scénarios d’utilisation possible de du site (machin arrive se
connecte se trompe de mot de passe recommence, va voir son compte,
change son mot de passe, va à la boutique, achète ça, achète une
deuxième fois la même chose…) On vérifie, les interactions entre
les contrôleurs, les variables de session, les routes etc…

Bon, c’est pas très compliqué tout ça, mais après on est beaucoup
plus tranquille.
J’espère pouvoir aider quelque uns à franchir le pas. Si certains
souhaitent d’autres renseignement qu’il n’hésitent pas.

Bonne chance.
NP

P.S. :

def self.for_product(product)
item =self.new
item.quantity =1
item.product = product
item.unit_price = product.price
item
end
Attention aussi : tu ne save() pas ton item, peut-être une autre
source possible de problèmes.

Le 14 août 06 à 22:20, Bolo a écrit :

Salut Nicolas,

Par raport à mon problème j’ai recommecé depuis le début. En fait je
suis le tuto du Livre ruby on rails

En tout cas, vraiment, prend 3 heures, 3 heures suffisent, pour apprendre à tester (en tout cas du test unitaire, bien que là je ne comprennes pas trop d’où vient l’erreur…). Tu verras que ça ne prend pas plus de temps et que tu ne te retrouvera pas avec un Float à la place d’un LineItem dans ta vue. Si tu commences pas apprendre l’unitaire, tu auras rapidement envie de faire du fonctionnel et enfin passer au top inclus dans rails, le test d’intégration.

Non je suis tout a fait pour pour les test ce que je fais en général
quand je code dans un autre langage. Mais la je suis pas encore arrivé
a ce chapitre :slight_smile:
J’essaye de faire des tests de changer mon code, de vérifier si j’ai
pas oublié une lettre mais la j’avoue que je sèche :frowning:

P.S. :

def self.for_product(product)
item =self.new
item.quantity =1
item.product = product
item.unit_price = product.price
item
end
Attention aussi : tu ne save() pas ton item, peut-être une autre source possible de problèmes.

Pourtant c’est le code exact dans le bouquin. tout fonctionner a peu
pres jusqu’a que j’atoute la fonction pour vider le panier et que je
la teste maintenant. je ne pluis ajouter aucun objet dans le panier
j’ai ce message

NoMethodError in Store#display_cart

Showing app/views/store/display_cart.rhtml where line #21 raised:
You have a nil object when you didn’t expect it! The error occured
while evaluating nil.product

Extracted source (around line #21): 18:

total 19:
20: <% for item in @items 21: product = item.product %> 22:
23: <%= item.quantity %> 24: <%=
h(product.title)%>

RAILS_ROOT: /Users/expay/Documents/work/depot/public/…/config/…
The error occured while evaluating nil.product

J’ai pourant bien une méthode display_cart dans mon controller Store.
Quand je désactive la redirection vers la vue display_cart j’ai ce
message d’erreur

class StoreController < ApplicationController

def index
@products = Product.salable_items
end

def add_to_cart
product = Product.find(params[:id])
@cart =find_cart
@cart.add_product(product)
redirect_to :action => “display_cart”
rescue
logger.error (“Tentative d’acces un produit invalide
#{params[:id]}”)
flash[:notice] = “Produit invalide”
redirect_to :action => “index”
end

def display_cart
@cart = find_cart
@items = @cart.items
if @items.empty?
flash[:notice] = “Votre panier est actuellement vide”
redirect_to :action => “index”
end
end

def empty_cart
find_cart.empty!
flash[:notice] = “votre panier est actuellement vide”
redirect_to :action => “index”
end

private
def find_cart
session[:cart] ||= Cart.new
end
end