Имеет ли смысл преобразовывать запросы DB-ish в язык Rails ActiveRecord Model? - PullRequest
2 голосов
/ 29 ноября 2008
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. Какой обходной путь? например если я хочу ограничить количество записей до указанного пользователем предела.

Ответы [ 3 ]

2 голосов
/ 29 ноября 2008

Похоже, что find_by_sql не имеет предоставления переменной связывания, как find.

Конечно. (из рельсов документы )

# 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]
2 голосов
/ 29 ноября 2008
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")

Надеюсь, это поможет!

1 голос
/ 30 ноября 2008

Ну, это код, который наконец-то сработал для меня .. (Франсуа .. в результате в 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-инъекции или вызов метода to_i предотвращает это?

Спасибо за помощь. Я благодарен.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...