Domanda

Ho un modello utente con gli attributi 'first' e 'last' Quindi per esempio User.first.first # = > & Quot; Charlie " User.first.last # = > & Quot; Brown "

Questo modello utente ha anche un attributo virtuale '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

Quindi, per esempio:

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"

Sarebbe così bello se potessi cercare quell'attributo virtuale quindi ad esempio per la ricerca dinamica:

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

Esempio di condizioni in find:

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

Spero di trovare almeno alcuni modi in linguaggio SQL che possano farlo; se c'è anche un attributo virtuale dinamico, trova anche una fonte extra di vaniglia nello strudel. (qualcuno lo ha questo inverno?)

Ero anche preoccupato per la ricerca di un nome, ad esempio "Holmes" può essere cercato solo nella colonna 'first' ma non nell''ultimo 'per recuperare, ad esempio User.first.full_name # = > " Sherlock Holmes " .

Ho provato a fare una ricerca più 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

Ad esempio

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"]

Ma ho solo pensato che il metodo find_by_full_name qui sia un po 'ingombrante.

Voglio dire, se avessi una colonna full_name che viene impostata ogni volta da un filtro after save con il concat di first e last. Quindi è utile trovare il nome di una persona, specialmente con la memoria confusa di questa persona. Quindi, se mi ricordo di 'Doe' nel nome o nel cognome di quella persona, posso sempre fare un semplice User.find_by_full_name ('Doe') per restituire il maggior numero possibile per appuntarlo ulteriormente.

E poiché è una colonna, posso cercarla in una clausola find (: condizioni [...]) se devo fare qualcosa come Project.find (: all,: include = >: utenti,: condizioni = > ['users.full_name LIKE?', query]) dove

#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

Buone vacanze N

È stato utile?

Soluzione

Puoi usare named_scope nel tuo user.rb:

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

Quindi puoi fare User.find_by_full_name ('John Carver')

nuovi contenuti in risposta a cambiamenti nei requisiti

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

Altri suggerimenti

Ho trovato utile anche la risposta di Jim. Grazie. Farei un piccolo cambiamento però. Questo codice corrente ti fa perdere qualsiasi secondo nome. Quello che ho sotto è un po 'disordinato ma conserva i nomi medi e i cognomi composti (pensa Jean-Claude van Damme). Tutto ciò che segue il nome va nel campo last_name.

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(' ')}
   }
}

Ovviamente qualsiasi modo più pulito per farlo è il benvenuto.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top