【问题标题】:Complex Scope, Rails 3复杂范围,Rails 3
【发布时间】:2011-11-05 06:34:42
【问题描述】:

所以我正在构建一个匹配用户的应用程序。用户模型有 3 个属性(无论如何都与我的问题相关:gender:stringlooking_for_men:booleanlooking_for_women:boolean

目前我的模型中有这样的方法:

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

如您所知,这非常混乱。无论如何要清理它并使其成为一个范围,例如我是一个男性用户,我正在寻找女性,当我进行这样的查询时它只返回正在寻找男性的女性:

@users = User.all.browse

【问题讨论】:

    标签: ruby-on-rails ruby-on-rails-3 activerecord scope


    【解决方案1】:

    我会做下面的代码,使其更具可读性。但不知何故,我对这个解决方案并不完全满意。还是很多代码:

    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
    

    【讨论】:

    • 我喜欢这个。我将重命名范围 looking_for_menlooking_for_women 只是为了便于阅读(与布尔值冲突);但这并不是真正需要的。
    【解决方案2】:

    仅从作用域的角度来看,只需将逻辑传递给 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)
    

    您还可以将范围链接在一起以清理逻辑:http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.html

    我不确定这是否完全回答了你的问题?

    【讨论】:

      猜你喜欢
      • 2014-10-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多