Ruby on rails 如何实例化两侧都具有多态关联/验证的Rails模型?
在过去的两个小时里,我一直在为这个问题绞尽脑汁。我有两个多态链接的类。医生有医生的东西在他们和用户处理的网络组件电子邮件地址,设计等。医生是一个用户 原因是有不同的用户类别护士、医疗机构,它们都需要自己的字段,但由于它们是用户,所以它们相互关联。所以我在本例中选择了多态关联 问题是我似乎无法同时实例化它们,因为它们都没有被保存。假设一个空数据库,由于它们彼此需要,我如何准确地创建它们?有没有一种方法可以同时保存两者Ruby on rails 如何实例化两侧都具有多态关联/验证的Rails模型?,ruby-on-rails,factory-bot,polymorphic-associations,Ruby On Rails,Factory Bot,Polymorphic Associations,在过去的两个小时里,我一直在为这个问题绞尽脑汁。我有两个多态链接的类。医生有医生的东西在他们和用户处理的网络组件电子邮件地址,设计等。医生是一个用户 原因是有不同的用户类别护士、医疗机构,它们都需要自己的字段,但由于它们是用户,所以它们相互关联。所以我在本例中选择了多态关联 问题是我似乎无法同时实例化它们,因为它们都没有被保存。假设一个空数据库,由于它们彼此需要,我如何准确地创建它们?有没有一种方法可以同时保存两者 class User < ActiveRecord::Base rol
class User < ActiveRecord::Base
rolify
devise :database_authenticatable, :registerable,
:recoverable, :rememberable, :trackable, :validatable
validates_presence_of :profile
belongs_to :profile, polymorphic: true
end
class Doctor < ActiveRecord::Base
has_one :user, as: :profile, dependent: :destroy
accepts_nested_attributes_for :user
validates_presence_of :user
# doctor-specific code here
delegate :email, :password, to: :user
end
class Nurse < ActiveRecord::Base
# has_one, accepts... same as doctor. nurse-specific code here
end
如果有人能解决如何在FactoryGirl中使用此工具,我也将不胜感激
旁白:我已经看到了,但它们的两面都没有验证。您可以跳过第一条记录的验证:
your_record.save(validate: false)
编辑:
实际上,您不需要跳过验证。它不工作的原因可能是因为验证检查的存在,以查看数据库中是否存在关联的对象。因此,对于医生、护士等来说,这样做是可以的,因为这些表没有存储用户id。但是您应该更改用户模型的验证以检查:
validates :profile_id, presence: true
这将确保配置文件_id属性被分配,即使配置文件医生、护士等还不存在。您必须按照正确的顺序创建对象,但:
u = User.new
d = Doctor.new
u.profile = d
u.save # it should be happy at this point because profile_id should be set
d.save
将护士/医生类型存储为用户的资源,并为用户设置控制器
class User
#resource will be nurse/doctor etc
belongs_to :resource, polymorphic: true, dependent: :destroy
accepts_nested_attributes_for :resource
#add user specific validations here
end
#user will be either doctor or nurse and not both
class Doctor
has_one :user, as :resource
#add doctor specific validations
end
class Nurse
has_one :user, as :resource
#add nurse specific validations
end
现在,当您创建医生/护士类型的用户时,您可以要求用户选择类型,并根据选择为所选类型呈现嵌套表单。您可以直接在用户表单中呈现这两种类型的嵌套表单,也可以在用户选择类型时使用ajax添加它们
haml中的示例表格如下所示“资源_字段”是一个html id
= form_for @user ...
= #user specific fields go here
= #show dropdown to select type and send ajax with type to render type specific form.
- if @user.resource.nil? #if resource is not set
#resource_fields
- else #if resource is present
= render 'users/doctor_form', f: f if @user.resource.is_a? Doctor
= render 'users/nurse_form', f: f if @user.resource.is_a? Nurse
响应ajax类型表单的控制器方法
def get_type_form
@user = User.new
@user.resource = case params[:selected_type]
when "Doctor"
Doctor.new
when 'Nurse'
Nurse.new
end
end
在get_form_type.js.haml中
:plain
- if @user.resource.is_a? Doctor
$('#resource_fields').replaceWith("#{escape_javascript(render partial: 'users/doctor_form', locals: { f: nil })}");
- if @user.resource.is_a? Nurse
$('#resource_fields').replaceWith("#{escape_javascript(render partial: 'users/nurse_form', locals: { f: nil })}");
医生表格的部分内容如下:
#resource_fields
- if f.nil?
= fields_for "user[resource_attributes]", @user.resource do |doctor|
= render 'users/doctor_fields', :doctor: doctor
- if f
= f.fields_for :resource, @user.resource do |doctor|
= render 'users/doctor_fields', doctor: doctor
= doctor.text_field :degree
= doctor.text_field :specialization
而doctor_fields的部分
#resource_fields
- if f.nil?
= fields_for "user[resource_attributes]", @user.resource do |doctor|
= render 'users/doctor_fields', :doctor: doctor
- if f
= f.fields_for :resource, @user.resource do |doctor|
= render 'users/doctor_fields', doctor: doctor
= doctor.text_field :degree
= doctor.text_field :specialization
我有一个类似的功能,我用上面的方法实现。这里不完全清楚您的设置-尝试询问一些问题以澄清。那么医生就是用户——那么护士或医疗机构在代码方面是否与医生相似?这就是你所说的不同用户类别的意思?@RichardJordan感谢你的回答。是的,它们差不多。它们有自己特定于类的字段。@DaryllSantos,所以基本上每个人都是用户。唯一不同的是他们有不同的个人资料doctor/nurse/etc?@prasad.surase。我就是不能保存,因为用户需要配置文件,反之亦然。我想这对完整性来说是有意义的。我现在不想让随机用户没有配置文件,也不想让配置文件没有电子邮件地址。@DaryllSantos我正在添加答案。我实现的解决方案有点冗长。在下面添加它。谢谢迈克。呃,我如何确保每件事都得到很好的验证?我更新了我的答案,我想这会解决你的问题。由于多态性的原因,它可能有点偏离,但这个想法应该是正确的。太棒了,我会检查一下这个。。。我注意到您删除了委托/验证,并移动了资源的accepts\u nested\u attributes\u。如果你不介意我问,为什么这比旧代码好?这会改变预期的行为。在这个问题中,由于验证,医生或护士不能独立于用户而存在。但这实际上等同于删除这些验证,因为现在医生可以在没有用户的情况下生存。@MikeSlutsky我们可以在医生和护士上添加验证,以检查用户是否始终存在,并在用户上添加验证,以检查资源是否始终存在。@Darylsantos在我的应用程序中,要求用户能够选择类型。因此,父对象是用户对象,而不是医生或护士对象。因此,父对象接受子对象的嵌套属性。@DaryllSantos您可以添加特定于模型的验证和字段。表单将显示验证错误。