2010-03-24 21 views
14

Estoy tratando de pasar algunos filtros en mis params a través de un formulario de este modo:de hash como valores en hidden_field_tag ​​

hidden_field_tag "filters", params[:filters]

Por alguna razón los parametros se cambian en la página siguiente. Por ejemplo, si params [: filtros] solía ser ...

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

... que se cambia a ...

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

nota las citas adicionales y las barras invertidas en [2] cuando se compara con [1].

¿Alguna idea? Estoy intentando usar esto con searchlogic para algunos filtros, pero necesito que persista cuando cambie los objetos de cambio en los formularios. Preferiría no tener que almacenarlo en sesión.

Respuesta

11

Realmente quiere/necesita 'serializar' un hash usando los campos ocultos.

Agregue esto a su 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 

Entonces, a la vista:

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

Esto debería hacer el truco, incluso si tiene un hash multinivel/matriz en sus filtros.

solución tomada http://marklunds.com/articles/one/314

+0

Eso lo hizo gracias. Esta solución debe incluirse en Rails o algo así. – funkymunky

+0

De nada :). No, creo que esto no es una funcionalidad central, pero sería bueno que se incluyera en un complemento. –

+0

¡Impresionante! Definitivamente debería ser parte de Rails. Btw tiene que cambiar 'hidden_fields.join (" \ n ")' a 'hidden_fields.join (" \ n "). Html_safe' en Rails 5, para que el HTML no se escape – elsurudo

0

es porque al convertir en HTML con su hidden_field_tag, se agrega la comilla invertida. Después, cuando lo recibiste como una cuerda, no como un Hash.

El tipo de Hash no puede existir en HTML. Solo tienes cadena. Entonces, si quieres pasar tu hash (no lo recomiendo), necesitas evaluarlo cuando lo recibiste. Pero puede ser un gran problema de seguridad en su aplicación.

0

A modo de advertencia a la respuesta de Vlad, tuve que usar prima:

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

a conseguir que funcione en Rails 3.1.1. Esencialmente, el texto que se estaba emitiendo se estaba escapando, por ejemplo, "<" convirtiéndose en "& lt".

12

Mi solución fue sólo para volver a crear cada uno de parámetro con el par clave-valor:

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

Tan simple. Funciona de maravilla. Gracias okliv! –

+4

Soluciones como estas no manejan anidamientos hash más profundos ... – vemv

7

simplemente escribí una joya de hacer esto llama HashToHiddenFields.

El núcleo de la gema es this código:

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

Así es como me las arreglé para pasar un valor de parámetro través mi punto de vista - es decir, de la vista A través View B y en el controlador:

en la vista A (índice):

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

en la vista B (Run_script):

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

En el controlador:

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

La clave de transición que no se documentó en cualquier lugar que pude encontrar es donde {...: id => object.id} desde la Vista A se pasa a la Vista B como <% ...: id => @object%>, que Vista B luego pasa al controlador como (: param_name, params [: id]) a través de la construcción hidden_field_tag.

No vi esto documentado en ninguna parte, pero después de leer varias publicaciones en varios sitios, incluida esta publicación (cuya sintaxis proporcionó la inspiración clave), la solución finalmente se consolidó. He visto las advertencias sobre campos ocultos relacionados con la seguridad, pero no he encontrado otra forma de hacerlo dado mi diseño actual, tal como es.

Cuestiones relacionadas