ruby-on-rails - 如何验证数据库,rails 6,postgres中是否已经存在列组合
问题描述
新手来了!
红宝石 2.7.1,宝石--版本 3.1.4,Rails 6.0.3.4
我的查询出现错误
def entry_uniqueness
if Entry.where("lower(from) = ? AND lower(to) = ?",
from.downcase, to.downcase).exists?
errors.add(:base, 'Identical combination already exists. YUP.')
end
end
错误:
PG::SyntaxError:错误:“来自”第 1 行或附近的语法错误:从“条目”WHERE 中选择 1 作为一个(lower(from)= 'here' A ... ^
完全错误
app/models/entry.rb:35:in
entry_uniqueness' app/controllers/entries_controller.rb:9:in
create' 开始 POST "/entries" for ::1 at 2021-02-13 16:17:47 +0800 由 EntriesController#create 作为 HTML 参数处理:{"authenticity_token"= >"98sjupNso6NW5xUonE/414I7ZvJQETMPBNWS+jcN+PffHaAJ3K0pdQofVPgnrBfflYn2SDXMlB17Q2G/gzideA==", "entry"=>{"translation"=>"1", "from"=>"here", "to"=>"there"}, " commit"=>"Post Translation"} [1m[36mEntry 存在吗?(10.2ms)[0m [1m[34mSELECT 1 AS one FROM "entries" WHERE (lower(from) = 'here' AND lower(to) = 'there') LIMIT $1[0m [["LIMIT", 1]] ↳ app/models/entry.rb:35:in `entry_uniqueness' Completed 500 Internal Server Error in 38ms (ActiveRecord: 10.2ms | Allocations: 2140)ActiveRecord::StatementInvalid (PG::SyntaxError: 错误: "from" LINE 1 或附近的语法错误: SELECT 1 AS one FROM "entries" WHERE (lower(from) = 'here' A...^): app/模型/entry.rb:35:in
entry_uniqueness' app/controllers/entries_controller.rb:9:in
create'
我想要实现的是:
| from | to |
-----------------
| Here | there |
=> 验证应该阻止用户添加heRE | THERE
但可以添加THERE | heRE
列:from
和:to
在表中entries
。
注意:我尝试过作用域,它们在唯一性上起作用,但在不区分大小写时失败
validates_uniqueness_of :from, scope: :to
也试过
validates_uniqueness_of :from, :scope => :to, :case_sensitive => false
还尝试了 @r4cc00n 的实现,但它不起作用
scope :get_entries_by_from_and_to, ->(from, to) { where(arel_table[:from].lower.eq(from)).where(arel_table[:to].lower.eq(to))}
validates_uniqueness_of :from, if: :entry_uniqueness?
def entry_uniqueness?
Entry.get_entries_by_from_and_to('from','to').nil?
end
解决方案
from
是PostgreSQL 中的保留名称。这很有意义,因为读取查询通常包含这个词(想想SELECT value FROM table
)。因此,Rails 根据您的条件构建的查询
SELECT 1 AS one FROM "entries" WHERE (lower(from) = 'here' A...
^^^^ ^^^^
混淆了数据库。顺便说一句to
,它也是一个保留名称。
避免遇到此类问题的一种方法是,您应该考虑重命名该列。
另一个简单的解决方法是将列名用双引号括起来。只需将您的条件更改为:
Entry.exists?('lower("from") = ? AND lower("to") = ?', from.downcase, to.downcase)
请注意,我在列名周围使用了双引号,在整个条件周围使用了单引号。
推荐阅读
- android - Kotlin - 缩放画布性能问题
- r - 循环遍历数据框时如何引用同一行中的元素?
- c# - 在启动时访问 dbcontext
- android - Android WebView和html透明背景
- sql - 哪种商店类型按销售金额和销售数量销售的产品最多
- python - 从numpy中的图像中提取缩略图
- sap-cloud-sdk - 构建失败,例如应用程序 cloud-s4-sdk-book(集成测试)
- python-3.x - Python:如何将 json 逗号分隔键转换为字典
- dialogflow-es - Dialogflow 后续意图未在 Actions on Google 上触发
- oracle - Oracle Apex 交互式网格 - 使用只读方式保存不正确的记录