Rails无法将未经许可的参数转换为哈希

时间:2017-09-04 01:01:43

标签: ruby-on-rails ruby sorting parameters search-form

我正在尝试为我的webapp实现简单的搜索和排序。我正在关注railscast和此railscast

我作为链接使用的可排序函数的应用程序助手是:

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

我在视图中使用这些。在控制器中我使用白名单:

 @listingssearch.where(:vehicletype => 'Car').order(sort_column + " " + sort_direction).paginate(:page => params[:page], :per_page => 30)

私人消毒方法:

 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

我尝试在私有方法中使用merge:

(Listing.column_names + params) but its not working 

对于辅助方法当我尝试向排序链接提供搜索参数时出现错误:无法将未经许可的参数转换为哈希

它显示错误是合并

link_to title, params.merge(:sort => column, :direction => direction, :page => nil), {:class => css_class}

其他方面工作正常:

<%= 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 %>

我的问题是如何在rails 5中的sort helper方法中保留搜索参数?我做错了什么?

6 个答案:

答案 0 :(得分:44)

在Rails 5中,ActionController::Parameters不再继承Hash,试图阻止人们在请求参数上使用Hash相关方法而不明确过滤它们。

作为this pull request的一部分,它被反向移植到Rails 5.1中,部分移植到Rails 5.0中,如果您尝试在参数对象上调用to_h而不调用permit,则会引发异常。

在原始merge对象(params)上调用params.merge(:sort => column, :direction => direction, :page => nil)会返回具有相同ActionController::Parameters状态的新permitted对象(即{{1}没有被调用过)。 permit方法最终会在该对象上调用link_to,从而引发异常。

如果您知道链接中应允许哪些参数,则可以使用列出的参数调用to_h

permit

如果您不知道链接中可以包含哪些参数,那么您可以使用params.permit(:param_1, :param_2).merge(:sort => column, :direction => direction, :page => nil) # OR params.merge(:sort => column, :direction => direction, :page => nil).permit(:param_1, :param_2, :sort, :direction, :page) (如this answer中所述)或request.parameters.merge(...)。在创建链接时,这两者基本上都绕过了强参数保护。默认情况下,这意味着原始请求中的任何参数也会出现在链接URL中。我想在这种特殊情况下风险并不大,但如果你在其他地方有代码没有正确清理参数,这可能会使情况变得更糟。

答案 1 :(得分:4)

您可以使用此技巧:

class Car
{
    // ... your existing code
    public override string ToString() { return name; }
}

我认为Rails开发人员将在知道使用不许可参数的方式时对其进行限制。 :)

答案 2 :(得分:3)

您可以尝试使用request.parameters.merge,下面是上面代码的示例

<%= link_to title, listings_path(request.parameters.merge({:sort => "column", :direction => "direction", :page => nil})), :class => "form-control css_class" %>  

答案 3 :(得分:2)

您也可以通过执行params.permit!进行覆盖,但这可能会带来安全风险,因此请谨慎使用。

答案 4 :(得分:1)

我相信如果你通过专栏允许它再次让你工作!

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.permit(column).merge(sort: column, direction: direction, page: nil), { class: css_class }
end

答案 5 :(得分:1)

因为没有人提出这个建议。所以这是我们可以使用 params.to_unsafe_hash 的一种方法,它将强参数转换为哈希。

例如:

(byebug) values
<ActionController::Parameters {"country"=>"RU", "city"=>"Moscow", "street"=>"1 First Street", "zip"=>"123456"} permitted: false>
(byebug) values.to_unsafe_hash
{"country"=>"RU", "city"=>"Moscow", "street"=>"1 First Street", "zip"=>"123456"}