将哈希值作为hidden_​​field_tag中的值传递

时间:2010-03-24 07:07:26

标签: ruby-on-rails ruby hash hidden-field

我试图通过类似的形式在我的参数中传递一些过滤器:

hidden_field_tag "filters", params[:filters]

由于某种原因,下一页中的参数更改了。例如,如果params [:filters]曾经是......

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

......它变成了......

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

与[1]相比,注意[2]中的额外引号和反斜杠。

有什么想法吗?我试图将它与searchlogic一起用于某些过滤,但是当我在表单中更改更改对象时,我需要它继续存在。我宁愿不把它存放在会话中。

7 个答案:

答案 0 :(得分:16)

我的解决方案只是用键值对重新创建每个参数:

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

答案 1 :(得分:12)

您实际上想要/需要使用隐藏字段“序列化”哈希。

将此添加到 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

然后,在视图中:

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

即使你的过滤器中有多级散列/数组,这也应该可以解决问题。

解决方案http://marklunds.com/articles/one/314

答案 2 :(得分:8)

我刚刚写了一个名为HashToHiddenFields的宝石。

gem的核心是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

答案 3 :(得分:1)

以下是我设法传递参数值我的视图 - 即从View A到View B再到控制器:

  

在视图A(索引)中:

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

在视图B(run_script)中:

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

在控制器中:

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

在我能找到的任何地方都没有记录的关键转换是{...:id =&gt;来自View A的object.id}作为&lt;%...:id =&gt;传递给View B. @object%&gt;,然后View B通过hidden_​​field_tag构造传递给控制器​​(:param_name,params [:id])。

我没有在任何地方看到这个记录,但是在几个网站上仔细阅读了几篇帖子后,包括这篇文章(其语法提供了关键灵感),解决方案终于凝聚了。我已经看到了关于安全性的隐藏字段的注意事项,但鉴于我目前的设计,没有找到其他方法来做到这一点,例如它。

答案 4 :(得分:0)

这是因为当您使用您的hidden_​​field_tag转换HTML时,会添加反引号。当你收到它之后就像字符串而不是哈希。

Hash类型不能存在于HTML中。你只有字符串。所以如果你想传递你的哈希(不是我推荐的),你需要在收到它时进行评估。但对您的应用程序来说可能是一个很大的安全问题。

答案 5 :(得分:0)

作为弗拉德回答的一个警告,我不得不使用原始

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

让它在Rails 3.1.1中运行。基本上,正在输出的文本正在被转义,例如,“&lt;”成为“&amp; lt”。

答案 6 :(得分:0)

假设哈希是字符串,符号,数字和数组,则可以调用eval将哈希的params字符串从hidden_​​fields形式转换回控制器中的哈希。然后,添加引号的反斜杠转义字符不再是问题:

hash = eval(params["hash_string"].to_s)

请信任以下文章,以帮助确定适合我的情况的简单解决方案:

How do I convert a String object into a Hash object?

请记住,应使用.require和.permit清除参数的内容。