设置:
rails new testing --minimal
cd testing
bin/rails g model Property name handle --no-timestamps
bin/rails db:migrate
sed -i '2i \ normalizes :handle, with: ->(handle) { handle.to_s.underscore.parameterize(separator: "_") }' app/models/property.rb
# app/models/property.rb
class Property < ApplicationRecord
normalizes :handle, with: ->(handle) { handle.to_s.underscore.parameterize(separator: "_") }
end
handle
在创建/更新记录以及搜索时需要进行规范化:
Property.create(name: "My property", handle: " My property ")
#=> #<Property:0x00007f9b3a0e2e50 id: 1, name: "My property", handle: "my_property">
# ^^^^^^^^^^^
Property.where(handle: " myProperty ").to_sql
#=> "SELECT \"properties\".* FROM \"properties\" WHERE \"properties\".\"handle\" = 'my_property'"
# ^^^^^^^^^^^
但是当LIKE
使用 arel 构建查询时%
,字符也会被剥离,而这些字符应该是查询的一部分:
Property.arel_table[:handle].matches("%prop%").to_sql
#=> "\"properties\".\"handle\" LIKE 'prop'"
# ^^^^
我可以避免这样做where("handle LIKE ?")
并始终保持handle
正常化吗?
这个问题之前已经提出过,如Rails 问题所示。看起来没有计划修复它,因为它不是公共 API 的一部分。
您可以通过引用节点(不会被强制转换)来绕过通配符的过滤:
或者如果您想在搜索之前应用规范化: