Rails 6中find_by、where查询数字开头的attempt_token结果异常如何解决
Rails 按id或token查询错误匹配问题解决方案
问题根因
- 调用
find_by(id: 字符串)时,Rails ActiveRecord会自动将传入值适配id的bigint类型做隐式转换:仅提取字符串开头的连续数字作为查询值,形如5HqBToVVbFVL4T6TLzuuKju8的字符串会被转换为数字5,因此错误命中id为5的记录。 - 直接写原生SQL条件
where('id = ?', 字符串)时,PostgreSQL不会做隐式类型转换,字符串无法匹配bigint类型的id字段,因此抛出类型错误异常。
可选解决方案
方案1:纯数字校验后再查id(数据库无关,逻辑直观)
仅当传入值为纯数字时才执行id查询,否则直接查询attempt_token,避免非id格式的字符串触发错误的类型转换:
def random_method(value) str_value = value.to_s if str_value.match?(/\A\d+\z/) find_by(id: str_value) || find_by(attempt_token: str_value) else find_by(attempt_token: str_value) end end
方案2:强转整数判断(逻辑更严谨)
尝试将传入值强转为整数,转换失败则跳过id查询,规避正则匹配可能的边界问题:
def random_method(value) id = Integer(value) rescue nil (id && find_by(id: id)) || find_by(attempt_token: value) end
方案3:数据库统一转字符串查询(性能最优,单次查询即可完成)
如果固定使用PostgreSQL,可以直接将id字段转为字符串后和token做统一查询,无需分两次查询,性能更好:
def random_method(value) find_by("id::text = ? OR attempt_token = ?", value.to_s, value.to_s) end
内容的提问来源于stack exchange,提问作者Vishal
相关产品推荐
相关产品推荐

