2013-08-22 16 views
36

To może być bardziej pytanie rubinowe niż pytanie o szynę, ale jestem prawie pewien, że udało mi się to zrobić w aplikacji z rubinem waniliowym.Zmodyfikuj hash ruby ​​(sztywne szyny)

Mam zdefiniowane silne parametry.

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

Teraz otrzymuję te parametry w metodzie sterownika. Chce to zrobić.

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

To nigdy nie działa. Nazwa nigdy się nie zmienia. BTW: Typ trip_params to ActionController :: Parametry

Jeśli wykonuję standardowy skrypt ruby, to działa.

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

Czy Trip jest aktywnym zapisem? Może być konieczne jawne zapisanie go w bazie danych: '@ trip.save' – Daiku

+0

Wziąłem część Trip.new. Nie pozwól, aby to rozpraszało. Próbuję zmodyfikować mieszanie ActionController :: Parameters w miejscu. –

Odpowiedz

48

permit zwraca nowy hash z tymi kluczami w nim, więc nie jesteś modyfikując prawdziwe params zmienną. Nie zapisujesz również odniesienia do zwracanych przez program hash znaków trip_params, więc otrzymujesz zawsze świeże każde wywołanie w save.

Spróbuj tego:

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

Lub, jeśli naprawdę chcesz, żeby być używany tak, jak wcześniej zrobił, modyfikować trip_params tak:

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

Teraz hash jest leniwie pamięci podręcznej i tym ten sam jest zwracany podczas kolejnych wywołań trip_params.

+2

To ma sens teraz! Derp. Dzięki za pomoc –

+3

Wreszcie, po godzinach zmagań! Dziękuję Panu. –

+1

Wow to działa dla mnie !!! –

1

To dlatego, że nie ma metody, takie jak trip_params[]=(arg, val).

To znaczy, kiedy zadzwonić trip_params wracasz wartość params.require(:trip).permit(:name, :date), więc za każdym razem, gdy nazywają trip_params jesteś znowu coraz params.

Więc gdybym był tobą, to bym zdefiniować metodę trip_params następujące:

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

I byłoby również określenie sposobu, aby zmienić 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 

Więc teraz, kiedy zadzwoń pod numer trip_params, a następnie zwrócisz @trip_params, a jeśli @trip_params nie zostanie jeszcze ustawiony, ustawi się na params.require(:trip).permit(:name, :date)

A potem, kiedy zadzwonisz trip_params[:name] = "Some name" będzie zapewnienie pierwszy @trip_params jest inicjowany przez wywołanie trip_params and then it will set the :name param to „Niektóre nazwy” `

nadzieję, że pomogliśmy Ci

18

Jeśli naprawdę chce zmienić params kontroler ty można to zrobić na tej drodze:

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

Myślę, że jest to najlepsza i najprostsza odpowiedź tutaj. Po prostu zmodyfikuj najpierw rzeczywiste parametry, a następnie wywołaj metodę silnych parametrów. Możesz nawet zrobić to za pomocą before_action: modify_params, only [: create,: update], a następnie utwórz prywatną metodę, aby nie tworzyć jej z metod tworzenia i aktualizowania. – savmac

1

można również zrobić

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

Jeśli nowy skrót zostanie scalony w stary skrót i jeśli istnieją zduplikowane klucze, nowe klawisze skrótu zastąpią stare, pasujące klucze.