Rails:创建的参数无法正确保存

时间:2018-08-20 19:42:39

标签: ruby-on-rails ruby forms select model-view-controller

我正在尝试构建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字符串,而是保存为指向作者页面的直接链接。这个错误弄乱了我的应用程序的其他部分,而我已经困扰了几天。有人可以协助吗?

2 个答案:

答案 0 :(得分:0)

您生成的方式不是本书的author_name字段的正确方式,但是根本不需要它,如果存在关系并且author表具有name字段,则始终可以使用book_instance.author.name ,也可以在书本模型中生成方法author_name,并返回该方法。

因此,通过迁移从书本表中删除author_name字段,将其从控制器中的强参数中删除,然后将下一个方法添加到书本模型中:

def author_name
  self.author.name
end

这应该有效

答案 1 :(得分:0)

两种解决方法:

before_create :set_author_name

OR

before_validation(on: :create) do
  set_author_name
end

并在图书模型中定义以下方法:

def set_author_name
  self.author_name = self.author.name
end

另一点,在Book模型中,它应该是belongs_to :author而不是has_one :author

希望这会有所帮助。