【问题标题】:Can I use a Custom method in a WHERE statement?我可以在 WHERE 语句中使用自定义方法吗?
【发布时间】:2015-09-03 09:02:52
【问题描述】:

我的 Rails 应用程序中有这两个模型:

create_table "projects", force: :cascade do |t|
  ...
  t.float    "latitude",   limit: 24,    default: 0.0
  t.float    "longitude",  limit: 24,    default: 0.0

用户:

create_table "users", force: :cascade do |t|
  ...
  t.float    "last_latitude",         limit: 24,    default: 0.0
  t.float    "last_longitude",        limit: 24,    default: 0.0111

我有一个自定义类:

class CalculusAid
  public
    # point_one and point_two are arrays of [latitude, longitude]

    def self.distance point_one, point_two

    first_point_latitude,  first_point_longitude  = point_one
    second_point_latitude, second_point_longitude = point_two

    latitude_difference_in_radians = (first_point_latitude - second_point_latitude).to_radians
    longitude_difference_in_radians = (first_point_longitude - second_point_longitude).to_radians

    #Math stuff
    a = Math.sin(latitude_difference_in_radians/2) * Math.sin(latitude_difference_in_radians/2) +
    Math.cos(first_point_latitude.to_radians) * Math.cos(second_point_latitude.to_radians) *
    Math.sin(longitude_difference_in_radians/2) * Math.sin(longitude_difference_in_radians/2);
    c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1-a));

    distance_in_kilometers = 6371 * c; # Multiply by 6371 to get Kilometers
    return distance_in_kilometers
 end
 ...

我不想做的是返回 5 个距离用户 0 到 50 公里的随机项目,我想用这样的方法来做到这一点

class User < ActiveRecord::Base
  def get_nearby_projects
     @nearby_projects = User.joins(:projects).where(CalculusAid.distance([self.last_longitude],self.last_latitude][project.longitude,project.latitude]) < 50).limit(5).order("RAND()")
  end

但我不知道是否可以在 where 语句中使用自定义方法,或者语法是否正确。

【问题讨论】:

    标签: mysql sql ruby-on-rails ruby activerecord


    【解决方案1】:

    这是不可能的,因为 Rails 只是构建一个由 MySQL 执行的查询,并从数据库服务器获取结果。这是一个原子操作,不能将 lambda 传递给 MySQL 来过滤结果。

    但是 MySQL 有 built-in math functions:

    @nearby_projects = ActiveRecord::Base.connection.execute <<-SQL
      SELECT * 
      FROM users
        JOIN projects ON (???) -- unclear from the code you’ve pasted
      WHERE
        50 > 6371 * (SIN(users.last_latitude + .......
    SQL
    

    希望对你有帮助。

    【讨论】:

    • 我不能用距离函数替换 50 > 6371 *(SIN... 吗?
    • 不行,你应该用纯SQL重写。
    • 好的,如果没有更好的方法我会这样做
    • 不是我所知道的那个。也许未来的访客会提出更好的建议。
    【解决方案2】:

    你为什么不简单的“范围

    SELECT a,b,c, ... 
    FROM table
    WHERE range < 50
    ORDER BY RAND()
    LIMIT 5;
    

    【讨论】:

    • 我没有范围方法
    猜你喜欢
    • 2017-05-07
    • 2012-04-28
    • 2013-04-13
    • 1970-01-01
    • 2015-09-16
    • 1970-01-01
    • 1970-01-01
    • 2017-07-18
    • 2012-06-28
    相关资源
    最近更新 更多