Rails:按参数搜索不起作用-关联有问题吗?

时间:2018-08-21 00:00:39

标签: ruby-on-rails ruby search model-view-controller parameters

我正在构建一个Rails应用程序,该应用程序允许用户按作者的名字搜索Books。在构建搜索功能时遇到一些问题,但是据我所知,我觉得自己做的事情完全正确吗?

这是我开始的目的: schema.rb

ActiveRecord::Schema.define do
  create_table "books", force: :cascade do |t|
    t.string   "title"
    t.integer  "author_id"
    t.string   "author_name"
    t.index ["title"], name: "index_books_on_title", unique: true
  end

  create_table "authors", force: :cascade do |t|
    t.string   "name"
    t.string   "bio"
  end
end

这是我在seeds.rb中的样本数据

books = [
          {title:"Ruby Programming", author_id: 1, author_name: "John Smith"},
          {title:"Java Programming", author_id: 2 , author_name: "Jane Adams"},
          {title:"PHP Programming", author_id: 3, author_name: "Mike Jones"},
          {title:"Python Programming", author_id: 1, author_name: "John Smith"}
        ]

authors = [
            {name:"John Smith", bio: "John Smith loves Ruby and Python"},
            {name:"Jane Adams", bio: "Jane Adams loves Java"},
            {name:"Mike Jones", bio: "Mike Jones loves PHP"}
          ]

这是我的books_controller.rb

class BooksController < ApplicationController
  def index
    @books = Books.all
    if params[:search]
      @books = Book.search(params[:search]).order("created_at DESC")
    else
      @books = Book.all.order("created_at DESC")
    end
  end    
end

这是我的模型/book.rb。这是我定义搜索功能的地方。

class Book < ApplicationRecord
  has_one :author

  def author_name
    self.author.name
  end

  def self.search(search)
    where("book.author.name LIKE ?", "%#{search}%") 
  end
end

这是我的模型/author.rb

class Author < ApplicationRecord
  has_many :books
end

用户可以在此处通过views / books / index.html.erb中的作者姓名搜索书籍

<h3> Search by author </h3>

<%= form_tag(books_path, :method => "get") do %>
  <%= text_field_tag :search, params[:search], placeholder: "Search by Author" %>
  <%= submit_tag "Search", :name => nil %>
<% end %>

<ul>
  <% @books.each do |book| %>
    <li>
     <%= link_to book.title book_path(book) %>          
    </li>
  <% end %>
</ul>

但是,当我输入一个作者(使用示例“ John Smith”)时,我不断遇到错误:

SQLite3::SQLException: no such column: book.author.name: SELECT "books".* FROM "books" WHERE (book.author.name LIKE '%John Smith%') ORDER BY created_at DESC

我怀疑在models / book.rb中,我没有正确定义搜索功能。有人对不正确之处有任何建议吗?

3 个答案:

答案 0 :(得分:0)

看看您在models/book.rb中的搜索方法:

def self.search(search)
    where("book.author.name LIKE ?", "%#{search}%") 
end

由于您正在搜索书籍模型,所以您输入的列名错误,因此您使用的是book.author_name,而不是book.author.name

尝试以下操作:

def self.search(search)
    where("book.author_name LIKE ?", "%#{search}%") 
end

在将作者的姓名存储在多个表中时,您可能还需要考虑一下数据库设计。通过仅在书籍模型中引用作者ID,然后将作者姓名保留在作者模型中,进一步规范数据库设计是个好主意。

答案 1 :(得分:0)

我在您的代码中发现了几个问题。可能是,修复它们会为您解决错误。

模型书中的关联

您在模型Author中有一个正确定义的关联,其中包含很多书。倒数应定义为belongs_to,而不是has_one。将其更改为以下内容:

class Book < ApplicationRecord
  belongs_to :author
end

books表中的冗余/未使用列

根据您的数据库架构,在 books 表中有一列 author_name 。但是,您没有定义直接获取其值的方法,而是定义了自己的getter方法author_name,该方法将返回author.name。因此,如果您真的想在 books 表中有该列,请从模型中删除自定义方法author_name

class Book < ApplicationRecord
  # def author_name
  #   self.author.name
  # end
end

搜索

您看到的错误是因为没有表 book (单数)。将search方法更改为以下方法,它应该可以工作:

def self.search(search)
  where("author_name LIKE ?", "%#{search}%") 
end

注意::该解决方案假定您故意将 author_name 列保留在表 books 中。我建议尽管删除列 author_name 并在关联的authors表中搜索<​​em> name 。

答案 2 :(得分:0)

代码更改的一对:

1。图书模型内部的关系

它应该是belongs_to :author而不是has_one :author

2。修改搜索栏

从Book模型中删除多余的author_name方法。

搜索部分可以通过两种方式完成:

  • 在books表中具有author_name列。
  • books表中没有author_name列,因为它已经存在于作者记录中。

对于第一种情况,简单地修改您的搜索方法如下:

def self.search(search)
  where("author_name LIKE ?", "%#{search}%") 
end

最好在author_name上添加索引。

对于第二种情况,请从books表中删除author_name列,并按如下所示修改代码:

def self.search(search)
  author_ids = Author.where("name LIKE ?", "%#{search}%").ids
  where(author_id: author_ids)
end

同样,最好在authors表中的author_name上添加索引。

另一个建议,进行不区分大小写的搜索,以改善搜索效果,如下所示:

where("lower(author_name) LIKE ?", "%#{search.downcase}%")

希望这会有所帮助。