2016-12-01 126 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