Rails: 如何将嵌套表单保存到不同的嵌套模型中?
Rails: How to have a nested form save to different nested models?
上下文:
我有一个 Company
模型,其中有很多 projects
。每个 project
有许多 tasks
。 company
有很多 employees
。
Employee
属于Company
,有很多tasks
。每个任务是一名员工,一名员工每个 project
.
将只有一名 task
架构:
问题:
我正在构建一个表单来创建一个项目,用户可以在其中添加多个 tasks
。每个任务都指定了 hours
的数量,并且 employee
执行了 task
。提交后,表单应创建一个 project
记录,一个或多个具有 hours
和 employee_id
属性的 task
记录,并(!)检查 employee
名称已存在于数据库中或创建一个新的。
我正在努力解决如何让表单保存 employee_id
而不是 employee_name
。
代码:
我的表格如下:
<%= simple_nested_form_for @project do |f| %>
<%= f.input :project_details %>
<%= f.simple_fields_for :tasks do |task| %>
<%= task.input :employee_name, input_html: { data: { autocomplete_source: @queried_employee_names.to_json } } %>
<%= task.input :hours %>
<% end %>
<%= f.link_to_add "Add +", :tasks %>
<%= f.button :submit %>
<% end %>
我的控制器:
class TransactionsController < ApplicationController
def new
@project = current_company.projects.build
end
def create
@project = current_company.projects.new(project_params)
if @project.save
employee_save
redirect_to success_url
else
@project = current_company.projects.build
render :new
end
end
# save the employees not yet in the database
def employee_save
@project.tasks.each do |task|
if current_company.employees.where(name: task.employee_name).empty?
current_company.employees.new(name: task.employee_name).save
end
end
end
def project_params
params.require(:project).permit(:project_details, tasks_attributes: [:id, :employee_name, :hours, :_destroy])
end
end
问题:
不幸的是,这会将 tasks
table 保存到 employee_name
而不是 employee_id
(加上将新的 employee_name
写入 employees table
).当然,tasks
table 应该只包含 employee_ids
和 employee
table names
.
关于如何解决这个问题有什么建议吗?
我会在如下表单中添加一个隐藏字段:
<%= simple_nested_form_for @project do |f| %>
<%= f.input :project_details %>
<%= f.simple_fields_for :tasks do |task| %>
<%= task.input :employee_name, input_html: { data: { autocomplete_source: @queried_employee_names.to_json } } %>
<%= task.hidden_field :employee_id, '' %>
<%= task.input :hours %>
<% end %>
<%= f.link_to_add "Add +", :tasks %>
<%= f.button :submit %>
<% end %>
此字段必须通过 Ajax 填写。我看到您的 :employee_name
输入字段中有一个自动完成源,那么当您 select 员工时,您可以在那里添加一个事件,并通过 Ajax 获取 ID 并填充隐藏字段selected 员工的 ID,这样您就可以轻松地在 create
操作中保存该数据。
上下文:
我有一个 Company
模型,其中有很多 projects
。每个 project
有许多 tasks
。 company
有很多 employees
。
Employee
属于Company
,有很多tasks
。每个任务是一名员工,一名员工每个 project
.
task
架构:
问题:
我正在构建一个表单来创建一个项目,用户可以在其中添加多个 tasks
。每个任务都指定了 hours
的数量,并且 employee
执行了 task
。提交后,表单应创建一个 project
记录,一个或多个具有 hours
和 employee_id
属性的 task
记录,并(!)检查 employee
名称已存在于数据库中或创建一个新的。
我正在努力解决如何让表单保存 employee_id
而不是 employee_name
。
代码:
我的表格如下:
<%= simple_nested_form_for @project do |f| %>
<%= f.input :project_details %>
<%= f.simple_fields_for :tasks do |task| %>
<%= task.input :employee_name, input_html: { data: { autocomplete_source: @queried_employee_names.to_json } } %>
<%= task.input :hours %>
<% end %>
<%= f.link_to_add "Add +", :tasks %>
<%= f.button :submit %>
<% end %>
我的控制器:
class TransactionsController < ApplicationController
def new
@project = current_company.projects.build
end
def create
@project = current_company.projects.new(project_params)
if @project.save
employee_save
redirect_to success_url
else
@project = current_company.projects.build
render :new
end
end
# save the employees not yet in the database
def employee_save
@project.tasks.each do |task|
if current_company.employees.where(name: task.employee_name).empty?
current_company.employees.new(name: task.employee_name).save
end
end
end
def project_params
params.require(:project).permit(:project_details, tasks_attributes: [:id, :employee_name, :hours, :_destroy])
end
end
问题:
不幸的是,这会将 tasks
table 保存到 employee_name
而不是 employee_id
(加上将新的 employee_name
写入 employees table
).当然,tasks
table 应该只包含 employee_ids
和 employee
table names
.
关于如何解决这个问题有什么建议吗?
我会在如下表单中添加一个隐藏字段:
<%= simple_nested_form_for @project do |f| %>
<%= f.input :project_details %>
<%= f.simple_fields_for :tasks do |task| %>
<%= task.input :employee_name, input_html: { data: { autocomplete_source: @queried_employee_names.to_json } } %>
<%= task.hidden_field :employee_id, '' %>
<%= task.input :hours %>
<% end %>
<%= f.link_to_add "Add +", :tasks %>
<%= f.button :submit %>
<% end %>
此字段必须通过 Ajax 填写。我看到您的 :employee_name
输入字段中有一个自动完成源,那么当您 select 员工时,您可以在那里添加一个事件,并通过 Ajax 获取 ID 并填充隐藏字段selected 员工的 ID,这样您就可以轻松地在 create
操作中保存该数据。