首页 > 解决方案 > Rails:创建的参数未正确保存

问题描述

我正在练习构建一个 Rails 应用程序。我正在尝试构建一个使用作者和书籍的应用程序。该应用程序的目的是为书籍提供一个显示页面,为作者提供一个显示页面,以及一些连接两者的链接。我几乎已经准备好了。我唯一的问题是,每当我尝试保存作者的姓名时,它都会被保存为作者页面的链接。

这是我开始的内容: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

  def show
    @book = Book.find(params[:id])
  end

  def new
    @book = Book.new
  end

  def create
    @book = Book.new(book_params)

    if(@book.save)
      redirect_to @book
    else
      render 'already_exists'
    end
  end

  private def book_params
    params.require(:book).permit(:id, :title, :author_id, :author_name)
  end

end

这是我的 author_controller.rb

class AuthorsController < ApplicationController
  def index
    @authors = Author.all
  end

  def show
    @author = Author.find(params[:id])
  end

end

这是我的模型/book.rb

class Book < ApplicationRecord
    has_one :author
    validates :title, presence:true, length: {minimum:1}
end

这是我的模型/author.rb

class Superpower < ApplicationRecord
    has_many :books
end

因此,我正在努力让用户可以使用其中一位选定的作者创建一本新书。创建书后,他们将被重定向回一个新页面,该页面将显示书名和作者姓名(这将链接回作者页面及其简历)。

这是views/books/new.html.erb

<h1> Add Book </h1>

<%= form_for :book, url: books_path do |f| %>

    <p>
    <%= f.label :title %> <br>
    <%= f.text_field :title %>
    </p>

    <p>
    <%= f.label :author_id, "Author" %> <br>
    <%= collection_select(:book, :author_id, Author.all, :id, :name, {:prompt => 'Please select'}, class: 'form-control' ) %>
    </p>

    <p>
    <%= f.submit %>
    <p>
    <% end %>

这是views/book/show.html.erb

<h2> Title: <%= @book.title %> </h2>

<h2> Author: <%= link_to @book.author_name, author_path(@book.author_id) %> </h2>

<p> <%= link_to "Go back to Books", root_path %> </p>

但不是显示这个:

Title: Ruby Programming
Author: John Smith

我明白了:

Title: Ruby Programming
Author: authors/1

我怀疑这与我选择作者的表单有关,但我不知道为什么“author_name”没有保存为 author_name 字符串,而是作为作者页面的直接链接。这个错误弄乱了我的应用程序的其他部分,我已经困惑了几天了。有人可以帮忙吗?

标签: ruby-on-railsrubyformsselectmodel-view-controller

解决方案


你没有以正确的方式生成书的 author_name 字段,但你根本不需要它,如果你有关系并且作者表有一个 name 字段,你总是可以使用 book_instance.author.name,或者你可以在书本模型中生成一个返回 this 的方法 author_name。

因此,通过迁移从 book 表中删除 author_name 字段,将其从控制器中的强参数中删除,并将 next 方法添加到 book 模型:

def author_name
  self.author.name
end

这应该工作


推荐阅读