Update automatico di un campo

Vorrei che al momento della creazione di un nuovo oggetto venisse
valorizzato automaticamente uno dei suoi attributi.
I modelli in questione sono settori e categorie, in relazione uno a
molti.
Il partial della view per la categoria e’:

<%= f.collection_select :sector_id, @sectors, :id, :name, :prompt =>
“seleziona il settore” %>
<%= f.label :descrizione %>

<%= f.text_field :descr %>
<%= f.label :esempi %>

<%= f.text_area :example %>
<%= f.submit label_text %>

in questo modo la categoria e’ associata ad un settore.
La categoria contiene un attributo codice che vorrei venisse
valorizzato automaticamente col valore dell’attributo codice del
settore.
Banalmente nel controller avevo fatto:

def create
@category = Category.new(params[:category])
@sectors = Sector.find(:all)
@category.code = @sectors[params[:category][:sector_id].to_i]

pero’ al codice della categoria viene assegnato un valore che non
corrisponde a quello del codice del settore selezionato nella select.
Logicamente mi sembrava corretto ma evidentemente non lo e’.

Il 17 dicembre 2009 13.03, Mauro [email protected] ha scritto:

<%= f.text_area :example %>
def create
@category = Category.new(params[:category])
@sectors = Sector.find(:all)
@category.code = @sectors[params[:category][:sector_id].to_i]

pero’ al codice della categoria viene assegnato un valore che non
corrisponde a quello del codice del settore selezionato nella select.
Logicamente mi sembrava corretto ma evidentemente non lo e’.

Il motivo per cui non funziona è che tu speri che gli id siano tutti
consecutivi e senza buchi, ma non è detto che sia così; inoltre, tu
speri che il primo id sia zero, ma qui avrai una grossissima
delusione.

Farsi passare tutti i record per guardarne solo uno è sconsigliato;
anche ridefinire create può avere i suoi svantaggi.

Ti consiglio di usare before_save o before_validation, dipende se fai
validazione e come:

before_save do |c|
c.code = c.sector && c.sector.code
end

(Nota che, se sector vale null, code viene impostato a null).

pietro

2009/12/17 Pietro G. [email protected]:

<%= f.label :esempi %>

consecutivi e senza buchi, ma non è detto che sia così; inoltre, tu
speri che il primo id sia zero, ma qui avrai una grossissima
delusione.

Se nella select seleziono il settore da associare alla categoria e, al
submit, i parametri passati sono:

“category”=>{“sector_id”=>“1”,
“descr”=>“bbbbb”,
“example”=>“”},
“commit”=>“Crea”}

facendo @category.code =
@sectors[params[:category][:sector_id].to_i].code sto andando a
prendere il valore dell’attributo code del settore con indice 1.
Sbaglio?
E invece nel code della categoria mi trovo un valore diverso.

2009/12/17 Pietro G. [email protected]:

@sectors[params[:category][:sector_id].to_i].code sto andando a
prendere il valore dell’attributo code del settore con indice 1.
Sbaglio?
E invece nel code della categoria mi trovo un valore diverso.

Esattamente; e poiché gli id partono da 1 mentre gl’indici degli array
partono da 0, è molto probabile che “sfori”, ottenendo un
NoMethodError, perché se a è un array di 10 elementi, a[10] è nil.

Si lo so ma lo sforamento nel mio caso non e’ di 1, se il paramentro
passato e’ “category”=>{“sector_id”=>“1”,
@category.code = @sectors[params[:category][:sector_id].to_i].code mi
da 13, e’ questo che non capisco.

Il 17 dicembre 2009 13.18, Mauro [email protected] ha scritto:

prendere il valore dell’attributo code del settore con indice 1.
Sbaglio?
E invece nel code della categoria mi trovo un valore diverso.

Esattamente; e poiché gli id partono da 1 mentre gl’indici degli array
partono da 0, è molto probabile che “sfori”, ottenendo un
NoMethodError, perché se a è un array di 10 elementi, a[10] è nil.

pietro

2009/12/17 Mauro [email protected]:

I modelli in questione sono settori e categorie, in relazione uno a molti.
immagino quindi che

Category belongs_to :sector
Sector has_many :categories

La categoria contiene un attributo codice che vorrei venisse
valorizzato automaticamente col valore dell’attributo codice del
settore.

quindi vuoi che sia sempre

category.code === category.sector.code

Se non hai esigenze particolari che ti portano a volere la
“denormalizzazione” del dato perche’ non togli il campo code dalla
category ed deleghi il code al sector? (per sapere come si fa vedi ad
esempio quest’articolo recente di simone:

)

def create
@category = Category.new(params[:category])
@sectors = Sector.find(:all)
@category.code = @sectors[params[:category][:sector_id].to_i]

ma qui assegni al code il sector e non il valore del suo campo code…
invece dell’ultima riga potresti fare (togliendo anche la
Sector.find(:all)) :

@category.code = @category.sector.code

ciao,
Luca

2009/12/18 Luca M. [email protected]:

ma qui assegni al code il sector e non il valore del suo campo code…
invece dell’ultima riga potresti fare (togliendo anche la Sector.find(:all)) :

La Sector.find.all mi serve unicamente per popolare la select

<%= f.collection_select :sector_id, @sectors, :id, :name, :prompt =>
“seleziona il settore” %>
<%= f.label :descrizione %>

<%= f.text_field :descr %>
<%= f.label :esempi %>

<%= f.text_area :example %>
<%= f.submit label_text %>

E’ scorretto?

2009/12/18 Mauro [email protected]:

2009/12/18 Luca M. [email protected]:

ma qui assegni al code il sector e non il valore del suo campo code…
invece dell’ultima riga potresti fare (togliendo anche la Sector.find(:all)) :

La Sector.find.all mi serve unicamente per popolare la select

E’ scorretto?

no, e’ giusto, immagino che tu lo faccia anche nella action new, e poi
ti serva nuovamente nella create per consentirti di fare il render
della pagina.
Potresti evitarlo se facessi il render della pagina con la form solo
in caso di errori (i.e. popoleresti @sectors solo se non riuscissi a
salvare la @category).

Luca

2009/12/18 Luca M. [email protected]:

no, e’ giusto, immagino che tu lo faccia anche nella action new,
Si e’ un partial usato nella new e nella edit.

2009/12/18 Luca M. [email protected]:

quindi vuoi che sia sempre

category.code === category.sector.code

Semplificando si, in realta’ il category.code dovrebbe essere uguale
al category.sector.code piu’ un progressivo, es:
se il category.sector.code e’ “A” il category.code dovrebbe essere
“A01” o “A02” o “A22” per intenderci un progressivo per ogni categoria
appartenenete ad un determinato settore, avrei quindui anche “B01” o
“L01”.
Per ottenere il progressivo pensavo di fare un
#{category.sector.categories.count+1}".to_s.rjust(2,‘0’).

Il 17 dicembre 2009 23.20, Mauro [email protected] ha scritto:

Si lo so ma lo sforamento nel mio caso non e’ di 1, se il paramentro
passato e’ “category”=>{“sector_id”=>“1”,
@category.code = @sectors[params[:category][:sector_id].to_i].code mi
da 13, e’ questo che non capisco.

Ciao,

lancia la console di rails ( script/console da mac e linux, ruby
script\console da windows); prova il codice una riga alla volta, forse
avrai lumi.

In particolare:

@sectors[1].code che valore ti
dà?

pietro