I am trying to implement a simple search and sort for my webapp. I am following the railscast and this railscast.
My application helper for sortable function which I am using as link is:
def sortable(column, title = nil)
title ||= column.titleize
css_class = column == sort_column ? "current #{sort_direction}" : nil
direction = column == sort_column && sort_direction == "asc" ? "desc" : "asc"
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
end
I am using these in the view. In the controller I am using white listing as:
@listingssearch.where(:vehicletype => 'Car').order(sort_column + " " + sort_direction).paginate(:page => params[:page], :per_page => 30)
Private Methods for sanitization:
private
def sort_column
Listing.column_names.include?(params) ? params[:sort] : "rateperhour"
end
def sort_direction
%w[asc desc].include?(params[:direction]) ? params[:direction] : "asc"
end
I tried using merge in the private method:
(Listing.column_names + params) but its not working
For the helper methods I am getting an error when I am trying to provide search params to the sorting link: unable to convert unpermitted parameters to hash
It shows the error is for merge
link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}
The otherway around works fine:
<%= bootstrap_form_for listings_path, :method => 'get' do %>
<%= hidden_field_tag :direction, :value => params[:direction] %>
<%= hidden_field_tag :sort,:value => params[:sort] %>
<div class= "col-sm-12 col-lg-12 col-md-12" style = "margin: auto;">
<h6 style = "color:#7C064D;"><strong> PICK A DATE <span class="glyphicon glyphicon-calendar"></span></strong>
<%= date_field_tag :startdate, params[:startdate], placeholder: 'DATE' %>
</h6>
</div>
<div class= "col-sm-12 col-lg-12 col-md-12" style = "margin: auto;">
<p>
<%= text_field_tag :near, params[:near], placeholder: ' Destination' %>
<%= text_field_tag :radius, params[:radius], placeholder: ' Search Radius' %>
</p>
</div>
<div class= "col-sm-12 col-lg-12 col-md-12" style = "margin: auto;">
<p>
<%= text_field_tag :min, params[:min], placeholder: ' Minimum Rate Per Hour' %>
<%= text_field_tag :max, params[:max], placeholder: ' Maximum Rate Per Hour' %>
</p>
</div>
<div class= "col-sm-12 col-lg-12 col-md-12" style = "margin-top: 10px;">
<%= submit_tag "Search", class: "btn btn-info", style: "width: 40%; background-color: #E20049; border: #e20049;" %>
<%= link_to 'View All', root_path, class: "btn btn-info", style: "width: 40%; background-color: #E20049; border: #e20049;" %>
</div>
<!-- <div class= "col-sm-6 col-lg-6 col-md-6" style = "margin-top: 10px;">
</div> -->
<% end %>
My question is How to persist search params in sort helper methods in rails 5? What I am doing wrong?
In Rails 5,
ActionController::Parameters
no longer inherits fromHash
, in an attempt to discourage people from usingHash
-related methods on the request parameters without explicitly filtering them.As part of this pull request, which was backported into Rails 5.1 and partially into Rails 5.0, an exception is raised if you try to call
to_h
on the parameters object without callingpermit
.Calling
merge
on the originalparams
object (params.merge(:sort => column, :direction => direction, :page => nil)
) returns a newActionController::Parameters
object with the samepermitted
status (that is,permit
has not been called on it). Thelink_to
method then ends up callingto_h
on that object, which raises the exception.If you know which parameters should be allowed in the link, you can call
permit
with those listed.If you don't know which parameters could be included in the link, then it's possible to call
request.parameters.merge(...)
(as mentioned in this answer) orparams.to_unsafe_h.merge(...)
. However, as pointed out in comments, this is a security risk when the result is passed tolink_to
, as a parameter likehost
would be interpreted as the actual host for the link instead of a query parameter. There are several other keys that also have special meaning inlink_to
(everything accepted byurl_for
, plus:method
), so it's generally a risky approach.