嵌套表单不呈现或保存数据
Nested Form not rendering or saving data
我是 Ruby 和 Rails 的新手,我正在尝试组合一个嵌套表单,最终创建一个页面,但也允许用户创建单独的部分 inline 在提交页面之前。内联表单包含两个按钮,一个添加零件,另一个删除零件。这是我的相关文件(如果您需要查看任何其他文件,请告诉我)我将列出我遇到的问题:
仅供参考,我使用的 gem 是:Slim, Simple Form, cocoon 和 Bootstrap。在 Rails 4.
_form.html.slim
= simple_form_for(@page, html: { class: 'form-horizontal' }) do |f|
= f.input :title, label: 'Title'
= f.input :description, label: 'Desc'
.form-group
.col-xs-10
label Parts
.form-inline
= f.simple_fields_for :parts do |part|
= render 'part_fields', f: part
.links
= link_to_add_association 'Add Part', f, :parts
= f.button :submit
_parts_fields.html.slim
= f.input :part_type, collection: ['String 1', 'String 2'], prompt: 'Part type', label: false
= f.input :part_title, placeholder: 'Part title', label: false
= f.input :part_desc, placeholder: 'Part description', label: false
= link_to_remove_association 'Remove Part', f
/models/page.rb
class Page < ActiveRecord::Base
belongs_to :project
has_many :parts
accepts_nested_attributes_for :parts
end
/models/part.rb
class Part < ActiveRecord::Base
belongs_to :page
end
/controllers/pages_controller.rb
class PagesController < ApplicationController
def index
@pages = Page.all
respond_to do |format|
format.html
format.json { render json: @pages }
end
end
def new
@page = Page.new
respond_to do |format|
format.html
format.json { render json: @page }
end
end
def edit
@page = Page.find(params['id'])
end
def create
@page = Page.new(page_params)
respond_to do |format|
if @page.save
format.html { redirect_to(@page) }
format.json { render json: @page, status: :created, location: @page }
else
format.html { render action: 'new' }
format.json { render json: @page.errors, status: :unprocessable_entity }
end
end
end
def update
@page = Page.find(params['id'])
respond_to do |format|
if @page.update_attributes(page_params)
format.html { redirect_to(action: 'index') }
format.json { head :ok }
else
format.html { render action: 'edit' }
format.json { render json: @page.errors, status: :unprocessable_entity }
end
end
end
def page_params
params.require(:page).permit(:title, :description, parts_attributes: [:id, :part_type, :part_title, :part_desc])
end
end # End Pages Controller
路线
resources :projects do
resources :pages
end
resources :pages
resources :parts
问题:
1) 表单未保存任何数据(无法 edit/update 当前页面或创建新页面)。 更新:已修复,请参阅下面我自己的回答。
2) 部分我使用 collection
来创建下拉菜单,但这些测试值现在是硬编码的。我怎样才能有一个下拉菜单,用数据库中的列填充每个字段?
3) 来自部分的内联表单元素没有在主表单上呈现。我所看到的只是 "Parts" 标签,它下面没有任何元素。 更新:@pages.parts.build
解决了这个问题。
感谢你们能给我的任何帮助。
您有一个没有 parts
的 @page
对象。因此,当它尝试渲染 fields_for
时,它确实如此!只是,零次。在您的控制器中添加 @page.parts.build
以添加一个。
不确定;现在太累了。尝试将 save
更改为 save!
,将 update_attributes
更改为 update!
,以便 Rails 抛出错误而不是静默失败。顺便说一句,为什么你的 page_params
里面有 if params[:page]
?那是不需要的;这就是 require(:page)
所做的。
ActiveRecord提供了一个column_names方法,即returns一个列名数组。
实际上,@page.parts.build
将始终构建一个新的 part
,即使用户没有请求(这可能是您想要的)。现在您只为每个嵌套部分显示 Add
按钮。我假设您只需要一个 Add
按钮,如下所示:
.form-inline
= f.simple_fields_for :parts do |part|
= render 'parts_fields', f: part
= link_to_add_association 'Remove Part', f, :parts
= link_to_add_association 'Add Part', f, :parts
这将始终显示 Add Part
link(并且只显示一次)。
至于没有保存,可能的原因是:
- 数据未发布到服务器(检查您的日志文件,可能的原因是您的 html 中的错误,例如多个相同的 ID)
- 您的强参数命令阻止了数据
- 数据被
accepts_nested_attributes_for
的 reject_if
条件阻塞
- 验证失败
现在,如果显示的代码是您的实际代码,则一切正常。那么你能告诉我们发布到服务器上的内容吗? (检查您的日志文件)。
表单现在正在按预期保存数据。在我的一个部分中,我有两个相同的领域,因此对我造成了无声的冲突。此外,在解决此问题后,我开始收到 Unpermitted parameter: _destroy
错误,解决方法是将 :_destroy
添加到 parts_attributes
所需的参数列表中。
我是 Ruby 和 Rails 的新手,我正在尝试组合一个嵌套表单,最终创建一个页面,但也允许用户创建单独的部分 inline 在提交页面之前。内联表单包含两个按钮,一个添加零件,另一个删除零件。这是我的相关文件(如果您需要查看任何其他文件,请告诉我)我将列出我遇到的问题:
仅供参考,我使用的 gem 是:Slim, Simple Form, cocoon 和 Bootstrap。在 Rails 4.
_form.html.slim
= simple_form_for(@page, html: { class: 'form-horizontal' }) do |f|
= f.input :title, label: 'Title'
= f.input :description, label: 'Desc'
.form-group
.col-xs-10
label Parts
.form-inline
= f.simple_fields_for :parts do |part|
= render 'part_fields', f: part
.links
= link_to_add_association 'Add Part', f, :parts
= f.button :submit
_parts_fields.html.slim
= f.input :part_type, collection: ['String 1', 'String 2'], prompt: 'Part type', label: false
= f.input :part_title, placeholder: 'Part title', label: false
= f.input :part_desc, placeholder: 'Part description', label: false
= link_to_remove_association 'Remove Part', f
/models/page.rb
class Page < ActiveRecord::Base
belongs_to :project
has_many :parts
accepts_nested_attributes_for :parts
end
/models/part.rb
class Part < ActiveRecord::Base
belongs_to :page
end
/controllers/pages_controller.rb
class PagesController < ApplicationController
def index
@pages = Page.all
respond_to do |format|
format.html
format.json { render json: @pages }
end
end
def new
@page = Page.new
respond_to do |format|
format.html
format.json { render json: @page }
end
end
def edit
@page = Page.find(params['id'])
end
def create
@page = Page.new(page_params)
respond_to do |format|
if @page.save
format.html { redirect_to(@page) }
format.json { render json: @page, status: :created, location: @page }
else
format.html { render action: 'new' }
format.json { render json: @page.errors, status: :unprocessable_entity }
end
end
end
def update
@page = Page.find(params['id'])
respond_to do |format|
if @page.update_attributes(page_params)
format.html { redirect_to(action: 'index') }
format.json { head :ok }
else
format.html { render action: 'edit' }
format.json { render json: @page.errors, status: :unprocessable_entity }
end
end
end
def page_params
params.require(:page).permit(:title, :description, parts_attributes: [:id, :part_type, :part_title, :part_desc])
end
end # End Pages Controller
路线
resources :projects do
resources :pages
end
resources :pages
resources :parts
问题:
1) 表单未保存任何数据(无法 edit/update 当前页面或创建新页面)。 更新:已修复,请参阅下面我自己的回答。
2) 部分我使用 collection
来创建下拉菜单,但这些测试值现在是硬编码的。我怎样才能有一个下拉菜单,用数据库中的列填充每个字段?
3) 来自部分的内联表单元素没有在主表单上呈现。我所看到的只是 "Parts" 标签,它下面没有任何元素。 更新:@pages.parts.build
解决了这个问题。
感谢你们能给我的任何帮助。
您有一个没有
parts
的@page
对象。因此,当它尝试渲染fields_for
时,它确实如此!只是,零次。在您的控制器中添加@page.parts.build
以添加一个。不确定;现在太累了。尝试将
save
更改为save!
,将update_attributes
更改为update!
,以便 Rails 抛出错误而不是静默失败。顺便说一句,为什么你的page_params
里面有if params[:page]
?那是不需要的;这就是require(:page)
所做的。ActiveRecord提供了一个column_names方法,即returns一个列名数组。
实际上,@page.parts.build
将始终构建一个新的 part
,即使用户没有请求(这可能是您想要的)。现在您只为每个嵌套部分显示 Add
按钮。我假设您只需要一个 Add
按钮,如下所示:
.form-inline
= f.simple_fields_for :parts do |part|
= render 'parts_fields', f: part
= link_to_add_association 'Remove Part', f, :parts
= link_to_add_association 'Add Part', f, :parts
这将始终显示 Add Part
link(并且只显示一次)。
至于没有保存,可能的原因是:
- 数据未发布到服务器(检查您的日志文件,可能的原因是您的 html 中的错误,例如多个相同的 ID)
- 您的强参数命令阻止了数据
- 数据被
accepts_nested_attributes_for
的 - 验证失败
reject_if
条件阻塞
现在,如果显示的代码是您的实际代码,则一切正常。那么你能告诉我们发布到服务器上的内容吗? (检查您的日志文件)。
表单现在正在按预期保存数据。在我的一个部分中,我有两个相同的领域,因此对我造成了无声的冲突。此外,在解决此问题后,我开始收到 Unpermitted parameter: _destroy
错误,解决方法是将 :_destroy
添加到 parts_attributes
所需的参数列表中。