我希望有人可以帮助指导我以最好的方式做到这一点。我正在设置一个注册表单,供人们列出他们在各种工作中的技能/证书
Schema 使用 Mongoid 和 Inheritance 遵循这些思路
class Person
include Mongoid::Document
field :name, :type => String
field :education, :type => String
end
class Accountant < Person
field :cpa, :type => Boolean
field :active_cpa, :type => Boolean
end
class SoftwareDeveloper < Person
field :full_stack, :type => Boolean
field :language, :type => Array
end
所以用户会来到一个注册页面 mysite.com/persons/new 那里会有一个表格来选择各种工作(按不同行业列出和分组:金融、工程、营销)并根据用户的选择,将显示特定于该工作职能的更详细 View 。 (例如,软件开发人员可以列出编程语言,会计师可以列出是否有注册会计师)。
我的问题是,在 Controller 和 View 层中处理此问题的最佳方法是什么?我涵盖了大约 100 种不同的工作职能,所以我想结合 Controller 和 View ,而不是将用户重定向到 mysite.com/accountants/new 或 mysite.com/engineers/new 并为每个都有一个 Controller / View 具体工作。
有人可以帮助指导我解决这个问题的最佳方法吗?我知道我将不得不使用 jQuery,也许还有一些 ajax 调用来呈现详细的表单,但是我该如何处理 Controller ,因为 form_for 首先与用户相关联并且那里的模型具有有限的属性,所以我不确定如何获取参数并将它们传递到参数散列中,并验证更具体的作业
最佳答案
我最近遇到了这样的问题。我最终在基本类型上使用 form_for 设置了我的表单,在你的例子中是 Person 。在表单中,我为基本字段创建了一个字段集,并创建了单独的字段集标签来表示每个子类中可用的额外字段,如下所示:
<%= form_for @person do |f| %>
<fieldset id="base">
<%= f.label :name %>
<%= f.check_box :name %>
<!-- ... -->
</fieldset>
<fieldset id="accountant">
<%= fields_for :accountant do |f| %>
<%= f.label :cpa %>
<%= f.check_box :cpa %>
<!-- ... -->
<% end %>
</fieldset>
<fieldset id="software_developer">
<%= fields_for :software_developer do |f| %>
<%= f.label :full_stack %>
<%= f.check_box :full_stack %>
<!-- ... -->
<% end %>
</fieldset>
使用 fields_for 将导致表单 POST 在 Controller 中提供您的“创建”方法,参数如下:
params[:person] = { :name => "Joe Smith", ... }
params[:accountant] = { :cpa => true, ... }
params[:software_developer] = { :full_stack => false, ... }
在您的表单中,您还需要某种方式来指定工作类型。就我而言,我使用了一个简单的选择标签:
<%= select_tag :job_type, options_for_select(@job_types) %>
这将在您的 Controller 中为您提供 params[:job_type]。从那里,“创建”方法需要确定用户选择的作业类型,然后创建正确的子类并使用提供的参数。我为此使用了一个案例陈述:
case params[:job_type]
when :accountant
@person = Accountant.new(params[:person].merge(params[:accountant]))
when :software_developer
@person = SoftwareDeveloper.new(params[:person].merge(params[:software_developer]))
when ...
end
如果您有很多子类,那么可扩展性可能不是很好。所以你可以做的是安排 params[:job_type] 为你提供要创建的类的名称作为表单提交的值。然后你可以这样做:
@person = params[:job_type].constantize.new(params[:person].merge(params[params[:job_type].underscore])
此代码使用作业类型字段转换为类名,然后再次为子类找到正确的字段。
最后,您需要使用一些 jQuery 来在用户选择不同的作业类型时隐藏和显示不同的字段集。为此,将 .change() 处理程序附加到 select_tag 元素并使其隐藏所有字段集,然后显示一个具有与所选作业类型匹配的“id”的字段集。如果您需要示例代码,请告诉我。
作为画龙点睛之笔,您可能会考虑以部分方式呈现特定于作业的字段集,以便您的主窗体只需进行一系列调用即可呈现所有不同类型的作业。
我不知道是否有更好的方法来做到这一点,但这种方法对我来说非常有效,它允许我有一个 Controller 和一组 View 来管理整个父/子子类的创建和编辑树。
关于ruby-on-rails - 基于用户输入的动态表单和模型创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10637172/