find_by表现不如预期

时间:2013-11-13 02:19:30

标签: ruby-on-rails activerecord

在rails控制台上工作,为什么以下find_by返回nil?

2.0.0 (main):0 > Location.last
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT 1
=> #<Location id: 92, district: nil, address: "8026 S KEDZIE AVE", city: "CHICAGO", state: "IL", zip: 60652, website: nil, location: nil, latitude: 41.7474748619454, longitude: -87.7023800625442, location_type: "fire_station">
2.0.0 (main):0 > lat = Location.last.latitude
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" ORDER BY "locations"."id" DESC LIMIT 1
=> 41.7474748619454
2.0.0 (main):0 > Location.find_by( latitude: lat)
  Location Load (0.8ms)  SELECT "locations".* FROM "locations" WHERE "locations"."latitude" = 41.7474748619454 LIMIT 1
=> nil

我原本以为它与Sqlite有关,所以我切换到Postgres,但仍然产生相同的结果。在某个项目上工作的其他人运行相同的find_by得到了正确的结果。我的系统发生了什么事情正在发生?

2 个答案:

答案 0 :(得分:2)

假设这是Float平等检查的问题,以下是http://www.mail-archive.com/rubyonrails-talk@googlegroups.com/msg02703.html的一些建议:

给定: x = 11.967 y = 11.966999999999&lt; - 由十六进制&lt; - &gt;十进制引起的精度损失 转化

  1. 根据范围进行比较(如前一篇文章所述) 11.9670&lt; = x&lt; 11.968。​​

  2. 比较浮点值的字符串表示: x == y =&GT;假 (“%。3f”%x)==(“%。3f”%y) =&GT;真

  3. 使用定点数据类型(例如DECIMAL in)存储值 MySQL的): lng DECIMAL(5,3) x - &gt; LNG =&GT; 11.967 y - &gt; LNG =&GT; 11.967&lt; - 基于数据库中定义的规则进行舍入 可以安全地比较两个值的相等性

  4. 将固定的十进制值存储为数据库中的整数并进行转换 他们在展示它们时。我只提到这种技术,因为它是 存储货币值的选项。而不是存储美元,存储 相反,并转换为美元与显示值 视图。 $ 1.60 - &gt; 160(在数据库中)

答案 1 :(得分:0)

作为一种快速解决方法,您可以使用SQL ROUND方法

Location.find_by("ROUND(latitude, 3) = ?", "%.3f" % lat)

但它会有效地杀死位置表上的索引(假设你有一个)并且不适合大量数据。