我正在构建一个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中,我没有正确定义搜索功能。有人对不正确之处有任何建议吗?
答案 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 表中有一列 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方法。
搜索部分可以通过两种方式完成:
对于第一种情况,简单地修改您的搜索方法如下:
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}%")
希望这会有所帮助。