Variable d'instance non definie dans la Vue

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):

<%=
logger.info “New task: ==#{@task}== >>#{@parents_ids}<<”
select(:task, :parent_id, @parents_ids)
-%>

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:

Parent:
7: <%=
8: logger.info “New task: ==#{@task}== >>#{@parents_ids}<<”
9: select(:task, :parent_id, @parents_ids)
10: -%>
11:
12:

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

Fernando P. 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

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.

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

Fernando P. 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

2009/4/1 Paul M. [email protected]

You have a nil object when you didn’t expect it!
12:

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]}

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à .

Constantin G. 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

Fernando P. 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:
[…]

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

Merci de ta reponse.
Thierry