2009-02-14 13 views
5

tengo que hacer algo como esto¿Es posible hacer que ActiveRecord cree objetos para filas cargadas usando la opción: joins?

class User < ActiveRecord::Base 
    has_many :abuse_reports 
end 

class AbuseReport < ActiveRecord::Base 
    belongs_to :abuser, :class_name => 'User', :foreign_key => 'abuser_id' 
    belongs_to :game 
end 

class Game < ActiveRecord::Base 
    has_many :abuse_reports 
end 

@top_abusers = User.page(params[:page], 
    :joins => [ 
    'JOIN abuse_reports ON users.id = abuse_reports.abuser_id', 
    'JOIN games ON games.id = abuse_reports.game_id' 
    ], 
    :group => 'users.id', 
    :select => 'users.*, count(distinct games.id) AS game_count, count(abuse_reports.id) as abuse_report_count', 
    :order => 'game_count DESC, abuse_report_count DESC' 
) 

Esto funciona, pero no crea objetos para AbuseReports o Juegos - simplemente devuelve una pila de filas. Cuando hago referencia a estos objetos desde mi vista, los carga de nuevo. ¿Hay alguna manera de arreglar esto? O alguna forma de obtener este comportamiento sin usar: ¿se une?

+0

@jimgreer, ¿hay algún progreso con este problema? – vladr

Respuesta

3

El problema que está teniendo es que usa ActiveRecord de forma que no se "supone" que se use. Con eso quiero decir que estás escribiendo tu propio sql, lo que hace que AR te deje todo el control.

Si desea que AR maneje todo lo que debe tratar de usar con menos de su propio SQL allí. Parece que quieres saber qué usuario tiene la mayor cantidad de AbuseReports. Intentar algo como esto:

some_user.abuse_reports.count 

para obtener el recuento de abuse_reports

11

En primer lugar, usted debe utilizar: incluir en lugar de: une

User.find(:all, :include => { :abuse_reports => [ :game ] }, :order =>) 

o, en su caso, intente

User.page(params[:page], :include => { :abuse_reports => [ :game ] }) 

Esto realizará la unión para usted y recuperar los registros en una sola toma.

Ahora, esto puede recuperar un determinado juego para usted varias veces (si el mismo juego está vinculado a un usuario por varios informes). Si su juego es grande, puede reducir la cantidad de datos intercambiados entre su aplicación y el RDBMS de la siguiente manera:

class User < ActiveRecord::Base 
    has_many :abuse_reports 
    has_many :abused_games, :through => :abuse_reports 
end 
... 

User.find(:all, :include => [ :abuse_reports, :abused_games ]) 

Finalmente, también desea recuperar los recuentos y ordenar en consecuencia. Consulte http://railscasts.com/episodes/23 para saber cómo agregar cachés de contador a los registros activos reales (los cachés de los contadores simplifican el SQL y hacen que la vida del RDBMS sea más fácil y sus consultas se ejecutan más rápido). Después de configurar las memorias caché de venta libre, que finalmente puede alterar la anterior para hacer:

User.find(:all, :include => [ :abuse_reports, :abused_games ], :order => 'users.abused_games_count DESC, users.abuse_reports_count DESC') 

De esta manera podrán recuperar sus ActiveRecords en una sola , sencilla instrucción SQL.

Cuestiones relacionadas