2011-08-27 5 views
4

Je construis donc une application qui correspond aux utilisateurs. modèles d'utilisateurs ont 3 attributs (qui sont pertinents à ma question de toute façon. gender:string, looking_for_men:boolean, looking_for_women:booleanComplex Scope, Rails 3

actuellement j'ai une méthode dans mon modèle comme ceci:

def browse 
    if self.looking_for_men == true && self.looking_for_women == true 
    if self.sex == "Male" 
     User.where("looking_for_men = ?", true) 
    elsif self.sex == "Female" 
     User.where("looking_for_women = ?", true) 
    end 
    elsif self.sex == "Male" && self.looking_for_men == true 
    User.where("looking_for_men = ? AND sex = ?", true, "Male") 
    elsif self.sex == "Female" && self.looking_for_women == true 
    User.where("looking_for_women = ? AND sex = ?", true, "Female") 
    else 
    if self.sex == "Male" 
     User.where("looking_for_men = ? AND sex = ?", true, "Female") 
    elsif self.sex == "Female" 
     User.where("looking_for_women = ? AND sex = ?", true, "Male") 
    end 
    end 
end 

C'est assez désordonné, comme Est-ce qu'il y a de toute façon à nettoyer ça et à en faire un scope, alors disons par exemple que je suis un utilisateur masculin, et je cherche des femmes qui ne renvoie que des femmes qui cherchent des hommes quand je fais une requête comme ceci:

@users = User.all.browse 

Répondre

5

Je voudrais juste faire le code ci-dessous, pour le rendre plus lisible. Mais d'une manière ou d'une autre, je ne suis pas totalement à l'aise avec cette solution. Encore beaucoup de code:

class User < ActiveRecord::Base 
    scope :male, where(:gender => "Male") 
    scope :female, where(:gender => "Female") 
    scope :looking_for_men, where(:looking_for_men => true) 
    scope :looking_for_women, where(:looking_for_women => true) 

    def browse 
    @women = @men = [] 

    @women = self.interested_females if self.looking_for_women 
    @men = self.interested_males if self.looking_for_men 

    @result = @women.concat(@men) 
    @result.delete(self) #removes the user itself from the result-set 

    return @result 
    end 

    def interested_females 
    return User.female.looking_for_men if self.male? 
    return User.female.looking_for_women if self.female? 
    end 

    def interested_males 
    return User.male.looking_for_men if self.male? 
    return User.male.looking_for_women if self.female? 
    end 

    def male? 
    return (self.gender == "Male") 
    end 

    def female? 
    return (self.gender == "Female") 
    end 
end 
+1

J'aime ça. Je renommerais les étendues 'looking_for_men' et' looking_for_women' juste pour la lisibilité (heurtant les booléens); mais ce n'est pas vraiment nécessaire. – nathanvda

1

Juste d'un point de vue de portée, vous pouvez déplacer cette logique dans une portée assez facilement juste en la passant à un proc.

class User 
    scope :browse_for, lambda { |user| 
     user.looking_for_men == true && user.looking_for_women == true 
     ... 
    } 
end 

@users = User.browse_for(@single_male) 

et vous pourriez également enchaîner les étendues ensemble pour nettoyer la logique: http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.html.

Je ne sais pas si cela répond à votre question?