2012-10-25 2 views
4

Я хочу использовать подзапрос с ActiveRecord так:ActiveRecord Выберите с параметром Переплета

User.select(
    'users.*, 
    (select sum(amount) 
     from subscriptions 
     where subscriptions.user_id = user.id 
     and created_at < ?) as amt)' 
).order('amt') 

Однако, на втором в последнюю строку, у меня есть проблема, которую я не могу понять, как привязать Time параметр класса, так как метод ActiveRecord::Baseselect не принимает более одного параметра (строка sql). Что я делаю?

ответ

8

Вы можете использовать один из ActiveRecord::Sanitization class methods.

Они смешиваются в ActiveRecord::Base и почти все они защищены, поэтому они наиболее легко доступны, определив метод класса на модели:

class User < ActiveRecord::Base 
    def self.select_with_args(sql, args) 
    query = sanitize_sql_array([sql, args].flatten) 
    select(query) 
    end 
end 

Это также стоит искать другие способы для извлечения данных и сравнения их производительность для метода подзапроса. Например, вы можете получить подсчет подписей с помощью отдельного запроса:

subs_by_user = Subscription.group(:user_id).where('created_at < ?', d).count() 
+1

Не помешало бы использованию кэша готовых инструкций в адаптере db? Похоже, http://apidock.com/rails/ActiveRecord/Sanitization/ClassMethods/sanitize_sql_array просто интерполирует текущее значение в оператор. – qix

Смежные вопросы