首页 > 解决方案 > 复杂 Rails 表单最佳实践

问题描述

我有一个相对复杂的表单,我正在尝试有效地编写代码。大多数嵌套表单的在线示例都处理非常清晰的层次关系,我的没有。

下面是数据模型。表单的基本工作是创建一个“工作条目”记录,同时创建一个新的“实体”记录 - 这是一个人。几种关系以这种形式出现。

已创建“作业”。在用户点击此表单之前,作业有一对多的“问题”。但是,他们必须填写问题的“答案”。他们还选择许多预先创建的“工作角色”之一。

数据模型

问题是如何为所有这些相互关联的模型利用“form_with”和“fields_for”。

我的假设是放弃内置的帮助程序,只使用 form_tag 并手动将所有内容滚动在一起。但也许有一种“正确”的方式来滚动不一定遵守亲子关系的表格?在我的示例中,由于许多子对象已经有记录,所以没有纯顶级对象开始,但也许我错了,实体应该是起点?

标签: ruby-on-railsforms

解决方案


Mike 提出的嵌套表单是解决您问题的一种方式。没关系 - 但对于复杂的表单,有很多验证,它可能不是最好的解决方案)。您可以考虑改用 FormObject 模式。

FormObject 是一个简单的 ruby​​ 类,你可以将它保存在Forms文件夹中并使用如下:

class JobEntryForm
  include ActiveModel::Model

  attr_accessor :customer_id, :agency_id, :name, :question_text #you can use atributes from different models

  validates :customer_id, presence: true #you can validate yu attributes as you want - your in necessity to use model validation

  def initialize(attributes:)
    @customer_id = attributes[:customer_id]
    @agency_id        = attributes[:agency_id]
    @name          = attributes[:name]
    @question_text = attributes[:question_text]
  end
  

  #implement whatever you need
end

比你的控制器: @form = JobEntryForm.new

你的看法:

<%= form_for @form do |f| %>
  <%= f.label :customer_id, 'Customer' %>:
  <%= f.text_field :customer_id %>
  ...
  <%= f.submit %>
<% end %>

并且 - 最后 - 在您的控制器创建方法中:

def create
  @form = CreateJobEntry.new.call(attributes: form_params) #service object to keep your controller clean. 
end

推荐阅读