Pasar hash como valores en hide_field_tag
-
22-09-2019 - |
Pregunta
Estoy intentando pasar algunos filtros en mis parámetros a través de un formulario como este:
hidden_field_tag "filters", params[:filters]
Por alguna razón, los parámetros se cambian en la página siguiente.Por ejemplo, si params[:filters] solía ser...
"filters"=>{"name_like_any"=>["apple"]} [1]
...se cambia a...
"filters"=>"{\"name_like_any\"=>[\"apple\"]}" [2]
tenga en cuenta las comillas y barras invertidas adicionales en [2] en comparación con [1].
¿Algunas ideas?Estoy intentando usar esto con searchlogic para algunos filtrados, pero necesito que persista cuando cambio objetos de cambio en formularios.Preferiría no tener que almacenarlo en la sesión.
Solución
Usted realmente quiere / necesidad de 'serialize' un hash utilizando campos ocultos.
Añadir 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
A continuación, 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.
Otros consejos
Mi solución era 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 %>
Me acaba de escribir una joya para hacer esto se llama HashToHiddenFields .
El núcleo de la gema es este 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
Así es como logré pasar un valor de parámetro a través de mi vista, es decir, desde la Vista A hasta la Vista B y hasta 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 transición clave que no estaba documentada en ningún lugar que pude encontrar es donde {...:id => object.id} de la Vista A se pasa a la Vista B como <%...:id => @object %>, que la Vista B luego pasa al controlador como (:param_name, params[:id]) a través de la construcción hide_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 está.
es porque cuando se convierte en HTML con su hidden_field_tag, la comilla inversa es complemento. Después cuando lo recibió como una cadena no un hash.
El tipo de hash no puede existir en HTML. Sólo tiene cuerda. Así que si quieres pasar su almohadilla (no recomiendo por mí), es necesario que eval cuando lo recibió. Pero puede ser un gran problema de seguridad en su aplicación.
A modo de advertencia a la respuesta de Vlad, tuve que usar prima
<%= raw hash_as_hidden_fields(:filter => params[:filter]) %>
para conseguir que funcione en Rails 3.1.1. Esencialmente, estaba siendo escapó de la salida es de texto, por ejemplo., "<" Convertirse "<".