【问题标题】:Does it make sense to convert DB-ish queries into Rails ActiveRecord Model lingo?将 DB-ish 查询转换为 Rails ActiveRecord 模型术语是否有意义?
【发布时间】:2008-11-29 08:14:38
【问题描述】:
mysql> desc categories;
+-------+-------------+------+-----+---------+----------------+
| Field | Type        | Null | Key | Default | Extra          |
+-------+-------------+------+-----+---------+----------------+
| id    | int(11)     | NO   | PRI | NULL    | auto_increment |
| name  | varchar(80) | YES  |     | NULL    |                |
+-------+-------------+------+-----+---------+----------------+

 mysql> desc expenses;
+-------------+---------------+------+-----+---------+----------------+
| Field       | Type          | Null | Key | Default | Extra          |
+-------------+---------------+------+-----+---------+----------------+
| id          | int(11)       | NO   | PRI | NULL    | auto_increment |
| created_at  | datetime      | NO   |     | NULL    |                |
| description | varchar(100)  | NO   |     | NULL    |                |
| amount      | decimal(10,2) | NO   |     | NULL    |                |
| category_id | int(11)       | NO   | MUL | 1       |                |
+-------------+---------------+------+-----+---------+----------------+

现在我需要这样的前 N ​​个类别...

Expense.find_by_sql("SELECT categories.name, sum(amount) as total_amount 
   from expenses 
   join categories on category_id = categories.id 
   group by category_id 
   order by total_amount desc")

但这在我的 Rails 良心上唠叨不休.. 似乎可以通过 Expense.find 并提供诸如 :group、:joins 之类的选项来实现相同的目标..

  • 有人可以将此查询翻译成 ActiveRecord 模型吗?
  • 值得吗...就我个人而言,我发现 SQL 更具可读性并且可以更快地完成我的工作。也许因为我还在学习 Rails。不将 SQL 嵌入源代码有什么好处(除了不能更改数据库供应商..sql 风格等)?
  • 似乎find_by_sql 没有像find 这样的绑定变量规定。解决方法是什么?例如如果我想将记录数限制为用户指定的限制。

【问题讨论】:

    标签: ruby-on-rails activerecord


    【解决方案1】:
    Expense.find(:all,
      :select => "categories.name name, sum(amount) total_amount",
      :joins => "categories on category_id = categories.id",
      :group => "category_id",
      :order => "total_amount desc")
    

    希望有帮助!

    【讨论】:

      【解决方案2】:

      好像 find_by_sql 没有像 find 这样的绑定变量规定。

      确实如此。 (来自 Rails docs

      # You can use the same string replacement techniques as you can with ActiveRecord#find
        Post.find_by_sql ["SELECT title FROM posts WHERE author = ? AND created > ?", author_id, start_date]
      

      【讨论】:

        【解决方案3】:

        这就是最终对我有用的代码..(Francois.. 生成的 sql stmt 缺少 join 关键字)

        def Expense.get_top_n_categories options={}
            #sQuery = "SELECT categories.name, sum(amount) as total_amount 
            #   from expenses 
            #   join categories on category_id = categories.id 
            #   group by category_id 
            #   order by total_amount desc";
            #sQuery += " limit #{options[:limit].to_i}" if !options[:limit].nil?
            #Expense.find_by_sql(sQuery)
            query_options = {:select => "categories.name name, sum(amount) total_amount",
                :joins => "inner join categories on category_id = categories.id",
                :group => "category_id",
                :order => "total_amount desc"}
            query_options[:limit] = options[:limit].to_i if !options[:limit].nil?
            Expense.find(:all, query_options)
          end
        

        find_by_sql 确实有rails 绑定变量...我不知道我是如何忽略它的。 最后,上述用户指定的使用是 sql-injection 的潜在入口点,还是 to_i 方法调用阻止了这种情况?

        感谢所有帮助。我很感激。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多