Rails 가상 속성 검색 또는 SQL 결합 열 검색
-
05-07-2019 - |
문제
'First'및 'Last'속성이있는 사용자 모델이 있습니다.
이 사용자 모델에는 가상 속성 '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
예를 들어 :
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"
예를 들어 동적 찾기를 위해 그 가상 속성으로 검색 할 수 있다면 너무 좋을 것입니다.
User.find_by_full_name('Home Simpson') # this doesn't work
찾기 조건에 대한 예 :
User.all(:conditions => ['full_name LIKE ?', query]) #this doesn't work
나는 이것을 할 수있는 SQL 언어로 적어도 몇 가지 방법을 찾기를 바라고있다. 동적 가상 속성이 발견되면 슈트 루델의 추가 바닐라 소스입니다. (이번 겨울에 이것을 가진 사람?)
예를 들어 "Holmes"는 'First'열에서만 검색 될 수 있지만 '마지막'은 예를 들어 검색 할 수있는 이름을 검색하는 것에 대해 걱정했습니다. User.first.full_name #=> "Sherlock Holmes"
.
더 포괄적 인 검색을 시도했습니다.
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
예를 들어
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"]
그러나 나는 여기서 find_by_full_name 메소드가 다루기 어려웠다 고 생각했습니다.
내 따라서 특히이 사람의 퍼지 기억으로 사람의 이름을 찾는 것이 도움이됩니다. 따라서 그 사람의 첫 번째 또는 성에서 'doe'를 기억한다면, 나는 항상 간단한 사용자를 할 수 있습니다 .find_by_full_name ( 'doe')을 가능한 한 많은 사람들을 반환하여 더 핀 다운 할 수 있습니다.
그리고 열이기 때문에 다음과 같은 작업을 수행 해야하는 경우 찾기 (: 조건 [...]) 절에서 검색 할 수 있습니다. Project.find(:all,:include => :users, :conditions=>['users.full_name LIKE ?', query])
어디
#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
해피 홀리데이 n
해결책
user.rb에서 named_scope를 사용할 수 있습니다.
named_scope :find_by_full_name, lambda {|full_name|
{:conditions => {:first => full_name.split(' ').first,
:last => full_name.split(' ').last}}
}
그런 다음 할 수 있습니다 User.find_by_full_name('John Carver')
요구 사항 변경에 대한 새로운 자료
named_scope :find_by_full_name, lambda {|full_name|
{:conditions => ["first LIKE '%?%' or last LIKE '%?%'",
full_name.split(' ').first, full_name.split(' ').last]}}
다른 팁
Jim의 답변도 도움이되었습니다. 감사. 그래도 약간의 변화를 할 것입니다. 이 현재 코드는 중간 이름을 잃게됩니다. 내가 아래에있는 것은 약간 지저분하지만 중간 이름과 복합 성을 보존합니다 (Jean-Claude van Damme 생각). 이름 이후의 모든 것은 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(' ')}
}
}
물론이를 수행하는 더 깨끗한 방법은 환영합니다.