Forum: Rails France Variable d'instance non definie dans la Vue

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
C800c36d051cb46d6d801e1b48685ca6?d=identicon&s=25 Paul Muaddib (orion98)
on 2009-04-01 10:40
Bonjour,

J'ai un soucis dans une appli rails.
Je defini une variable d'instance dans la methode new()  et edit() du
controller qui sert a construire un select() dans la vue:

class WorksController < ApplicationController
[...]

def new
    @task = Task.new
    @parents_ids = [["(No parent)",0]] + Task.find(:all, :order =>
"name").map {|p| [p.name, p.id]}
end

def edit
    @task = Task.find(params[:id])
    @parents_ids = [["(No parent)",0]] + Task.find(:all, :order =>
"name").map {|p| [p.name, p.id]} - [[@task.name, @task.id]]
end

[...]
end

Le model est simplement:
class Task < ActiveRecord::Base
  acts_as_tree  :order => "id"
  has_many :runtimes
  belongs_to :people
end

Et voici le bout de code qui l'utilise pour construire le select dans la
vue (un render partial utilisé pour new et edit):
    <td><%=
      logger.info "New task: ==#{@task}== >>#{@parents_ids}<<"
      select(:task, :parent_id, @parents_ids)
    -%>
    </td>

Jusqu'ici tout fonctionne parfaitement. En faisant un new ca marche j'ai
bien ma liste de choix dans la vue qui s'affiche et je peux creer des
enregistrements.

Mais alors je decide de rajouter une validation dans le model:

  validates_presence_of :name

Et a partir de ce moment la, si je tente de creer une nouvelle task sans
nom, j'ai l'erreur suivante a la soumission:

Showing app/views/works/_form.rhtml where line #9 raised:

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.inject
Extracted source (around line #9):

6:     <td><label for="parent_id">Parent: </label></td>
7:     <td><%=
8:       logger.info "New task: ==#{@task}== >>#{@parents_ids}<<"
9:       select(:task, :parent_id, @parents_ids)
10:     -%>
11:     </td>
12:   </tr>

Et effectivement dans le log @parents_ids est vide !!?
Par contre @task a une valeur.

Pourquoi cette variable n'a t-elle pas de valeur alors qu'elle est
definie dans le controller pour new() tout comme @task d'ailleurs ?

Regards,
Thierry
059ed46172a087063ce26250e44c8627?d=identicon&s=25 Fernando Perez (fernando)
on 2009-04-01 10:57
> def new
>     @task = Task.new
>     @parents_ids = [["(No parent)",0]] + Task.find(:all, :order =>
> "name").map {|p| [p.name, p.id]}
> end

Bonjour, le code de tes controlleurs pique les yeux, ça n'a rien à faire
ici, idem pour le logger.info, qu'est-ce qu'il fabrique dans la view?

Il faut nettoyer tout ça.
C800c36d051cb46d6d801e1b48685ca6?d=identicon&s=25 Paul Muaddib (orion98)
on 2009-04-01 11:11
Fernando Perez wrote:
> Bonjour, le code de tes controlleurs pique les yeux, ça n'a rien à faire
> ici,
Il faut mettre ca ou alors ? dans la vue ?

> idem pour le logger.info, qu'est-ce qu'il fabrique dans la view?
Ca je l'ai mis juste pour debugger mais sinon quelle est la maniere la
plus propre pour le faire ?

Merci de ta reponse.

Thierry
059ed46172a087063ce26250e44c8627?d=identicon&s=25 Fernando Perez (fernando)
on 2009-04-01 11:19
> Il faut mettre ca ou alors ? dans la vue ?
Dans le Model.

> Ca je l'ai mis juste pour debugger mais sinon quelle est la maniere la
> plus propre pour le faire ?
ruby-debug
C800c36d051cb46d6d801e1b48685ca6?d=identicon&s=25 Paul Muaddib (orion98)
on 2009-04-01 11:25
Fernando Perez wrote:
> Dans le Model.
Je croyais que le model ne devait contenir que les informations du model
!?
Ca c'est pas une information de model ni une validation. Je me trompe ?

> ruby-debug
Peux tu etre plus precis avec un exemple ?

Merci de ta reponse.
Thierry
13de37c0466c10344a11a7e1f7a64c63?d=identicon&s=25 Constantin Gavrilescu (Guest)
on 2009-04-01 17:46
(Received via mailing list)
2009/4/1 Paul Muaddib <list-incoming@andreas-s.net>

> You have a nil object when you didn't expect it!
> 12:   </tr>
>
> Et effectivement dans le log @parents_ids est vide !!?
> Par contre @task a une valeur.



Ajoutez-vous ce ligne dans *create* dans le controller:
@parents_ids = [["(No parent)",0]] + Task.find(:all, :order =>
"name").map
{|p| [@p.name, @p.id]}
C800c36d051cb46d6d801e1b48685ca6?d=identicon&s=25 Paul Muaddib (orion98)
on 2009-04-01 19:27
Constantin Gavrilescu wrote:
> Ajoutez-vous ce ligne dans *create* dans le controller:
> @parents_ids = [["(No parent)",0]] + Task.find(:all, :order =>
> "name").map
> {|p| [@p.name, @p.id]}

Merci Constantin,
Ca marche maintenant !

Thierry
059ed46172a087063ce26250e44c8627?d=identicon&s=25 Fernando Perez (fernando)
on 2009-04-01 20:38
> Ca marche maintenant !
>
> Thierry

Même si ça marche pensez à nettoyer le code, ça va vite devenir une
plaie à maintenir si ça ne l'est pas déjà.
C800c36d051cb46d6d801e1b48685ca6?d=identicon&s=25 Paul Muaddib (orion98)
on 2009-04-02 09:43
Fernando Perez wrote:
> Même si ça marche pensez à nettoyer le code, ça va vite devenir une
> plaie à maintenir si ça ne l'est pas déjà.

J'ai tout enlevé du controlleur ca devrait aller là non ?

Model:
class Task < ActiveRecord::Base
  acts_as_tree  :order => "id"
  has_many :runtimes
  belongs_to :people
  validates_presence_of :name

  def self.names_for_ids(prompt = ["Choose...", 0], current = [])
    [prompt] + self.find(:all, :order => "name").map {|p| [p.name,
p.id]} - current;
  end
end

View:
[...]
  <td><label for="parent_id">Parent: </label></td>
    <td><%= select(:task, :parent_id, Task.names_for_ids(["(No parent)",
0], [@task.name, @task.id])) -%>
    </td>
[...]

Merci de ta reponse.
Thierry
This topic is locked and can not be replied to.