复杂范围,Rails 3

时间:2011-08-27 22:16:50

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

所以我正在构建一个匹配用户的应用程序。用户模型有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

你可以说,这非常混乱。无论如何要清理它并将它变成一个范围,所以例如我说我是一个男性用户,我正在寻找女性,它只返回正在寻找男性的女性,当我这样做一个查询时:< / p>

@users = User.all.browse

2 个答案:

答案 0 :(得分:6)

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

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 :(得分: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

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