我有Ruby on Rails应用程序,它有一个映射到People表的Person模型。该表包括first_name,middle_name和last_name,如下所示:
John Q. Doe
John H. Doe
Jane M. Doe
Jim R. Doe, Jr.
Jack Timothy Doe
现在,当输入是特定名称派生的缩写时,我需要对表执行查找。缩写形式如下:
例如:
find_by_abbreviated_name("J Q Doe") => would find the John Q. Doe record
find_by_abbreviated_name("J T Doe") => would find the Jack Timothy Doe record
find_by_abbreviated_name("J R Doe, Jr.") => Jim R Doe, Jr.
Ruby中是否有一种灵巧的方法可以使用第一个和中间名的第一个字母以及完整的姓氏进行查找。我希望我能想出办法来做到这一点,所以我不必在Person表中添加另一个字段。
答案 0 :(得分:2)
所以我认为你必须处理的问题是输入的格式会有所不同......除非你能保证输入元素。如果middle是可选的,而last可以有多个令牌,那么如果它作为单个字符串传递,你就会遇到一些你无法可靠解析的挑战:
John Doe Jr
John Doe, Jr.
John Quentin Doe
John Doe Worthington-Smythe
(许多姓氏有多个部分等)
因此,您可以通过提供不同的输入字段,通过确认用户的模糊情况,或根据某些规则或常见情况尝试多种备选方案来处理此问题。因此,让我们等待解析部分,并假设您有不同的输入格式正确(例如,大写单字符):
def find_by_abbreviated_name(fist_init, middle_init, last_name)
if middle_init.blank?
People.where("first LIKE ? AND middle LIKE ? and LAST like ?", "#{first_init}%", "#{middle_init}%", "#{last_name}%")
else
People.where("first LIKE ? AND LAST LIKE ?", "#{first_init}%", "#{last_name}%")
end
end
这将导致SQL使用LIKE运算符,这是一个部分匹配 - %
是一个SQL通配符,类似于文件名匹配中的*
或.*
in正则表达式。
抱歉,我的前三次尝试都有错误。我现在正在检查是否有办法更好地使用通配符......
答案 1 :(得分:1)
没有光滑的Ruby方式。您只需构建一个查询。这样的事情应该有效:
def self.find_by_abbreviated_name(name)
if name[3].blank? && name.size >= 5 # Check if there's a middle initial
where("first_name like ? and middle_name like ? and last_name = ?", "#{name[0]}%", "#{name[2]}%", name[4..-1])
else # No middle initial
where("first_name like ? and last_name = ?", "#{name[0]}%", name[2..-1])
end
end
说明:
只有字符串的格式始终相同时,带有名称字符串的“技巧”才有效。 name[0]
给出字符串的第一个字符,name[2]
给出第三个字符,name[4..-1]
将第五个字符返回给字符串的末尾。
我认为where
子句本身非常简单。要仅根据第一个字符查找记录,您可以使用:.where('field_name like ?', "#{query}%")
,其中问号确实是替换值的占位符。
编辑:
我更新了我的答案,省略了中间的首字母。
答案 2 :(得分:1)
此问题是使用字符串排名算法的理想选择!
使用Jquery / Prototype查看Quicksilver算法的this implementation。
基本上,就像其他人已经提到的那样,这很痛苦,因为你不能总是考虑输入数据的格式。
我不相信有一个活跃的gem或ruby端口,但它相当简单。
在rails应用程序中实现此功能意味着
我个人经常避免“建立”查询,AR对我来说就像ORM一样强大。 但是如果你要走这条路,你一定要看看Squeel gem失败的AREL是必须的。