【问题标题】:Migrating a nested polymorphic record to a new relationship using accepts_nested_attributes_for使用 Accepts_nested_attributes_for 将嵌套多态记录迁移到新关系
【发布时间】:2013-12-13 17:02:35
【问题描述】:

这是一个艰难的过程。我有以下型号:

 class Account < ActiveRecord::Base
    belongs_to :accountable, :polymorphic => true

 class Professional < ActiveRecord::Base
    has_one :account, as: :accountable, dependent: :destroy
    accepts_nested_attributes_for :account, :allow_destroy => true

 class User < ActiveRecord::Base
    has_one :account, as: :accountable, dependent: :destroy
    accepts_nested_attributes_for :account, :allow_destroy => true

现在,假设某人已经有一个User 的帐户,但他们去注册为Professional. 我们实际上想说“如果这个人尝试注册已经有一个用户帐户,那么专业记录和迁移他们的用户帐户将与专业帐户相关联。”

所以在规范方面:

describe "A person with an existing user account for their email address", focus: true do
  before(:each) do
    @user = create(:user, account_attributes: {email: 'testdesigner@test.com', password: 'testing', password_confirmation: 'testing'})
  end

  it "can still sign up as a professional with the same email address" do
    # need to transfer the user account to the professional and delete it
    pro = Professional.new(first_name: 'Test', last_name: 'Designer', company_name: 'A Design Firm', account_attributes: {email: 'testdesigner@test.com', password: 'testing', password_confirmation: 'testing'})

    pro.save.should be_true

    account = Account.find_by_email(@user.email)
    account.accountable_type.should eql 'Professional'

    pro.account.should eql account
  end
end

但无论我们尝试什么(在 hooks 之前,尝试修改 person 模型中的嵌套属性,accept_nested_attributes_for 上的 update_only 和 reject_if),我们似乎都无法让它在模型中工作)

我们真正需要做的是完全绕过accepts_nested_attributes_for 记录的创建,如果该人类型为User 的当前帐户存在,但如果我们输入reject_if,那么它会完全停止父记录(即Professional)的创建。

我们如何实现这一点的任何想法

【问题讨论】:

  • 一条评论 - 我们知道我们可以在调用 create 之前在控制器中完成这一切,但由于这是数据驱动的,我们希望完全在模型中处理它。

标签: ruby-on-rails devise models nested-attributes


【解决方案1】:

为您更新了使用现有模型结构的解决方案:

class Professional < ActiveRecord::Base
  before_create :assign_existing_account_if_exists

  has_one  :account, as: :accountable, dependent: :destroy
  delegate :email, to: :account, prefix: true, allow_nil: true

  accepts_nested_attributes_for :account, :allow_destroy => true

  private

  def assign_existing_account_if_exists
    account_to_assign = Account.find_by_email(self.account_email)
    self.account = account_to_assign if account_to_assign.present?
  end
end

【讨论】:

  • No STI 在这种情况下不起作用,因为 Professional 和 User 模型属性完全不同。此外,除非您暗示用户模型篡夺了帐户模型,否则这无助于回答问题,而我们不希望这样做。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多