2010-03-30 22 views
4

Hy,J'ai une relation has_many et je veux définir la limite et le décalage personnalisés. ainsi que pour les compter

Mon code:

@profile.images 

et je voudrais obtenir seulement 10 images à la fois et avec un 10 décalage, comme celui-ci

@profile.images(:limit => 10, :offset => 10) 

et pas comme ça

has_many :images, :limit => 10, :offset => 10 

Ensuite, je voudrais compter en quelque sorte toutes les images pour ce profil.

@profile.count_images 

Merci (:.


has_many :images, :foreign_key => 'on_id', :conditions => 'on_type = "profile"' do 
def paginate(page = 1, limit = 10, offset = nil) 
    page = nil if page < 1 
    limit = 1 if limit < 1 
    offset = 0 if(offset && offset < 0) 
    offset = 0 if (!page) 
    offset = limit * (page - 1) if (page) 

    all(:limit=> limit, :offset => offset) 
end 

fin

Maintenant, je voudrais ajouter ce comportement à d'autres relations has_many Mais je ne voudrais pas copier coller le code .. Une idée?: P

Répondre

7

Utiliser des extensions d'association:

class Profile < ActiveRecord::Base 
    has_many :images do 
    def page(limit=10, offset=0) 
     all(:limit=> limit, :offset=>offset) 
    end 
    end 
end 

vous pouvez maintenant utiliser la méthode page comme suit:

@profile.images.page # will return the first 10 rows 
@profile.images.page(20, 20) # will return the first 20 rows from offset 20 
@profile.images # returns the images as usual 

Modifier

Dans ce cas précis, la fonction d'association pourrait être un o approprié ption. Même lambda avec named_scope pourrait fonctionner. Si vous le définissez sur la classe Profile, vous perdez l'aspect réutilisable du named_scope. Vous devez définir le named_scope sur votre classe d'image.

class Image < ActiveRecord::Base 

    named_scope :paginate, lambda { |page, per_page| { :offset => ((page||1) -1) * 
           (per_page || 10), :limit => :per_page||10 } } 

end 

Vous pouvez maintenant utiliser ce named_scope avec l'association:

@profile.images.paginate(2, 20).all 

Ou vous pouvez utiliser le named_scope directement sur la Image classe

Image.paginate(2, 20).all(:conditions => ["created_at > ?" , 7.days.ago]) 

D'autre part, pourquoi êtes-vous n'utilisant pas le plugin will_paginate?

+1

Merci, c'est beaucoup mieux. J'ai compris, mais ce n'est pas vraiment cool: named_scope: paginate, lambda {| page, limite, offset | {: limite => limite || 10,: offset => offset || ((limit || 10) * (page - 1))}} merci vraiment!maintenant je vais l'essayer;) –

+0

+1 pour une technique plus avancée – vladr

+0

J'ai mis à jour ma réponse avec une solution named_scope. –

1

Vous pouvez utiliser with_scope pour étendre votre appel à @profile.images, et effectuez le compte en dehors de la portée.

Image.with_scope(:find => { :limit => 10, :offset => 10 }) do 
    @profile.images  # load association using limit and offset 
end 

@profile.images.reset # reset cached association, else size would return <=10 
@profile.images.size # go to the database again for a real COUNT(*) 
+0

Merci. Vous m'avez donné une nouvelle idée: named_scope: limit, lambda {| num | {: limit => num}} named_scope: offset, lambda {| num | {: limit => num}} puis @ profile.images.limit (10) .offset (10) –