怎么用rails方式呢?

时间:2014-07-10 06:48:52

标签: ruby-on-rails ruby ruby-on-rails-4 rails-activerecord

新手问题。

查询我的自定义数据库(我使用mysql数据库而不是sqlite3)。 根据导轨指南,通过导轨模型,它可以高效,轻松地从我的数据库访问数据。

但我这样做(我知道它不是实际的rails方式)使用长查询返回一些对象,并需要建议以rails方式执行(我希望我的控制器只调用模型返回对象而不是自己动手)。

在我的控制器中。

def near
      begin
        @lat = params[:lat]
        @lon = params[:lon]
        @near_ids = []

        def get_id(dist_var) 
          @near_ids = Bank.find_by_sql("SELECT id FROM(SELECT al.id,(3959 * acos(cos(radians(#{@lat})) * cos(radians(y(ppt))) * cos(radians(x(ppt)) - radians(#{@lon})) +sin(radians(#{@lat})) * sin(radians(y(ppt))))) AS distance FROM db1.tbl1 gf,db2.tbl1 al WHERE gf.object_type = 256 AND al.c_id = 10 AND gf.object_id = al.wp_id HAVING distance < #{dist_var}) S ORDER BY S.distance; ")  
          puts 'Total id :'+@near_ids.length.to_s
          puts 'distance :'+dist_var.to_s
        end

      get_id(dist = 1)

        while(@near_ids.length < 10)
          dist +=5
          get_id(dist)
        end

          @banks = []
          @near_ids.each do |bank|
            @banks << Store.find_by_id(bank["id"])
          end
          @user = @banks.paginate(:page => params[:page], :per_page => 10 )
          rescue ActiveRecord::RecordNotFound
          render json: 'Not found', status: 404
      end
    end

这是我的银行模式

class Bank < ActiveRecord::Base
    self.table_name = 'table1'
    has_many :branch, :foreign_key => 'tbl1_id'
end

在我的分支模型中,我使用外键使用belongs_to :Bank

3 个答案:

答案 0 :(得分:1)

要纠正的一些事情:

-

<强> SQLite3的

这不是&#34; rails方式&#34; - 它只是Rails附带的默认数据库类型。它们包括它因为它不依赖任何外部数据库服务器来操作(保持系统自包含)

您可以自由使用Mysql,甚至PostgreSQL等

-

<强> MVC

我不明白您的问题究竟是什么,但我建议您阅读MVC programming pattern

enter image description here

这基本上意味着您需要从使用控制器从模型中提取特定数据,与数据存储通信的模型以及显示被调用数据的视图的角度来考虑您的系统

你的控制器包含直接SQL - 对于MVC而言是一个很大的禁忌,因为它只会导致flying spaghetti monster code。你会做得更好:

#app/controllers/your_controller.rb
Class YourController < ApplicationController
    def action
        @model = Model.your_class_method_or_scope
    end
end

#app/models/model.rb
Class Model < ActiveRecord::Base
    def self.your_class_method
        where("your query here")
    end
end

最后,你真的需要具体针对SO,以获得具体的答案。我不知道你的问题是直接的

答案 1 :(得分:1)

您正在寻找一种方法来重写您的MySQL查询轨道方式?由于这不是一个常见的用例,ActiveRecord并没有提供一种简单的方法来进行地理搜索。您需要依赖原始的MySQL语法。

有关空间数据的MySQL-manual page可能会帮助您改善坐标搜索。

答案 2 :(得分:1)

您的代码中存在一些问题,但让我尝试将它们包装起来:

控制器

如何调用控制器?当你通过商店分页时,我认为它是StoresController。在 Rails Way 中,我们希望StoresController能够对Stores模型执行操作。

此外,在更多 RESTful 方式中,您可能不会定义函数near,而是定义列出所有index的函数Stores可以通过提供latlng参数来对列表进行排序。

模型

我不清楚你为什么要Store.find_by_id(bank["id"])。在正常情况下,这样的通话毫无意义,因为bank_id只有标识一个Bank而不是Store。因此,我假设您正在寻找BankStore模型之间的某些关系,您可以通过在bank_id表中添加stores字段来定义Store } model as:

class Store < ActiveRecord:Base
  belongs_to :bank
end

查询

正如之前的回答声明的那样,您最好使用所谓的范围将查询放入模型而不是控制器。但是对于您的特定用例,我建议您查看geokit-rails gem,它可以让您执行以下操作:

Store.by_distance(origin: [params[:lat],params[:lng]])

要使用它,您必须将Store模型定义为acts_as_mappable,如下所示:

class Store < ActiveRecord:Base

 acts_as_mappable :through => :bank                

end

当然,您需要lat表中定义的lngbanks字段。

(不幸的是geokit-rails gem的README已经过时了,所以你必须摆弄一下才能做到正确)

分页

我认为写

是错误的

@user = @ stores.paginate(:page =&gt; params [:page],:per_page =&gt; 10)

使用上面的查询代码,您应该改为编写

@stores = Store.by_distance(origin:[params [:lat],params [:lng]])。paginate(page:params [:page],per_page:10)

错误处理

您不太可能获得ActiveRecord :: NotFound异常,因为这些异常通常仅在您使用find - 特定id上的查找时抛出。当你想抛出这样的异常时,你会想要:

raise ActiveRecord::RecordNotFound if @stores.empty?

位于方法的底部。