为什么Rails titlecase会为名称添加空格?
为什么这个titlecase
搞砸这个名字? 我有:
John Mark McMillan
它把它变成:
>> "john mark McMillan".titlecase => "John Mark Mc Millan"
为什么在姓氏上添加了空格?
基本上我在我的模型中有这个:
before_save :capitalize_name def capitalize_name self.artist = self.artist.titlecase end
我试图确保所有名称都是数据库中的标题,但是在使用camelcase名称的情况下,它会失败。 任何想法如何解决这一问题?
如果Rails不够好,你总是可以自己做:
class String def another_titlecase self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ") end end "john mark McMillan".another_titlecase => "John Mark McMillan"
这种方法比正则表达式解决方案快一小部分:
我的解决方案
ruby-1.9.2-p136 :034 > Benchmark.ms do ruby-1.9.2-p136 :035 > "john mark McMillan".split(" ").collect{|word|word[0] = word[0].upcase; word}.join(" ") ruby-1.9.2-p136 :036?> end => 0.019311904907226562
正则表达式解决方案:
ruby-1.9.2-p136 :042 > Benchmark.ms do ruby-1.9.2-p136 :043 > "john mark McMillan".gsub(/\b\w/) { |w| w.upcase } ruby-1.9.2-p136 :044?> end => 0.04482269287109375
如果您想要的是确保每个单词都以大写字母开头:
class String def titlecase2 self.split(' ').map { |w| w[0] = w[0].upcase; w }.join(' ') end end irb(main):016:0> "john mark McMillan".titlecase2 => "John Mark McMillan"
嗯,这很奇怪..但你可以写一个快速的自定义正则表达式,以避免使用该方法。
class String def custom_titlecase self.gsub(/\b\w/) { |w| w.upcase } end end "John Mark McMillan".custom_titlecase # => "John Mark McMillan"
资源
编辑 (受锡人的建议启发)
黑客将是:
class String def titlecase gsub(/(?:_|\b)(.)/){$1.upcase} end end p "john mark McMillan".titlecase # => "John Mark McMillan"
请注意,字符串'john mark McMillan'
在大小写中不一致,并且作为人类输入有点意外,或者如果它不是来自人类输入,您可能不应该以这种方式存储字符串。 像'john mark mc_millan'
这样'john mark mc_millan'
字符串更加一致,如果你定义这样的约定,它更有可能作为人类输入出现。 我的答案也将处理这些案件:
p "john mark mc_millan".titlecase # => "John Mark McMillan"
titlecase的文档说([强调添加]):
将所有单词大写并替换字符串中的某些字符以创建更好看的标题。 titleize用于创建漂亮的输出。 它不用于Rails内部。
我只是在这里猜测,但也许它认为PascalCase是一个问题 – 也许它认为它是ActiveRecordModelClass
的名称。
您正在尝试使用通用方法将Rail的内部字符串转换为更易读的名称。 它不是为处理“Mc”,“Mac”和“Van Der”以及任何其他复合拼写而设计的。
您可以将它作为一个起点,然后是特殊情况,结果寻找它破坏的地方并做一些修复,或者你可以编写自己的方法,包括特殊的套管那些边缘情况。 多年来,我不得不在不同的应用程序中多次这样做。
您可能还会遇到两个大写字母的名字,例如麦克拉伦,麦当劳等。
没有花时间去改进它,但你可以随时做
码
# Rails.root/config/initializers/string.rb class String def titleize_name self.split(" ") .collect{|word| word[0] = word[0].upcase; word} .join(" ").gsub(/\b('?[az])/) { $1.capitalize } end end
例子
[2] pry(main)> "test name".titleize_name => "Test Name" [3] pry(main)> "test name-name".titleize_name => "Test Name-Name" [4] pry(main)> "test McName-name".titleize_name => "Test McName-Name"
如果你想处理有人进入JOHN CAPSLOCK JOE
以及其他人的情况,我将这个结合起来:
class String def proper_titlecase if self.titleize.split.length == self.split.length self.titleize else self.split(" ").collect{|word| word[0] = word[0].upcase; word}.join(" ") end end end
如果你想在String方法上有那种逻辑,取决于它;)