Scaffold : Je ne comprends pas

Bonjour,
Voila j’epeluchais le code des scaffold genere par Rails, j’ai tout
compris a part 1 detail …

Cela concerne l’action new :
Je vois dans le controller , dans l’action new, l’instanciation de
l’objet, jusqu’a la c’est normal, dans la view, rien de special, ma
question est :
Pourquoi quand je soumets le formulaire, ca passe dans l’action create,
alors que dans la view, il n’y a aucune reference a Create …
J’ai chercher partout, dans les routes et tout je ne trouve rien …

Je vous mets le code de l’action new et create, si ca peut vous aider…

GET /products/new

GET /products/new.xml

def new
@product = Product.new

respond_to do |format|
  format.html # new.html.erb
  format.xml  { render :xml => @product }
end

end

POST /products

POST /products.xml

def create
@product = Product.new(params[:product])

respond_to do |format|
  if @product.save
    flash[:notice] = 'Product was successfully created.'
    format.html { redirect_to(@product) }
    format.xml  { render :xml => @product, :status => :created,

:location => @product }
else
format.html { render :action => “new” }
format.xml { render :xml => @product.errors, :status =>
:unprocessable_entity }
end
end
end

Je vous remercie d’avance, je commence a devenir fou la ^^

ça passe dans create car avec rails et REST tu es orienté vers les
actions en fonction de la méthode d’envois des données.

et donc par défaut avec le scaffold de rails:
get => index
post => create
put => update
delete => destroy

dans ta vue je suppose que tu as donc un formulaire, avec comme
adresse d’envois product_path probablement.

Rails sait donc qu’il doit aller dans le controller product, et comme
un formulaire est un post par défaut, ça par dans l’action create

Aurélien Bottazini
http://www.mycashgarden.com

Merci a vous pour vos reponses, effectivement ca me parait plus clair,
neanmoins, j’ai encore 2 questions :

  1. Peut etre une question idiote, mais c’est quoi une instance “AR::B” ?
    AR est une class ?
    C’est la premiere fois je vois ce terme

  2. A quel moment Rails test @product.new_record? ?
    Au moment ou l’ont soumis le formulaire ?

Merci.

Le 14 juin 2008 18:42, Alfref B. a écrit :

alors que dans la view, il n’y a aucune reference a Create …
J’ai chercher partout, dans les routes et tout je ne trouve rien …

Je vous mets le code de l’action new et create, si ca peut vous aider…

GET /products/new

GET /products/new.xml

def new
@product = Product.new

1/ Dans le cas où on a un nouvel enregistrement @product = Product.new

Dans la vue correspondante, tu as un formulaire :

form_for(@product) do |f|

end

Quand tu ne passes qu’une instance AR::B en argument à form_for,
celui-ci va utiliser les conventions de Rails pour déduire l’url et le
verbe HTTP adapté. Rails va le déduire depuis l’objet @product.

  • Pour le verbe HTTP, il le détermine en faisant @product.new_record?.
    Rails sait alors s’il a affaire à un produit déjà existant dans la
    base ou fraîchement créé. Donc là, @product.new_record? renvoie true
    et Rails décide d’avoir un POST ( :method => :post ) .

  • Pour l’url, il va passer par la méthode #polymorphic_path(@product)
    qui va appeler le path helper #products_path. On aura donc ‘/products’.
    (il sait qu’il faut appeler products_path car @product est un objet
    de classe Product donc Rails se doute que le nom de la ressource
    utiliséeest ‘product’ (c’est le boulot du module
    ActionController::RecordIdentifier).
    En suivant encore les conventions de rails, on a un nouveau produit,
    donc
    il va prendre le path helper #products_path plutôt que #product_path)

Finalement le formulaire, une fois validée, enverra bien ses données
en faisant un POST /products, ce qui en suivant les conventions REST
de Rails (car on a fait un map.resources :product dans
config/routes.rb),
dirigera la requête vers l’action ProductsController#create.

2/ Dans le cas où on a @product = Product.find params[:id], donc
dans le cas d’une édition d’un enregistrement, on aura cette fois-ci :

  • Pour le verbe HTTP, @product.new_record? retourne false, donc
    Rails utilisera le verbe PUT ( :method => :put).

(plus exactement, le PUT sera simulé par une requête POST
avec un champ caché avec le paramètre _method=put
(et Rails sait reconnaître cette pseudo-requête POST en requête PUT))

  • Pour l’url, polymorphic_path(@product) appellera cette fois-ci
    le path helper #product_path avec le bon argument (@product), soit
    product_path(@product), c’est-à-dire ‘/products/42’ (par exemple).

Finalement, on fera un PUT /products/42 quand on validera le formulaire,
et d’après les conventions REST de Rails, Rails traitera la
requête par l’action ProductsController#update.

Conclusion : le form_for(@product) a l’air un peu magique comme ça,
mais au final, pas tant que ça.

– Jean-François.


http://twitter.com/underflow_

Ha oui ok
C’est ce que je me disais aussi, mais je comprenais pas comment il fait
pour savoir si c’est pour la methode create, alors que l’ont pas encore
rempli le formulaire…
Mais je viens de comprendre que c’est grace a l’instanciation dans la
methode new qui contient un objet vide :slight_smile:

Merci

Le 15 juin 2008 18:28, Alfref B. a écrit :

Merci a vous pour vos reponses, effectivement ca me parait plus clair,
neanmoins, j’ai encore 2 questions :

  1. Peut etre une question idiote, mais c’est quoi une instance “AR::B” ?
    AR est une class ?
    C’est la premiere fois je vois ce terme

AR::B = ActiveRecord::Base
AC::B = ActionController::Base
AV::B = ActionView::Base
ARes::B = ActiveResource::Base
AM::B = ActionMailer::Base

AWS = ActionWebService
AS = ActiveSupport

  1. A quel moment Rails test @product.new_record? ?
    Au moment ou l’ont soumis le formulaire ?

Non, au moment où la vue est générée, puisque l’url et le verbe HTTP
ont besoin d’être spécifiés dans le code HTML de ton formulaire.

– Jean-François.


http://twitter.com/underflow_

Je crois que l’a tout est clair :slight_smile:
Merci, j’avais des lacunes sur le REST :slight_smile:

Le 15 juin 2008 18:42, Alfref B. a écrit :

Ha oui ok
C’est ce que je me disais aussi, mais je comprenais pas
comment il fait pour savoir si c’est pour la methode create,
alors que l’ont pas encore rempli le formulaire…

Le client web n’a pas besoin de le savoir, on fait du REST,
à partir du moment où il fait une requête POST /products
pour un nouveau produit, ça roule.

Ensuite, quand Rails voit une requête POST /products,
il sait que c’est ProductsController#create qui va traiter
la requête, car tu as spécifié map.resources :products
dans config/routes.rb et que tu suis les conventions de
Rails concernant la manière dont REST est traité par Rails.

rake routes te montre que tu as une route :

POST /products {:controller=>“products”, :action=>“create” }

Et donc par convention, c’est l’action create qui s’en charge.

Alors par convention, l’action aurait très bien pu s’appeler
van_nistelrooy_enrhume_la_defense_francaise

Il aurait fallu définir la route :

POST /products {:controller=>“products”,
:action=>“van_nistelrooy_enrhume_la_defense_francaise” }

Pour PUT /products/42, c’est pareil, ç’aurait pu être
la route :

PUT /products/:id {:controller=>“products”,
:action=>“benzema_n_est_pas_rentre_sur_le_terrain” }

mais la convention choisie, va savoir pourquoi, est la route :

PUT /products/:id {:controller=>“products”, :action=>“update” }

Mais je viens de comprendre que c’est grace a l’instanciation dans la
methode new qui contient un objet vide :slight_smile:

La notion d’objet vide n’a pas grand sens, sauf si tu définis #empty?
sur ton objet ou si tu utilises des objets conteneurs comme
des instances de Hash, Array, Set…

#new_record? indique si l’objet est neuf ou s’il a déjà été sauvé dans
la base de données, ce n’est pas la même chose.

– Jean-François.


http://twitter.com/underflow_