Alcance complejo, rieles 3

Así que estoy creando una aplicación que se adapta a los usuarios. Los modelos de usuario tienen 3 atributos (que son relevantes para mi pregunta de todos modos: gender:string, looking_for_men:boolean, looking_for_women:boolean.

actualmente tengo un método en mi modelo así:

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

Esto es bastante complicado, como puede ver. ¿Hay alguna forma de limpiar esto y convertirlo en un alcance, de modo que digamos, por ejemplo, que soy un usuario masculino, y estoy buscando mujeres que devuelve solo mujeres que buscan hombres cuando hago una consulta como esta:

@users = User.all.browse

preguntado el 27 de agosto de 11 a las 22:08

2 Respuestas

Solo haría el código a continuación, para hacerlo más legible. Pero de alguna manera, no me siento totalmente cómodo con esta solución. Todavía mucho código:

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

contestado el 31 de mayo de 14 a las 23:05

Me gusta esto. Cambiaría el nombre de los ámbitos looking_for_men y looking_for_women solo por legibilidad (chocando con los booleanos); pero eso no es realmente necesario. - nathanvda

Solo desde el punto de vista del alcance, podría mover esa lógica a un alcance con bastante facilidad simplemente pasándola a 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)

y también podría encadenar los ámbitos para limpiar la lógica: http://edgerails.info/articles/what-s-new-in-edge-rails/2010/02/23/the-skinny-on-scopes-formerly-named-scope/index.html.

No estoy seguro de si eso responde a tu pregunta.

Respondido 28 ago 11, 03:08

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.