ruby-on-rails – 验证多态父代的存在

前端之家收集整理的这篇文章主要介绍了ruby-on-rails – 验证多态父代的存在前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我正在开发一个具有以下型号的Rails 3.2应用程序:
class User < ActiveRecord::Base
  # Associations
  belongs_to :authenticatable,polymorphic: true

  # Validations
  validates :authenticatable,presence: true # this is the critical line
end

class Physician < ActiveRecord::Base
  attr_accessible :user_attributes

  # Associations
  has_one :user,as: :authenticatable
  accepts_nested_attributes_for :user
end

我想要做的是验证用户是否总是具有可认证的父级.这本身很好,但是在我的形式里,用户模型抱怨认证不存在.

我正在使用以下控制器为新的医生显示一个表单,该表单接受用户的嵌套属性

def new
  @physician = Physician.new
  @physician.build_user

  respond_to do |format|
    format.html # new.html.erb
    format.json { render json: @physician }
  end
end

这是我的创建方法

def create
  @physician = Physician.new(params[:physician])

  respond_to do |format|
    if @physician.save
      format.html { redirect_to @physician,notice: 'Physician was successfully created.' }
      format.json { render json: @physician,status: :created,location: @physician }
    else
      format.html { render action: "new" }
      format.json { render json: @physician.errors,status: :unprocessable_entity }
    end
  end
end

在提交表单时,表示用户的可认证不能为空.但是,一旦保存了@physician,就应该分配authentatable_id和authentatable_type.如果我使用相同的表单来编辑医师及其用户,那么它可以正常工作,因为这个ID和类型被分配了.

我在这里做错了什么?

解决方法

我相信这是预料之中:

https://github.com/rails/rails/issues/1629#issuecomment-11033182(最后两个评论).

另请查看从rails api

One-to-one associations

Assigning an object to a has_one association automatically saves that
object and the object being replaced (if there is one),in order to
update their foreign keys – except if the parent object is unsaved
(new_record? == true).

If either of these saves fail (due to one of the objects being
invalid),an ActiveRecord::RecordNotSaved exception is raised and the
assignment is cancelled.

If you wish to assign an object to a has_one association without
saving it,use the build_association method (documented below). The
object being replaced will still be saved to update its foreign key.

Assigning an object to a belongs_to association does not save the
object,since the foreign key field belongs on the parent. It does not
save the parent either.

和这个

build_association(attributes = {}) Returns a new object of the
associated type that has been instantiated with attributes and linked
to this object through a foreign key,but has not yet been saved.

你必须首先创建一个父.然后将其分配给多态对象.

从我可以看到,你创建一个对象Physician.new,它构建用户,但在这一点上它还没有保存,所以它没有一个id,所以没有什么可以分配给多态对象.所以验证总是会失败,因为它在保存之前被调用.

换句话说:在你调用build_user的情况下,它返回User.new NOT User.create.因此,可认证不具有分配的authentatable_id.

你有几个选择:

>先保存关联用户.

要么
>将验证移动到after_save回调(可能但非常烦人和坏)

要么
>更改您的应用程序结构 – 可能避免多态关联并切换到has_many?我很难判断,因为我不知道内部和业务的要求.但是在我看来,这不是一个很好的候选者.你会有更多的模型,而不仅仅是用户将被认证?

多媒体协会的最佳候选人是电话,地址等.地址可以属于用户,客户,公司,组织,区域51等,成为家庭,运输或帐单类别,即可以容纳多种用途的MORPH,因此它是很好的对象提取.但是在我看来,Authenticatable似乎有点诡异,并增加了不必要的复杂性.我没有看到任何其他对象需要被认证.

如果您可以呈现您的Authenticatable模型和您的推理,也许迁移(?),我可以建议你更多.现在我只是从稀薄的空气中拉出来:-)但是它似乎是一个很好的重构候选人.

猜你在找的Ruby相关文章