2013-08-22 15 views
36

Questa potrebbe essere più una domanda ruby ​​quindi domanda di rails ma sono abbastanza sicuro di essere stato in grado di farlo in un'applicazione di rubino alla vaniglia.Modifica hash rubino in posizione (parametri forti rotaie)

Ho definito parametri forti.

def trip_params 
    params.require(:trip).permit(:name, :date) 
end 

Ora ottengo quei parametri in un metodo di controllo. Voglio farlo.

def save 
    trip_params[:name] = 'Modifying name in place' 
    #trip_params[:name] still equals original value passed 
end 

Questo non funziona mai. Il nome non cambia mai. BTW: Il tipo di trip_params è ActionController :: Parametri

Se eseguo uno script ruby ​​standard, funziona.

test = {}  
test[:name] = "blah"  
test[:name] = "ok"  
puts test #{:name=>"ok"} 
+0

Is Trip è un record attivo? Potrebbe essere necessario salvarlo esplicitamente nel database: '@ trip.save' – Daiku

+0

Ho preso la parte Trip.new. Non lasciarti distrarre. Sto cercando di modificare l'hash ActionController :: Parameters sul posto. –

risposta

48

permit restituisce un nuovo hash con le chiavi in ​​esso, in modo da non sta modificando la variabile reale params. Inoltre, non si sta salvando un riferimento ai ritorni hash trip_params, pertanto è possibile ricevere ogni chiamata in save.

Prova questo:

def save 
    tp = trip_params 
    tp[:name] = 'Modifying name in place' 
    # ... use tp later, it'll be in there 
end 

Oppure, se si vuole veramente di essere utilizzato il modo in cui in precedenza fatto, modificare trip_params in questo modo:

def trip_params 
    @trip_params ||= params.require(:trip).permit(:name, :date) 
end 

Ora che hash viene pigramente memorizzato nella cache e la lo stesso viene restituito nelle successive chiamate trip_params.

+2

Questo ha senso ora! Derp. Grazie per il tuo aiuto –

+3

Finalmente dopo ore di lotta! Grazie Signore. –

+1

Wow i suoi lavori per me !!! –

1

Questo è perché non c'è nessun metodo come trip_params[]=(arg, val).

Voglio dire, quando si chiama trip_params si restituisce il valore di params.require(:trip).permit(:name, :date), così ogni volta che si chiama trip_params hai trovato di nuovo i params.

Quindi, se fossi in te, mi piacerebbe definire il metodo trip_params come segue:

def trip_params 
    @trip_params ||= params.require(:trip).permit(:name, :date) 
end 

E vorrei anche definire un metodo per cambiare trip_params

def trip_params[]= (key,val) 
    trip_params # Ensure that trip_params is called once or you will get an error 
    @trip_params[key] = val 
end 

Così ora quando Chiama il numero trip_params in caso di risposta effettiva al numero @trip_params e, se @trip_params non è impostato, sarà impostato su params.require(:trip).permit(:name, :date)

E poi quando si chiama trip_params[:name] = "Some name" farà in modo che la prima @trip_params viene inizializzato chiamando trip_params and then it will set the :name param to "qualche nome" `

Speranza ho aiutato si

18

Se davvero desidera modificare parametri in controller che si può farlo in questo modo:

def save 
    params[:trip][:name] = 'Modifying name in place' 
    # Now trip_params[:name] is 'Modifying name in place' 
end 
+4

Penso che questa sia la risposta migliore e più semplice qui. Basta modificare prima i parametri attuali, quindi chiamare il metodo dei parametri forti. Puoi anche farlo con before_action: modify_params, solo [: create,: update] quindi creare un metodo privato per tenerlo fuori dai metodi di creazione e aggiornamento. – savmac

1

si potrebbe anche fare

def save 
    data = trip_params.merge(name: 'new name') 
    # use data later 
end 

Se un nuovo hash viene unito in un vecchio hash e se sono presenti chiavi duplicate, le nuove chiavi dell'hash sovrascrivono le chiavi corrispondenti dell'hash precedente.