即使满足条件,也会忽略两种自定义Active Record验证方法之一(规则5)

时间:2019-06-04 09:40:14

标签: ruby-on-rails activerecord

我的模型有两个自定义的ActiveRecord验证方法,应该同时触发。但是,无论我做什么,都只会执行方法A(setup_ssh_user),而不会执行B(save_ssh_on_server)。

我已经尝试过:

  • 使用byebugRails.logger.info('funciton B is called')检查方法B确实从未被调用
  • 注释方法A
  • 重命名方法B
  • 使用validate代替before_validation
  • 交换方法A和B的代码
class Postgresql < ApplicationRecord
  # Validations
  validates :host, presence: true
  validates :port, presence: true
  validates :user, presence: true
  validates :dbname, presence: true
  before_validation :setup_ssh_user, :save_ssh_on_server, on: :create, if: :ssh_tunnel?
  before_validation :save_ssh_on_server, on: :update, if: :ssh_public_key_changed?
  validate :rollback_ssh_setup, if: :rollback_needed

  # Associations
  has_one :target, as: :resource, inverse_of: :resource, autosave: true

  accepts_nested_attributes_for :target, reject_if: :all_blank, allow_destroy: true

  def rollback_needed
    return self.target.deleted || errors[:ssh_public_key].any? || errors[:ssh_user].any? ? true : false
  end

  def rollback_ssh_setup
    status1, status2, status3 = SshTunnel::Setup.new().rollback_ssh_setup(self.ssh_user, self.ssh_public_key)
    if status1.success? && status2.success? && status3.success?
      return true
    else
      errors.add(:ssh_tunnel, "Rollback of ssh setup failed.")
      return false
    end
  end

  def setup_ssh_user
    status = SshTunnel::Setup.new().create_user(self.ssh_user)
    if status.success?
      return true
    else
      errors.add(:ssh_user, "User Creation failed, please try again.")
      return false
    end
  end

  def save_ssh_on_server
    Rails.logger.info("ssh saving function called")
    status = SshTunnel::Setup.new().save_public_key(self.ssh_public_key, self.ssh_user)
    if status.success?
      return true
    else
      errors.add(:ssh_public_key, "Saving SSH Key failed, please try again.")
      return false
    end
  end
end

由于这两种方法超级相似,所以我不明白为什么一个永远不会执行,而另一个却如此。也许我误解了ActiveRecord验证的工作原理?非常感谢您提出的任何改进或调试建议。

1 个答案:

答案 0 :(得分:0)

不幸的是,这并不是上述代码为什么不起作用的真正答案,但我找到了一种解决方法-希望这对可能遇到类似情况的其他人有所帮助。

我替换为:

before_validation :setup_ssh_user, :save_ssh_on_server, on: :create, if: :ssh_tunnel?

具有:

  before_validation on: :create do
    if self.ssh_tunnel
      self.setup_ssh_user
      self.save_ssh_on_server
    end
  end