gpt4 book ai didi

ruby-on-rails - 在 ActiveModel 对象上,如何检查唯一性?

转载 作者:行者123 更新时间:2023-12-02 18:27:59 27 4
gpt4 key购买 nike

在 Bryan Helmkamp 的优秀博文“7 Patterns to Refactor Fat ActiveRecord Models”中,他提到使用表单对象来抽象多层表单并停止使用accepts_nested_attributes_for

编辑:参见below寻求解决方案。

我几乎完全复制了他的代码示例,因为我有同样的问题需要解决:

class Signup
include Virtus

extend ActiveModel::Naming
include ActiveModel::Conversion
include ActiveModel::Validations

attr_reader :user
attr_reader :account

attribute :name, String
attribute :account_name, String
attribute :email, String

validates :email, presence: true
validates :account_name,
uniqueness: { case_sensitive: false },
length: 3..40,
format: { with: /^([a-z0-9\-]+)$/i }

# Forms are never themselves persisted
def persisted?
false
end

def save
if valid?
persist!
true
else
false
end
end

private

def persist!
@account = Account.create!(name: account_name)
@user = @account.users.create!(name: name, email: email)
end
end

我的代码的不同之处之一是我需要验证帐户名(和用户电子邮件)的唯一性。但是,ActiveModel::Validations 没有唯一性 验证器,因为它应该是 ActiveRecord 的非数据库支持变体。

我认为可以通过三种方法来处理这个问题:

  • 编写我自己的方法来检查这一点(感觉多余)
  • 包含 ActiveRecord::Validations::UniquenessValidator(尝试过此操作,但没有成功)
  • 或者在数据存储层添加约束

我更喜欢使用最后一个。但后来我一直想知道如何我将实现这个。

我可以做类似的事情(元编程,我需要修改一些其他区域):

  def persist!
@account = Account.create!(name: account_name)
@user = @account.users.create!(name: name, email: email)
rescue ActiveRecord::RecordNotUnique
errors.add(:name, "not unique" )
false
end

但现在我的类中运行了两项检查,首先使用 valid?,然后使用 rescue 语句来进行数据存储约束。

有谁知道解决这个问题的好方法吗?也许为此编写我自己的验证器会更好(但随后我会对数据库进行两次查询,理想情况下一个就足够了)。

最佳答案

如果这恰好是一次性要求,那么创建自定义验证器可能有点过分了。

简化的方法...

class Signup

(...)

validates :email, presence: true
validates :account_name, length: {within: 3..40}, format: { with: /^([a-z0-9\-]+)$/i }

# Call a private method to verify uniqueness

validate :account_name_is_unique


def persisted?
false
end

def save
if valid?
persist!
true
else
false
end
end

private

# Refactor as needed

def account_name_is_unique
if Account.where(name: account_name).exists?
errors.add(:account_name, 'Account name is taken')
end
end

def persist!
@account = Account.create!(name: account_name)
@user = @account.users.create!(name: name, email: email)
end
end

关于ruby-on-rails - 在 ActiveModel 对象上,如何检查唯一性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/14670396/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com