Pregunta

Tengo un modelo de usuario con los atributos 'primero' y 'último' Así por ejemplo Usuario.first.first # = > " Charlie " User.first.last # = > " Marrón "

Este modelo de usuario también tiene un atributo virtual 'full_name'

#user.rb
def full_name
  [first,last].join(' ')
end

def full_name=(name) #don't know what to do with people w/ middle names
  split = name.split(' ')
  self.first = split[0]
  self.last = split[1]
end

Entonces, por ejemplo:

User.first.full_name = "Charlie Brown" #=> "Charlie Brown"
User.first.full_name = "Homer Simpson" #=> "Home Simpson"
User.first.save
User.first.first #=> "Homer"
User.first.last #=> "Simpson"

Sería tan bueno si pudiera buscar por ese atributo virtual así, por ejemplo, para la búsqueda dinámica:

User.find_by_full_name('Home Simpson') # this doesn't work

Ejemplo de condiciones en encontrar:

User.all(:conditions => ['full_name LIKE ?', query]) #this doesn't work

Espero encontrar al menos algunas formas en lenguaje SQL que puedan hacer esto; si también hay un atributo virtual dinámico, esa es una fuente extra de vainilla en el strudel. (¿Alguien tiene esto este invierno?)

También me preocupaba que se buscara un nombre, por ejemplo, "Holmes" solo se puede buscar en la "primera" columna pero no en la "última" para recuperar, por ejemplo, User.first.full_name # = > " Sherlock Holmes " .

Intenté hacer una búsqueda más completa:

user.rb

def self.find_by_full_name(name) #returns an array of User model
  return all if name.blank?

  split = name.split(' ', 2)
  output = []
  if split.length > 1
    with_scope( :find => { :conditions => ['first LIKE ?', "%#{split[0]}%"] }) do
      output << all(:conditions => ['last LIKE ?', "%#{split[1]}%"])
      output.flatten!
    end
  elsif split.length == 1
    output << all(:conditions => ['first LIKE ?', "%#{split[0]}%"])
    output << all(:conditions => ['last LIKE ?', "%#{split[0]}%"])
    output.flatten!
  end
end

Por ejemplo

User.find_by_full_name("John").map(&:full_name) #=> ["John Resig", "John Doe"]
User.find_by_full_name("Doe").map(&:full_name) #=> ["John Doe", "Philips Doeringer"]
User.find_by_full_name("John Doe").map(&:full_name) #=> ["John Doe"]

Pero simplemente pensé que el método find_by_full_name aquí es un poco difícil de manejar.

Quiero decir, si tengo una columna full_name que se establece cada vez por un filtro de guardado posterior con la concat de primera y última. Por lo tanto, es útil encontrar el nombre de una persona, especialmente con el recuerdo borroso de esta persona. Entonces, si recordaba 'Doe' en el nombre o apellido de esa persona, siempre puedo hacer un User.find_by_full_name ('Doe') simple para devolver el mayor número posible para seguir precisándolo.

Y como es una columna, puedo buscarla en una cláusula de búsqueda (: condiciones [...]) si tengo que hacer algo como Project.find (: all,: include = >: usuarios,: conditions = > ['users.full_name LIKE?', consulta]) donde

#project.rb
has_many :assignments
has_many :users, :through=>:assignments

#user.rb
has_many :assignments
has_many :projects, :through => :assignments

#assignment.rb
belongs_to :user
belongs_to :project

Felices fiestas N

¿Fue útil?

Solución

Puedes usar un named_scope en tu usuario.rb:

named_scope :find_by_full_name, lambda {|full_name| 
  {:conditions => {:first => full_name.split(' ').first, 
     :last => full_name.split(' ').last}}
}

Luego puedes hacer User.find_by_full_name ('John Carver')

novedades en respuesta a cambios en el requisito

named_scope :find_by_full_name, lambda {|full_name| 
  {:conditions => ["first LIKE '%?%' or last LIKE '%?%'", 
    full_name.split(' ').first, full_name.split(' ').last]}}

Otros consejos

También encontré útil la respuesta de Jim. Gracias. Sin embargo, haría un ligero cambio. Este código actual hace que pierdas cualquier segundo nombre. Lo que tengo a continuación es un poco desordenado pero conserva los nombres medios y los apellidos compuestos (creo que Jean-Claude van Damme). Todo después del primer nombre va en el campo apellido_.

named_scope :find_by_full_name, lambda { |full_name| 
 {:conditions => {:first_name => full_name.split(' ').first, 
   :last_name => full_name.split(' ')[1, full_name.split(' ').length-1].join(' ')}
   }
}

Por supuesto, cualquier forma más limpia de hacer esto es bienvenida.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top