【问题标题】:Case insensitive uniqueness validation in a Ruby Sequel.migrationRuby Sequel.migration 中不区分大小写的唯一性验证
【发布时间】:2012-07-11 15:59:06
【问题描述】:

我正在尝试找出一个可以在我的迁移中使用的良好验证,这将要求用户电子邮件地址具有不区分大小写的唯一性。简而言之,我想要像validate :email, :uniqueness => {:case_sensitive => false} 这样的东西,而不必将所有东西都转换为使用Rails 或ActiveRecord。我可以通过正则表达式运行电子邮件,但我不喜欢那种解决方案。

我发现一条评论[1]说你可以使用
validates_unique(:email){ |ds| ds.opts[:where].args.map! { |x| Sequel.function(:lower, x)}; ds}
但我不明白该代码在做什么,当我不知道 ds 对象是什么或发生了什么事情时,我不想使用该代码(为什么 map!,postgresql 有 @ :lower 的 987654326@? ... 可能,但我就是不知道。)

[1]http://comments.gmane.org/gmane.comp.lang.ruby.sequel/6447

所以我需要回答以下两件事之一:
1) 如何在纯 Sequel.migration(无 ActiveRecord,无 Rails)中执行不区分大小写的唯一性验证?
- 或 -
2)如果我在网上找到的代码 sn-p 确实是我想要的,它有什么作用以及它是如何工作的? (ds 对象是什么,这个验证对我的数据库有什么作用?)

【问题讨论】:

  • 您似乎对验证和索引的工作方式以及迁移的作用感到困惑。
  • 不,我正在尝试添加数据库约束。你可以在我的Sequel.migration 对象中做到这一点(我已经有了一些)。我只是不太确定该怎么做。

标签: ruby migration email-validation sequel


【解决方案1】:

正如 Tin Man 提到的,您混淆了验证和约束。您说您正在尝试添加约束并谈论Sequel.migration,但这些与验证无关。

如果你想添加一个数据库约束,你需要在迁移中做这样的事情:

alter_table(:table){add_unique_constraint Sequel.function(:lower, :email)}

这样做是为了使数据库不允许以不区分大小写的方式重复电子邮件。

验证只是为了向用户呈现漂亮的错误消息。它们在保存之前运行,这样您就不会得到一个很好的错误消息,而不是数据库引发异常(这很难处理)。

就像评论中提到的那样,您不能使用 validates_unique 对区分大小写的数据库进行不区分大小写的查找而无需破解。这将要求 validates_unique 接受一个附加选项(将来可能会添加)。

如果您不想使用这样的 hack,则必须手动进行验证:

dataset = model.where{|o| {o.lower(:email)=>o.lower(email)}}
dataset.exclude(pk_hash) unless new?
errors.add(:email, 'is already taken') unless ds.count == 0

就该 hack 的作用而言,dsSequel::Dataset 实例,validates_unique 使用它来检查唯一性。如果你做validates_unique :email,它会是这样的:

model.where(:email=>email)
# WHERE email = 'some email'

ds.opts[:where] 从该数据集中提取 where 子句,并转换参数,将它们包装在 SQL lower 函数调用中,以便转换 where 子句,使其类似于:

model.where{|o| {o.lower(:email)=>o.lower(email)}}
# WHERE lower(email) = lower('some email')

这是一个 hack,因为它仅在模型的数据集尚未过滤时才有效。

【讨论】:

  • 我明白了。正如我所说,我不理解我找到的代码 sn-p,所以我没有意识到它是别的东西。谢谢。
  • 耙子中止! PG::Error: ERROR: syntax error at or near "(" LINE 1: ALTER TABLE "users" ADD UNIQUE (lower("name")) 我复制/粘贴了你所说的内容,并将其设为 alter_table(:users)。
  • 废话,我猜这是 postgres 的东西:bytes.com/topic/postgresql/answers/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-31
  • 1970-01-01
  • 1970-01-01
  • 2012-12-09
  • 1970-01-01
  • 2020-12-25
  • 1970-01-01
相关资源
最近更新 更多