web-dev-qa-db-fra.com

Rails: Préservation des paramètres de chaîne de requête GET dans link_to

J'ai une fonction de recherche typique dans mon application qui renvoie une liste de résultats qui peuvent être paginés, triés, affichés avec une valeur records_per_page différente, etc. Chacune de ces options est contrôlée par des paramètres dans la chaîne de requête. Un exemple simplifié:

/search?q=test&page=2

Supposons maintenant que je dois afficher un ensemble de liens qui définissent la valeur records_per_page sur 10, 20, 30. Chaque lien doit inclure les paramètres de requête existants, qui peuvent être un ensemble très long, plus un nouveau paramètre per_page.

/search?q=test&page=2& ... &per_page=10
/search?q=test&page=2& ... &per_page=20
/search?q=test&page=2& ... &per_page=30

Existe-t-il un moyen facile de le faire avec simplement link_to helper ou j'ai besoin d'analyser et de reproduire la chaîne de requête de la demande précédente d'une manière ou d'une autre?

45
Vincent
link_to 'Link', request.query_parameters.merge({:per_page => 20})
65
Vincent
link_to 'Link', params.merge({:per_page => 20})
22
Olek

La manière la plus simple de fusionner les nouveaux paramètres avec les paramètres de requête et NON avec tous les paramètres (y compris ceux obtenus via le chemin d'accès) est de fusionner avec request.query_parameters

link_to 'Search', search_path(request.query_parameters.merge({ per_page: 20 }))

Sinon, vous vous retrouvez avec des chaînes de requête dupliquant les paramètres de chemin, par exemple ?action=index&controller=products&foo=bar au lieu de ?foo=bar.

18
Clemens

Si vous souhaitez conserver les paramètres existants et ne pas vous exposer aux attaques XSS, assurez-vous de nettoyer le hachage des paramètres, en ne laissant que les paramètres que votre application peut envoyer:

# inline
<%= link_to 'Link', params.slice(:sort).merge(per_page: 20) %>

Si vous l'utilisez à plusieurs endroits, nettoyez les paramètres du contrôleur:

# your_controller.rb
@params = params.slice(:sort, :per_page)

# view
<%= link_to 'Link', @params.merge(per_page: 20) %>
4
Greg Funtusov

Vous pouvez simplement lancer des éléments du hachage params sur link_to. Comme

link_to "some_other_link", "/search", :page => params[:page]
2
Reactormonk

Cela fonctionne si les liens que vous traitez ne vous sont pas fournis par request.params.

require 'rack/utils'                                                                                
require 'uri'                                                                                       

def modify_query url, options={}                                                                    
  uri = URI(url)                                                                                    
  query_hash = Rack::Utils.parse_query(uri.query)                                                   
  query_hash.merge!(options)                                                                        
  uri.query = Rack::Utils.build_query(query_hash)                                                   
  uri.to_s                                                                                          
end                                                                                                 

puts modify_query('/search?q=test&page=2&per_page=10', 'per_page' =>  20)                           
puts modify_query('/search?q=test&page=2', 'per_page' => 30)                                        

# Outputs                                                                                           
# /search?q=test&page=2&per_page=20                                                                 
# /search?q=test&page=2&per_page=30
1
Joe Van Dyk

Qu'en est-il de

<%= link_to 'Whatever', :overwrite_params => { :pear_page => 20 } %>

?

1
jordinl

Un peu tard je sais ..

Si vous utilisez cela comme un moyen de filtrer les résultats de recherche, jetez un œil à mon aide :)

Cela supprime automatiquement tous les paramètres vides et inutiles et ajoute la classe "sélectionnée" si tous ses nouveaux paramètres ont déjà été définis.

def search_to s, args={}

  selected = 0
  args.each do |k, v|
    selected = selected + 1 if params[k] == v.to_s || ( params[k].nil? && v.blank? )
  end

  if @search_params_base.nil?
    @search_params_base = request.parameters.clone
    @search_params_base.delete(:action)
    @search_params_base.delete(:controller)
    @search_params_base.delete(:page)
    @search_params_base.delete_if{|k, v| v.nil? || v.blank?}
    @search_params_base.delete(:utf8) if @search_params_base[:keywords].nil?
  end
  search_params = @search_params_base.merge(args)
  search_params.delete_if{|k, v| v.nil? || v.blank?}

  link_to s, search_path + '?' + search_params.to_param, :class => selected == args.length ? 'selected' : nil
end

Vous pouvez ensuite simplement utiliser ceci dans votre vue:

search_to '$80 to $110', :price => 80..110

Ou dans votre cas:

search_to '30 per page', :page => params[:page], :per_page => 30
0
complistic