JeuWeb - Crée ton jeu par navigateur

Version complète : [Rails] Problème après rechargement de formulaire avec autocomplétion en cas d'erreur
Vous consultez actuellement la version basse qualité d’un document. Voir la version complète avec le bon formatage.
Bonjour à tous (et surtout à Sephi ConfusediffleSmile

Je dois vraiment être une quiche et faire (encore) n'importe quoi...

donc tout d'abord un peu de code :

La vue

%h1= "Nouveau Message"

= form_for @message do |f|
%p.double
= f.label :receiver
= f.text_field :receiver
= show_errors_message(@message.errors[:receiver])
%p.double
= f.label :title
= f.text_field :title
= show_errors_message(@message.errors[:title])
%p.double
= f.label :body
= f.text_area :body
= show_errors_message(@message.errors[:body])

= f.submit

Le modèle

class Message < ActiveRecord::Base
belongs_to :author, :class_name => "User", :foreign_key => "author_id"
belongs_to :receiver, :class_name => "User", :foreign_key => "receiver_id"

validates_presence_of :author, :receiver, :title, :body
end
et enfin, la méthode create de mon controlleur

def create
username = params[:message][:receiver]
params[:message][:receiver] = User.find_by_username(username)
@message = Message.new params[:message]
@message.author = current_user
if @message.save
redirect_to messages_path
else
render 'new'
end
end

Je passe sur le javascript (auto_completion) qui me remplie le champ "receiver".
Quand on remplit correctement le formulaire, tout se passe bien. par contre si je remplis le champ receiver et pas le reste, le formulaire n'est pas validé et au moment de réafficher le formulaire, le champ receiver vaut quelque chose du style #<User:0x286b870>! Alors, je comprends bien pourquoi mais je ne trouve pas comment le corriger... (J'ai fait pas mal de test en bidouillant mais rien n'a réellement fonctionné)
Premièrement, tu peux changer ton modèle pour :


class Message < ActiveRecord::Base
belongs_to :author, class_name: "User"
belongs_to :receiver, class_name: "User"

validates_presence_of :author, :receiver, :title, :body
end

En effet, les foreign keys sont devinées depuis le nom de l'association.


Ensuite, ton problème survient parce que ton champ de formulaire accepte un objet User et que tu y demandes une chaîne de caractère. le type de champ n'est pas très fidèle à son contenu.
Ca, je l'ai bien compris! Par contre, je suis obligé de travailler sur une chaine de caractère dans ce champ à cause de l'autocomplétion... C'est pour ça que je récupère un objet User via la chaine de caractère. Le problème est que je ne peux pas faire marche arrière (remettre du texte) dans ce champ en cas d'erreur...
Je dois mal faire quelque chose...
Tu peux fonctionner avec un id puisque le véritable attribut est receiver_id : les scripts d'autocompletion (genre jQuery UI Autocomplete) permettent d'avoir une valeur (dans ton cas, l'id) et un libellé (le nom de l'utilisateur).

Dans tous les cas, je pense que tu auras besoin d'avoir un affichage différent lors de l'échec de validation. Par exemple en cas d'erreur de validation sur le receiver_id, tu as affiches le champ avec l'auto-complétion comme tu le faisais avant que la validation n'échoue, sinon tu le préremplis.

A voir selon ce que tu as client side. Smile
(02-11-2011, 12:55 PM)Sephi-Chan a écrit : [ -> ]Dans tous les cas, je pense que tu auras besoin d'avoir un affichage différent lors de l'échec de validation. Par exemple en cas d'erreur de validation sur le receiver_id, tu as affiches le champ avec l'auto-complétion comme tu le faisais avant que la validation n'échoue, sinon tu le préremplis.

Et c'est bien là mon problème... :langue2:
En gros :


class MessagesController < ApplicationController
def new
@message = Message.new
end

def create
receiver_name = params.delete(:receiver_name)
@message = Message.new(params[:message])
@message.receiver = User.find_by_name(receiver_name)

if @message.save
redirect_to @message
else
render :new
end
end
end


Et la vue :


= form_for @message do |f|
%p
= label_tag :receiver_name
= text_field_tag :receiver_name, f.object.receiver.try(:name)
= errors_for(f.object, :receiver_name)

%p
= f.label :content
= f.text_area :content
= errors_for(f.object, :content)

%p
= f.submit


En fait je vire l'archive, ces fragments suffisent.
nickel, merci beaucoup, reste plus qu'a ajouté un message d'erreur adéquat et ca sera parfait
En fait, tu affiches l'erreur pour l'attribut receiver et ça marche. Smile
Tu veux dire quoi par "ça marche"? J'ai un message pour me dire que le champ est vide mais qu'il ne le doit pas, moi j'aimerai ajouter un message pour dire que le nom saisi n'est pas valide.
Ben, tu ajoutes un validateur sur le receiver au niveau de ton modèle :


class Message < ActiveRecord::Base
belongs_to :author, class_name: "User"
belongs_to :receiver, class_name: "User"

validates_presence_of :author, :receiver, :title, :body
validate :receiver_exists


def receiver_exists
errors[:receiver_id] << :inclusion unless User.exists?(id: receiver_id)
end
end