2010-03-24 24 views
14

Sto cercando di passare alcuni filtri nei miei params attraverso un modulo in questo modo:Passando hash come valori in hidden_field_tag ​​

hidden_field_tag "filters", params[:filters]

Per qualche ragione i params vengono modificati nella pagina successiva. Per esempio, se params [: filtri] usato per essere ...

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

... vengono cambiate in ...

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

nota le citazioni in più e backslash in [2] rispetto a [1].

Qualche idea? Sto tentando di usarlo con searchlogic per alcuni filtri, ma ho bisogno di persistere quando cambio oggetti di cambiamento nei moduli. Preferirei non doverlo conservare in sessione.

risposta

11

In realtà si desidera/è necessario "serializzare" un hash utilizzando i campi nascosti.

Aggiungi questo al vostro 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 

Poi, in vista:

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

Questo dovrebbe fare il trucco, anche se si dispone di un multilivello hash/array nei filtri.

Soluzione preso http://marklunds.com/articles/one/314

+0

Questo ha funzionato. Questa soluzione dovrebbe essere inclusa in Rails o qualcosa del genere. – funkymunky

+0

Prego :). No, credo che questa non sia una funzionalità di base, ma sarebbe bello se fosse inclusa in un plugin. –

+0

Fantastico! Dovrebbe sicuramente essere una parte di Rails. Btw deve cambiare 'hidden_fields.join (" \ n ")' in 'hidden_fields.join (" \ n "). Html_safe' in Rails 5, in modo che l'HTML non venga scappato – elsurudo

0

è perché quando si converte in HTML con il tuo hidden_field_tag, viene aggiunto il backquote. Dopo, quando lo hai ricevuto come una stringa, non un hash.

Il tipo di hash non può esistere in HTML. Hai solo una stringa. Quindi, se vuoi passare il tuo hash (non consigliato da me), hai bisogno di evalingarlo quando lo hai ricevuto. Ma può essere un grosso problema di sicurezza nella tua applicazione.

0

Come un avvertimento alla risposta di Vlad, ho dovuto usare prime:

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

per farlo funzionare in Rails 3.1.1. Essenzialmente, il testo in uscita era in fuga, ad es. "<" diventa "& lt".

12

La mia soluzione era solo per ricreare ciascuno dei param con coppia chiave-valore:

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

Così semplice. Funziona come un fascino. Grazie ok! –

+4

Soluzioni come queste non gestiscono nidificazioni hash più profonde ... – vemv

7

ho appena scritto una gemma per fare questo chiamato HashToHiddenFields.

Il nucleo della gemma è this codice:

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

Ecco come sono riuscito a passare un valore di parametro attraverso mio punto di vista - che è, da Vista A attraverso View B e al controller:

In Vista A (indice):

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

In View B (Run_script):

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

Nel controllore:

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

Il passaggio chiave che non è stato documentato da nessuna parte ho potuto trovare è dove {...: id => object.id} Dalla vista A viene passata alla vista B come <% ...: id => @object%>, che View B passa poi al controller come (: param_name, params [: id]) tramite il costrutto hidden_field_tag.

Non ho visto questo documentato da nessuna parte, ma dopo aver esaminato diversi post su diversi siti tra cui questo post (la cui sintassi ha fornito l'ispirazione chiave), la soluzione alla fine ha gelificato. Ho visto le avvertenze su campi nascosti relativi alla sicurezza ma non ho trovato nessun altro modo per fare questo dato il mio attuale design, come è.