Rails 4的has_one关联表单无法生成

14

我需要一些关于Rails 4如何使用has_one和belongs_to关联的指导。

我的表单无法保存has_one的关系。

Post模型

class Post < ActiveRecord::Base
  validates: :body, presence: true

  has_one :category, dependent: :destroy
  accepts_nested_attributes_for :category
end

class Category < ActiveRecord::Base
  validates :title, presence: true
  belongs_to :post
end

文章控制器

class PostController < ApplicationController
  def new
    @post = Post.new
    @post.build_category
  end

  def create
    @post = Post.new(post_params)
  end

  private

  def post_params
    params.require(:post).permit(:body)
  end
end

在“提交新文章”操作中的表单

<%= form_for @post do |form| %>

  <%= form.label :body %>
  <%= form.text_area :body %>

  <%= fields_for :category do |category_fields| %>
    <%= category_fields.label :title %>
    <%= category_fields.text_field :title %>
  <% end %>

  <%= form.button "Add Post" %>

<% end %>

提交文章表单时,未能保存分类标题。

调试参数

utf8: 
authenticity_token: 08/I6MsYjNUhzg4W+9SWuvXbSdN7WX2x6l2TmNwRl40=
post: !ruby/hash:ActionController::Parameters
  body: 'The best ice cream sandwich ever'
category: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  title: 'Cold Treats'
button: ''
action: create
controller: posts

应用程序日志

Processing by BusinessesController#create as HTML
  Parameters: {"utf8"=>"✓",
               "authenticity_token"=>"08/I6MsYjNUhzg4W+9SWuvXbSdN7WX2x6l2TmNwRl40=",
               "post"=>{"body"=>"The best ice cream sandwich ever"},
               "category"=>{"title"=>"Cold Treats", "button"=>""}

在Rails控制台中..我可以成功地运行以下命令

> a = Post.new
=> #<Post id: nil, body: "">
> a.category
=> nil

> b = Post.new
=> #<Post id: nil, body: "">
> b.build_category
=> #<Post id: nil, title: nil>
> b.body = "The best ice cream sandwich ever"
=> "The best ice cream sandwich ever"
> b.category.title = "Cold Treats"
=> "Cold Treats"

我关心的问题与如何解决此问题有关:

  1. 我不确定是否需要在post_params强参数方法中添加:category_attributes
  2. 日志和调试参数是否应该显示Category属性嵌套在Post参数内部?
  3. Category哈希参数中有一个空白的button键,而我的fields_for中没有,我在使用表单助手时漏掉了什么吗?
  4. 原因是因为创建操作没有采用build_category方法,我需要将其添加到创建操作中吗?
  5. Category模型(presence:true)的验证是否会自动用于Post表单?

提前感谢。

更新:在fields_for块内缺少category_fields

2个回答

16

问题 #1:是的,你需要像这样在post_params强参数方法中添加:category_attributes

def post_params
  params.require(:post).permit(:body, category_attributes: [:title])
end
问题2:是的,参数应该是嵌套的。您的观点中存在一个错别字,因为您没有将fields_for(复数形式)应用于父表单构建器的作用域中,而且您没有在fields_for块内使用category_fields表单构建器!

视图应该像这样:

<%= form_for @post do |form| %>

  <%= form.label :body %>
  <%= form.text_area :body %>

  <%= form.fields_for :category do |category_fields| %>
    <%= category_fields.label :title %>
    <%= category_fields.text_field :title %>
  <% end %>

  <%= form.button "Add Post" %>

<% end %>

第三个问题:由于视图中混乱的表单构建,按钮参数可能放在错误的位置。

第四个问题:如果您接受嵌套属性,则不需要在创建操作中构建子模型。

第五个问题:是的,子模型的验证也会运行,如果子模型的验证失败,父模型也会出现错误,并且不会保存到数据库中。


2
Sled,您真是位绅士。感谢您指出我的错误。我一直在看同一个表格,却不知道我需要在fields_for块中添加form.builder。再次感谢您澄清强参数嵌套属性。我非常感谢您花时间回答我所有的问题。谢谢! :) - Wasabi Developer

2

@sled你是对的。但是对于未来的Rails 4.1,加粗(**)将被弃用。

def post_params
  params.require(:post).permit **(:body, :category_attributes => [:title])**
end

被加粗的文本将会被强制加粗 (:body, category_attributes: [:title])


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接