Ruby Sequel.migration 中不区分大小写的唯一性验证

Posted

技术标签:

【中文标题】Ruby Sequel.migration 中不区分大小写的唯一性验证【英文标题】:Case insensitive uniqueness validation in a Ruby 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 对象中做到这一点(我已经有了一些)。我只是不太确定该怎么做。 【参考方案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/…

以上是关于Ruby Sequel.migration 中不区分大小写的唯一性验证的主要内容,如果未能解决你的问题,请参考以下文章

方法关闭似乎在 ruby​​racer 中不起作用

CSV::MalformedCSVError: 未加引号的字段在 Ruby 中不允许 \r 或 \n

运行 Ruby 命令时,PATH 中不安全的世界可写目录 /Users/username,模式 040777

:footnotes 扩展在 Redcarpet Ruby gem 中不起作用

字符串形式的正则表达式在 Ruby 中不起作用

Mailchimp double_optin => false 在 mailchimp-api-ruby 中不起作用