【问题标题】:How to add a validation to rails model which depends on another model如何向依赖于另一个模型的 Rails 模型添加验证
【发布时间】:2013-11-26 16:55:47
【问题描述】:

找不到轻松完成此任务的最佳方法 我想为以下问题提出数据库模型。

有一个 Deal 表,它有一个关联的 account 表。每个帐户可以有多个联系人。现在,一笔交易需要分配一个主要联系人,该联系人必须是关联帐户的众多联系人之一。如何确保主要联系人是帐户联系人之一。

Deal Table
  account_id
  primary_contact_id

Account Table
  name and other params

Contact Table
  account_id
  phone, email etc.

例如。我目前使用的类

class Deal < ActiveRecord::Base
  belongs_to :account
  belongs_to :contact
end

class Account < ActiveRecord::Base
  has_many :contacts
  has_many :deals
end

class Contact < ActiveRecord::Base
  belongs_to :account
  has_many :deals
end

我可以在交易模型或控制器中添加验证,以确保添加的联系人是其帐户联系人之一。但是如何处理以下情况:

  1. 从账户中删除联系人应确保deal表对应的contact_id设置为nil
  2. 删除与交易关联的帐户应确保该交易表的contact_id 无效
  3. 更新帐户关联应确保交易的contact_id 无效。

【问题讨论】:

    标签: mysql ruby-on-rails ruby-on-rails-3 ruby-on-rails-3.2 ruby-on-rails-3.1


    【解决方案1】:

    也许你可以使用模型回调,例如:

    class Deal < ActiveRecord::Base
      belongs_to :account
      belongs_to :contact
    
      before_update :nullify_contact_association, :if => lambda{|i| i.account_id_changed?}
    
      private
      # Nullify contact_id of the deal if it's account association was changed
      def nullify_contact_association
        self.contact_id = nil
      end
    end
    
    class Account < ActiveRecord::Base
      has_many :contacts
      has_many :deals
    
      before_destroy :nullify_dependencies
    
      private
    
      #Deleting an account associated with a deal should
      #make sure that contact_id of that deal table is nullified
      def nullify_dependencies
        self.deals.update_all(:contact_id => nil) if deal.present?
      end
    end
    
    class Contact < ActiveRecord::Base
      belongs_to :account
      has_many :deals
    
      before_destroy :nullify_dependencies
    
      private
    
      #Deleting a contact from an account should make sure
      #that corresponding contact_id of the deal table is set to nil
      def nullify_dependencies
        self.deals.update_all(:contact_id => nil) if account.present?
      end
    end
    

    【讨论】:

      【解决方案2】:
      class Deal
      
        validate :contact_is_among_the_contacts_in_associated_account
      
        private
      
        def contact_is_among_the_contacts_in_associated_account
          errors.add(:contact_id, "Your error message") unless contact.in?(account.contacts)
        end
      
      end
      

      【讨论】:

      • 感谢您的回复。我尝试过这种方式,但问题在于我上面提出的问题之一假设处理 id 1 有 account_id 1,它有 id 1 和 2 的联系人。现在我将交易主要联系人分配为联系人 2。之后,如果我们从联系人表中删除联系人 2,交易表将保持 account_id 1 和 primary_contact_id 为 2。这可以忽略,因为 deal.primary_contact 返回 nil 并且没问题。但问题是现在我们将无法对交易进行任何其他编辑(如名称更改),因为此验证将阻止所有进一步的编辑。
      • 也许我可以通过确保将 primary_contact_id 设置为 nil 来解决这个问题,只要从数据库中删除具有该 ID 的联系人。此外,我必须确保无论何时删除帐户,primary_contact_id 和 account_id 都会失效。如何在 Rails 中实现这一点?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2019-03-11
      • 1970-01-01
      • 2014-12-27
      • 1970-01-01
      • 1970-01-01
      • 2016-03-30
      • 1970-01-01
      相关资源
      最近更新 更多