2010-03-24 10 views
14

Próbuję przekazać niektóre filtry w moich params poprzez formularz tak:Przechodząc hash jako wartości w hidden_field_tag ​​

hidden_field_tag "filters", params[:filters]

Z jakiegoś powodu params się przebrać na następnej stronie. Na przykład, jeżeli params [: Filtry] Używany być ...

"filters"=>{"name_like_any"=>["apple"]} [1]

... to zostaje zmieniona na ...

"filters"=>"{\"name_like_any\"=>[\"apple\"]}" [2]

uwaga dodatkowe cytaty i backslashe w [2] w porównaniu do [1].

Wszelkie pomysły? Próbuję użyć tego z searchlogic do niektórych filtrowania, ale potrzebuję go do utrzymania, gdy zmienię zmianę obiektów w formularzach. Wolałbym nie przechowywać go w sesji.

Odpowiedz

11

Rzeczywiście chcesz/potrzebujesz "serializować" hash używając ukrytych pól.

Dodaj to do swojej ApplicationHelper:

def flatten_hash(hash = params, ancestor_names = []) 
    flat_hash = {} 
    hash.each do |k, v| 
     names = Array.new(ancestor_names) 
     names << k 
     if v.is_a?(Hash) 
     flat_hash.merge!(flatten_hash(v, names)) 
     else 
     key = flat_hash_key(names) 
     key += "[]" if v.is_a?(Array) 
     flat_hash[key] = v 
     end 
    end 

    flat_hash 
    end 

    def flat_hash_key(names) 
    names = Array.new(names) 
    name = names.shift.to_s.dup 
    names.each do |n| 
     name << "[#{n}]" 
    end 
    name 
    end 

    def hash_as_hidden_fields(hash = params) 
    hidden_fields = [] 
    flatten_hash(hash).each do |name, value| 
     value = [value] if !value.is_a?(Array) 
     value.each do |v| 
     hidden_fields << hidden_field_tag(name, v.to_s, :id => nil)   
     end 
    end 

    hidden_fields.join("\n") 
    end 

Następnie w widoku:

<%= hash_as_hidden_fields(:filter => params[:filter]) %> 

To powinno wystarczyć, nawet jeśli masz wielopoziomowego mieszania/tablicę w swoich filtrach.

rozwiązanie brane http://marklunds.com/articles/one/314

+0

To się udało, dzięki. To rozwiązanie powinno być zawarte w Railsach lub czymś podobnym. – funkymunky

+0

Nie ma za co :). Nie, uważam, że nie jest to podstawowa funkcjonalność, ale byłoby miło, gdyby została dołączona do wtyczki. –

+0

Awesome! Zdecydowanie powinien być częścią Rails. Btw musi zmienić 'hidden_fields.join (" \ n ")' na 'hidden_fields.join (" \ n "). Html_safe' w Rails 5, tak aby kod HTML nie został usunięty – elsurudo

0

dzieje się tak dlatego, że po konwersji w HTML za pomocą parametru hidden_field_tag ​​wsteczna kopia jest dodawana. Po tym, jak otrzymałeś go jak ciąg, a nie Hash.

Typ skrótu nie może istnieć w HTML. Masz tylko ciąg. Więc jeśli chcesz przekazać swój hasz (nie polecam przeze mnie), potrzebujesz eval go, kiedy go otrzymałeś. Ale może to być duży problem z bezpieczeństwem w aplikacji.

0

Jako zastrzeżeniem, aby odpowiedzieć Vlada, musiałem użyć surowego:

<%= raw hash_as_hidden_fields(:filter => params[:filter]) %> 

aby zmusić go do pracy w Rails 3.1.1. Zasadniczo, tekst wyjściowy był uciekł, np. "<" staje się "& lt".

12

Moje rozwiązanie było po prostu odtworzyć każdy z param z par klucz-wartość:

<% params[:filters].each do |key,value| %> 
<%= hidden_field_tag "filters[#{key}]",value %> 
<% end %> 
+2

Tak prosty. Działa jak marzenie. Dzięki, okliv! –

+4

Rozwiązania takie jak te nie obsługują głębszych zagnieżdżeń ... – vemv

7

Właśnie napisał gem to zrobić o nazwie HashToHiddenFields.

Trzon gem jest kod this:

def hash_to_hidden_fields(hash) 
    query_string = Rack::Utils.build_nested_query(hash) 
    pairs  = query_string.split(Rack::Utils::DEFAULT_SEP) 

    tags = pairs.map do |pair| 
    key, value = pair.split('=', 2).map { |str| Rack::Utils.unescape(str) } 
    hidden_field_tag(key, value) 
    end 

    tags.join("\n").html_safe 
end 
1

Oto, jak udało mi się przekazać wartości parametru przez mój pogląd - czyli od wyświetlić poprzez View B i na kontrolerze:

Mając A (index):

<%= link_to 'LinkName', {:action => "run_script", :id => object.id} %> 

W View B (Run_script):

<%= form_tag :action => 'index', :id => @object %> 
<%= hidden_field_tag(:param_name, params[:id]) %> 

W regulatorze:

Just reference params[:param_name] to make use of the value. 

Kluczem przejściowy, który nie został udokumentowany nigdzie nie mogłem znaleźć gdzie {...: id => object.id} z widoku A jest przekazywane do widoku B jako <% ...: id => @obiekt%>, który widok B następnie przekazuje do kontrolera jako (: nazwa_parametru, parametry [: id]) przez konstrukcję hidden_field_tag.

Nie widziałem tego udokumentowanego w dowolnym miejscu, ale po przejrzeniu kilku postów w kilku witrynach, w tym w tym poście (którego składnia stanowiła kluczową inspirację), rozwiązanie w końcu zelżowało. Widziałem zastrzeżenia na ukrytych polach związanych z bezpieczeństwem, ale nie znalazłem innego sposobu, aby to zrobić, biorąc pod uwagę mój obecny projekt, taki jaki jest.

Powiązane problemy