【问题标题】:Search not finding correct results搜索未找到正确结果
【发布时间】:2023-03-14 03:13:01
【问题描述】:

我正在学习如何创建 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

【问题讨论】:

  • 您是否检查了日志,如果您获得了所需的搜索参数?能否请您发布此请求的 Rails 服务器日志。
  • “不起作用”不是很有帮助。这段代码应该做什么,它目前在做什么?
  • 它不显示结果。没有错误,只是没有给我任何结果。表格是空白的。
  • 这是我搜索 ET 时服务器日志显示的内容。在 2016-12-01 10:37:46 -0800 开始 GET "/movies/new?utf8=%E2%9C%93&search=ET&commit=Search" for 127.0.0.1 10:37:46 -0800 由 MoviesController#new 作为 HTML 参数处理:{"utf8 "=>"✓", "search"=>"ET", "commit"=>"Search"} 在布局/应用程序中渲染电影/new.html.erb 电影存在 (1.5ms) SELECT 1 AS one FROM "movies “哪里(标题)限制?抵消 ? [["LIMIT", 1], ["OFFSET", 0]] 在布局/应用程序中渲染电影/new.html.erb (33.4ms) 在 854ms 内完成 200 OK (Views: 813.5ms | ActiveRecord: 1.5ms)

标签: ruby-on-rails forms search


【解决方案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;返回一个关系, .all 返回一个电影对象数组,如果你调用order 和其他链,你不想要它。

阅读 sql 注入和参数插值: http://rails-sqli.org/#where http://api.rubyonrails.org/v5.0.0.1/classes/ActiveRecord/QueryMethods.html#method-i-where

【讨论】:

  • 那么,你上面的方法可以保护数据库免受 SQL 注入?
  • 好吧,我不是注入方面的专家,所以我不能说这 100% 不可能,但是直接插入查询字符串是最常见的错误。阅读最后的这两个链接,了解更多关于如何正确构建查询以及其他注入示例的信息。
  • 您还应该阅读一下范围方法,这种方法可能更适合范围而不是类方法。这里:blog.plataformatec.com.br/2013/02/…
猜你喜欢
  • 1970-01-01
  • 2019-05-01
  • 2014-06-23
  • 1970-01-01
  • 2016-01-11
  • 2017-01-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多