我正在我的博客应用程序中使用 Rails 5
find_or_initialize
,该应用程序在输入文本字段中输入了帖子和类别。
后模型
# == Schema Information
#
# Table name: posts
#
# id :integer not null, primary key
# title :string default(""), not null
# body :text default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
# category_id :integer
class Post < ApplicationRecord
validates :title, :body, :category, presence: true
has_one :category
accepts_nested_attributes_for :category
end
类别模型
# == Schema Information
#
# Table name: category
#
# id :integer not null, primary key
# name :string default(""), not null
# created_at :datetime not null
# updated_at :datetime not null
class Category < ApplicationRecord
validates :name, presence: true
validates :name, length: { in: 3..80 }
has_many :posts
end
在控制台中,我可以执行以下操作:
post = Post.new(title: "Hello Stack Overflow", body: "How are you today?")
post.category = Category.find_or_initialize_by(name: "Greetings")
post.save
post.last
=> #<Post:0x007fd34fa21a23
id: 42,
title: "Hello Stack Overflow",
body: "How are you today?",
created_at: Mon, 25 Jul 2016 12:56:39 UTC +00:00,
updated_at: Mon, 25 Jul 2016 12:56:39 UTC +00:00,
category_id: 3>
Post 表单如下所示:
<%= form_for @post do |f| %>
<fieldset>
<%= f.label "Title" %>
<%= f.text_field :body %>
</fieldset>
<fieldset>
<%= f.fields_for :category do |category_fields|
<%= f.label "Category" %>
<%= category_fields.text_field :name %>
<% end %>
</fieldset>
<% end %>
我的麻烦是试图获取类别字段中输入的内容_for 输入到 Post 模型中以使用
find_or_initialize
。
我试过以下方法:
class Post < ApplicationRecord
before_save :generate_category?
has_one :category
accepts_nested_attributes_for :category
private
def generate_category?
self.category = Category.find_or_initialize_by(name: name)
end
end
这失败了,我得到一个
NameError
错误:
NameError in PostController#create
undefined local variable or method `name' for #<Listing:0x007fc3d9b48a48>
我的问题是:
nested_attributes
? before_save
任何关于我如何编写代码的提示都将不胜感激。
name
不是后模型上的方法,而是类别一上的方法。由于尚未定义类别,因此您也不能真正依赖调用:self.category.name
。您需要以其他形式定义名称值。现在,如果您打算使用 accepts_nested_attributes_for
,您应该能够完全放弃该方法,而只需让数据的哈希值包含类别名称:
{ title: 'Post Title', category: { name: 'blog' } }
如果你不走那条路,你应该设置一个传统的公共方法来通过将参数传递给这个方法来创建类别,而不是使用活动记录回调。此外,由于
find_or_initialize()
将返回一个对象,因此使用谓词方法没有多大意义。 generate_category?
应该变成generate_category