【问题标题】:Rails: Created params not saving correctlyRails:创建的参数未正确保存
【发布时间】:2019-01-26 23:37:06
【问题描述】:

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

这是我的开始: 架构.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

这是我在种子.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 字符串,而是作为作者页面的直接链接。这个错误弄乱了我的应用程序的其他部分,我已经困惑了几天了。有人可以帮忙吗?

【问题讨论】:

  • 我认为您在图书模型中有 has_one :author 关联,因此当您通过选择任何特定的作者 ID 创建图书时,不需要额外的字段“author_name”属性,它将与作者相关联因此您可以使用 @book.author.name 或使用 Book 模型中的委托。您是否尝试过这种方法,而不是添加额外的属性

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


【解决方案1】:

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

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

def author_name
  self.author.name
end

这应该可以工作

【讨论】:

  • 感谢您的回复。我试过这个,但现在我得到的是: 标题:Ruby Programming 作者:1 所以现在它只是显示 ID。
  • 你从哪里得到的?
  • 好吧,另外一件事,如果 book 表中有 author_id,则必须在 book 模型中使用 belongs_to 而不是 has_one...
  • 谢谢,多亏了你的建议,我终于让它工作了!
  • 或者delegate :name, to: :author, prefix: true, allow_nil: true
【解决方案2】:

有两种方法可以解决此问题:

before_create :set_author_name

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

希望这会有所帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多