Ruby on rails 为STI模型创建表单

Ruby on rails 为STI模型创建表单,ruby-on-rails,ruby,rails-activerecord,sti,Ruby On Rails,Ruby,Rails Activerecord,Sti,关于这篇文章: 使用STI和存储功能的组合来组织非常相似的模型。 “使用名为“设置”的文本列为学生声明基本模型 class Student < ActiveRecord::Base store :settings # name, email, phone, address etc.. end class HighSchoolStudent < Student # declare HighSchoolStudent specific attributes store

关于这篇文章:

使用STI和存储功能的组合来组织非常相似的模型。

“使用名为“设置”的文本列为学生声明基本模型

class Student < ActiveRecord::Base
  store :settings
  # name, email, phone, address etc..
end

class HighSchoolStudent < Student
  # declare HighSchoolStudent specific attributes 
  store_accessor :settings, :gpa
end
class-Student
如何在学生控制器的控制下为高中生创建表单

我不想为高中生添加单独的控制器或路由资源,有没有一种方法可以为学生和高中生创建一个表单,并带有一个复选框来指示它是学生还是高中生?我可以只要求为子类创建的额外属性仅在是否检查了特定的类

<%= simple_form_for(@student, html: {class: "form-horizontal"}) do |f| %>


当然,您可以创建任意复选框,并在创建操作中检查其值:

# In your view
<%= check_box_tag :high_school %>

# In your controller
def create
  base_class = params[:high_school] ? HighSchoolStudent : Student
  base_class.create(params[:student])
  ...
end
#在您的视图中
#在控制器中
def创建
基本类=参数[:高中]?高中生:学生
基本类。创建(参数[:学生])
...
结束

只有选中复选框,才能确保针对高中生的任何验证。

当然,您可以创建任意复选框,并在创建操作中检查其值:

# In your view
<%= check_box_tag :high_school %>

# In your controller
def create
  base_class = params[:high_school] ? HighSchoolStudent : Student
  base_class.create(params[:student])
  ...
end
#在您的视图中
#在控制器中
def创建
基本类=参数[:高中]?高中生:学生
基本类。创建(参数[:学生])
...
结束

只有选中复选框,才能确保针对高中学生的任何验证。

Rails STI使用
type
特殊列存储类名。
Student.new(type:'highschoolstudio')
将构建一个
Student
,该学生稍后将充当
highschoolstudion

此解决方案不会运行仅为
高中生定义的验证、回调等,而是运行
学生
中的所有内容

要做到这一点,您可以执行@PinnyM建议的操作,也可以使用它来确定要创建的正确类,这确实为您购买了所有的验证和回调,同时由于它使用了正确的属性而更易于维护


所有这些都表明,STI可能是错误的解决方案

我是否可以只要求为子类创建的额外属性仅在选中特定类的情况下提交表单才需要

<%= simple_form_for(@student, html: {class: "form-horizontal"}) do |f| %>
这告诉我,您在
学生
表中添加了与非高中生无关的属性


一个更好的解决方案可能是使用一个类,如
HighSchoolStudentProfile
作为关联,并在学生身上使用一个方法
HighSchooler?
,检查其存在性。这可以防止您遇到我以前遇到的问题,即“稀疏表”它通常需要各种条件验证,并且具有复杂的逻辑。

Rails STI使用
type
特殊列存储类名
Student.new(键入:“HighSchoolStudent”)
将构建一个
Student
,该学生稍后将充当
HighSchoolStudent

此解决方案不会运行仅为
高中生定义的验证、回调等,而是运行
学生
中的所有内容

要做到这一点,您可以执行@PinnyM建议的操作,也可以使用它来确定要创建的正确类,这确实为您购买了所有的验证和回调,同时由于它使用了正确的属性而更易于维护


所有这些都表明,STI可能是错误的解决方案

我是否可以只要求为子类创建的额外属性仅在选中特定类的情况下提交表单才需要

<%= simple_form_for(@student, html: {class: "form-horizontal"}) do |f| %>
这告诉我,您在
学生
表中添加了与非高中生无关的属性


一个更好的解决方案可能是使用一个类似于
HighSchoolStudentProfile
的类作为关联,并在学生身上使用一个方法
HighSchooler?
检查其存在性。这可以防止您遇到我以前遇到的问题,即“稀疏表”,通常需要各种条件验证,并且逻辑复杂。

您应该将问题中的“from”重命名为“form”。您应该将问题中的“from”重命名为“form”。我得到了错误“undefined method`gpa'”我如何让表单知道这是针对学生和高中生的,看起来它没有识别高中生的属性。你能看看问题中的上面表单吗,我刚刚添加了它,我得到了错误“undefined method`gpa”“我如何让表单知道这是针对学生和高中生的,它似乎没有识别高中生的属性一个简单的解决方法是加载
@Student=highschoolstuent.new
在你的
new
操作中,因为高中生保证拥有所有属性。如果这对您不起作用,您需要将它们创建为通用的“非关联”字段,而不是使用
f.input
,然后将它们合并回您的创建操作中。谢谢!我得到一个高中生路径错误,我应该在路径文件中输入什么?我想让高中生走上Students@KatieHeidmann:将路径添加到表单:
我收到错误“undefined method`gpa'”。如何让表单知道这是针对学生和高中生的,看起来它没有识别高中生的属性。你能看一下问题中上面的表格吗,我刚刚添加了它,我得到了错误“undefined method`gp”