Передача хэша как значений в теге скрытого поля

Я пытаюсь передать некоторые фильтры в моих парамах через такую форму:

hidden_field_tag "filters", params[:filters]

по какой-то причине параметры изменяются на следующей странице. Например, если раньше были params [: filters]...

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

...он заменяется...

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

обратите внимание на дополнительные цитаты и обратные косые черты в [2] по сравнению с [1].

какие идеи? Я пытаюсь использовать это с searchlogic для некоторых фильтрация, но мне нужно, чтобы она сохранялась, когда я изменяю объекты изменения в формах. Я бы предпочел не хранить его во время сеанса.

6 ответов


вы действительно хотите / должны "сериализовать" хэш, используя скрытые поля.

добавьте это в ваш 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


моим решением было просто воссоздать каждый из param с парой ключ-значение:

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

Я просто написал драгоценный камень, чтобы сделать это под названием HashToHiddenFields.

основной камень этой код:

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

вот как мне удалось передать значение параметра через мой вид-то есть из вида A через вид B и на контроллер:

in View A (index):

<%= 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 => объект.id} из представления A передается в представление B как @object % > , которое представление B затем передается контроллеру как (: param_name, params [: id]) через конструкцию hidden_field_tag.

Я не видел этого документированного нигде, но после просмотра нескольких сообщений на нескольких сайтах, включая этот пост (синтаксис которого обеспечивал ключевое вдохновение), решение наконец сгустилось. Я видел предостережения о скрытых полях, относящихся к безопасности, но не нашел другого способа сделать это, учитывая мой текущий дизайн, такой, как он есть.


Это потому, что когда вы конвертируете в HTML с помощью hidden_field_tag, backquote-add. После того, как вы получили его как строку, а не хэш.

тип хэша не может существовать в HTML. У вас есть только строка. Поэтому, если вы хотите передать свой хэш (не рекомендую мне), вам нужно оценить его, когда вы его получили. Но может быть большой проблемой безопасности в приложении.


в качестве предостережения к ответу Влада я должен был использовать raw:

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

чтобы заставить его работать в Rails 3.1.1. По сути, выводимый текст был экранирован, например., "