2016-12-01 129 views
0

我正在学习如何创建rails搜索栏。我有一个名为电影的模型。我想按标题搜索电影并显示结果。我在“新”视图中这样做,而不是“索引”。我也在结果上使用will_paginate。目前,即使电影存在,我的搜索也不会显示结果。如果我不搜索,我仍然可以看到我的所有电影......但显然,我需要搜索功能。有人可以帮忙吗?搜索未找到正确结果

新电影的看法:

<div class="row"> 
<div class="col-xs-12"> 
    <h2 class="white">Home</h2> 
    <hr /> 
    <h4 class="white">Add Movie</h4> 
    <%= form_for @movie, class: 'form-horizontal' do |m| %> 
     <div class="form-group"> 
      <label for="title" class="white">Title: </label><br/> 
      <%= m.text_field :title, class: 'form-control' %> 
     </div> 
     <div class="form-group"> 
      <label for="title" class="white">Year: </label><br/> 
      <%= m.text_field :year, class: 'form-control' %> 
     </div> 
     <div class="form-group"> 
      <%= m.submit %> 
     <div class="form-group"> 
    <% end %> 
</div> 
</div> 

<hr /> 

<div class="row"> 
<div class="col-xs-12"> 
<h4 class="white">Database</h4> 
<%= form_tag new_movie_path, :method=> 'get' do %> 
    <%= text_field_tag :search, params[:search] %> 
    <%= submit_tag "Search" %> 
<% end %> 
<br /> 
    <% if @movies.exists? %> 
    <div class="bg_white"> 
     <table class="table table-hover table-striped"> 
     <tr> 
      <th> 
       Title 
      </th> 
      <th> 
       Status 
      </th> 
      <th> 
       Year 
      </th> 
      <th> 
       Delete 
      </th> 
      <th> 
       Edit 
      </th> 
     </tr> 
     <% @movies.each do |m| %> 
     <tr> 
      <td> 
       <%= link_to m.title, new_movie_rental_path(m) %> 
      </td> 
      <td> 
       <%= m.status %> 
      </td> 
      <td> 
       <%= m.year %> 
      </td> 
      <td> 
       <%= link_to "Delete", movie_path(m), method: :delete %> 
      </td> 
      <td> 
       <%= link_to "Edit", edit_movie_path(m) %> 
      </td> 
     </tr> 
     <% end %> 
     </table> 
    </div> 
    <%= will_paginate @movies, class: 'white' %> 
    <% else %> 
     <p class="white">No movies have been entered</p> 
    <% end %> 
</div> 
</div> 
<div class="row"> 
<div class="col-xs-12"> 
    <hr /> 
    <%= link_to "Add Customer", new_customer_path, class: 'white' %> 
</div> 
</div> 
<br /><br /> 

电影模式:

class Movie < ApplicationRecord 
has_many :rentals, dependent: :destroy 


def status 
    if self.rentals.empty? 
     return "In Stock" 
    else 
     self.rentals.order(borrowed_on: :desc).each do |x| 
      if !x.returned_on.nil? 
       return "In Stock" 
      else 
       return "Rented" 
      end 
     end 
    end 
end 

def self.search(search) 
    if search 
     @movies = Movie.where(["title","%#{[:search]}%"]) 
    else 
     all 
    end 
end 

end 

电影控制器

def new 
    @movie = Movie.new 
    @movies = Movie.search(params[:search]).order(title: :asc).paginate(:page => params[:page], :per_page => 15) 
end 
+0

你检查日志,如果你得到所需的搜索参数? 您可以请发布此请求的导轨服务器日志。 –

+0

“不起作用”不是很有帮助。这段代码应该做什么,它目前在做什么? – tadman

+0

它不显示结果。没有错误,它只是没有给我任何结果。表格是空白的。 –

回答

1

我想说的问题是这一点,你必须为搜索该类方法适用范围:

def self.search(search) 
    if search 
    @movies = Movie.where(["title","%#{[:search]}%"]) 
    else 
    all 
    end 
end 

我想你试图插入搜索参数到查询中,但在这种情况下使用#{},您传递的是符号搜索,而不是插入它。因此您的查询结果为SELECT 1 AS one FROM "movies" WHERE (title)。但更重要的是,通过直接插入查询,您将使自己非常容易受到SQL注入的攻击。如果用户进入搜索字段如')DROP TABLE MOVIES ('会怎么样?我把它改写这样的:

def self.search(search = nil) 
    if search 
    Movie.where('title LIKE :search', search: "%#{search}%") 
    else 
    Movie.scoped 
    end 
end 

还要注意如何我归国Movie.scoped所有,而不是当搜索是空的;返回一个关系,.all返回一个电影对象数组,如果你打电话给order和其他链,你就不需要这个对象。阅读SQL注入和param插值

http://rails-sqli.org/#where http://api.rubyonrails.org/v5.0.0.1/classes/ActiveRecord/QueryMethods.html#method-i-where

+0

谢谢先生!这解决了这个问题。 –

+0

那么,你上面的方式将保护数据库免受SQL注入? –

+0

好吧,我不是注射专家,所以我不能说它是100%不可能的,但直接插入查询字符串是最常见的错误。在最后阅读这两个链接,了解更多关于如何正确构建查询以及其他注入示例。 – mlabarca