为什么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名称的情况下,它会失败。任何想法如何解决这个问题?
答案 0 :(得分:15)
如果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
答案 1 :(得分:3)
如果您想要的是确保每个单词都以大写字母开头:
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"
答案 2 :(得分:3)
class String
def custom_titlecase
self.gsub(/\b\w/) { |w| w.upcase }
end
end
"John Mark McMillan".custom_titlecase # => "John Mark McMillan"
答案 3 :(得分:2)
已编辑(灵感来自The Tin Man的建议)
黑客将是:
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'
的字符串更加一致,如果您定义此类约定,则更有可能显示为人工输入。我的回答也将处理这些案例:
p "john mark mc_millan".titlecase
# => "John Mark McMillan"
答案 4 :(得分:1)
标题词的documentation表示([强调添加]):
将所有单词 大写并替换 字符串 中的一些字符 创造一个更好看的标题。 titleize 用于创建漂亮的输出。 它没有在Rails内部使用。
我只是在这里猜测,但也许它认为PascalCase是个问题 - 也许它认为它是ActiveRecordModelClass
的名字。
答案 5 :(得分:1)
如果你想处理有人输入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方法的那种逻辑;)
答案 6 :(得分:0)
您正在尝试使用通用方法将Rail的内部字符串转换为更易读的名称。它不是为处理“Mc”,“Mac”和“Van Der”以及任何其他复合拼写而设计的。
您可以将它作为一个起点,然后是特殊情况,结果寻找它破坏的地方并做一些修复,或者你可以编写自己的方法,包括特殊的套管那些边缘情况。多年来,我不得不在不同的应用程序中多次这样做。
答案 7 :(得分:0)
您可能还会遇到两个大写字母的名字,例如麦克拉伦,麦当劳等。
没有花时间尝试改进它,但你总能做到
<强>代码强>
# Rails.root/config/initializers/string.rb
class String
def titleize_name
self.split(" ")
.collect{|word| word[0] = word[0].upcase; word}
.join(" ").gsub(/\b('?[a-z])/) { $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"
答案 8 :(得分:0)
我们刚刚添加了此功能,它支持我们面临的几种不同情况。
class String
# Default titlecase converts McKay to Mc Kay, which is not great
# May even need to remove titlecase completely in the future to leave
# strings unchanged
def self.custom_title_case(string = "")
return "" if !string.is_a?(String) || string.empty?
split = string.split(" ").collect do |word|
word = word.titlecase
# If we titlecase and it turns in to 2 words, then we need to merge back
word = word.match?(/\w/) ? word.split(" ").join("") : word
word
end
return split.join(" ")
end
end
和rspec测试
# spec/lib/modules/string_spec.rb
require 'rails_helper'
require 'modules/string'
describe "String" do
describe "self.custom_title_case" do
it "returns empty string if incorrect params" do
result_one = String.custom_title_case({ test: 'object' })
result_two = String.custom_title_case([1, 2])
result_three = String.custom_title_case()
expect(result_one).to eq("")
expect(result_two).to eq("")
expect(result_three).to eq("")
end
it "returns string in title case" do
result = String.custom_title_case("smiths hill")
expect(result).to eq("Smiths Hill")
end
it "caters for 'Mc' i.e. 'john mark McMillan' edge cases" do
result_one = String.custom_title_case("burger king McDonalds")
result_two = String.custom_title_case("john mark McMillan")
result_three = String.custom_title_case("McKay bay")
expect(result_one).to eq("Burger King McDonalds")
expect(result_two).to eq("John Mark McMillan")
expect(result_three).to eq("McKay Bay")
end
it "correctly cases uppercase words" do
result = String.custom_title_case("NORTH NARRABEEN")
expect(result).to eq("North Narrabeen")
end
end
end
答案 9 :(得分:-1)
“为什么”问题已经answered ...但是,正如所选答案和支持所证明的那样,我认为我们大多数人实际上想要的是解决地狱这一难题的灵丹妙药-formatting ...虽然有多个大写字母触发了该行为,但我发现带连字符的名称也是如此。
这些案例以及更多案例已经在 NameCase 宝石中处理过。
在2.0版中,仅当字符串全部为大写或全部为小写时,才根据定义的规则集转换字符串。我喜欢这个,因为我敢肯定规则集永远不可能是100%正确的。例如, Ian McDonald(来自苏格兰)的大写字母与Ian Mcdonald(来自爱尔兰) 的字母大写不同...但是,如果输入了正确的名称,这些名称将在输入时正确处理用户是特定用户,如果不是,则可以根据需要更正名称并保留其格式。
我的解决方案:
# If desired, add string method once NameCase gem is added
class String
def namecase
NameCase(self)
end
end
测试:(name.namecase)
test_names = ["john mark McMillan", "JOHN CAPSLOCK JOE", "test name", "test name-name", "test McName-name", "John w McHENRY", "ian mcdonald", "Ian McDonald", "Ian Mcdonald"]
test_names.each { |name| puts '# "' + name + '" => "' + name.namecase + '"' }
# "john mark McMillan" => "John Mark McMillan"
# "JOHN CAPSLOCK JOE" => "John Capslock Joe"
# "test name" => "Test Name"
# "test name-name" => "Test Name-Name"
# "test McName-name" => "Test McName-Name"
# "John w McHENRY" => "John w McHENRY" -FAIL
# "ian mcdonald" => "Ian McDonald"
# "Ian McDonald" => "Ian McDonald"
# "Ian Mcdonald" => "Ian Mcdonald"
如果您认为需要处理此页面上的所有特殊情况,并且不必担心丢失开头可能已经格式化的名称,例如。 Ian Mcdonald(来自爱尔兰) ...您可以先使用upcase
:
测试:(name.upcase.namecase)
test_names.each { |name| puts '# "' + name + '" => "' + name.upcase.namecase + '"' }
# "john mark McMillan" => "John Mark McMillan"
# "JOHN CAPSLOCK JOE" => "John Capslock Joe"
# "test name" => "Test Name"
# "test name-name" => "Test Name-Name"
# "test McName-name" => "Test McName-Name"
# "John w McHENRY" => "John W McHenry"
# "ian mcdonald" => "Ian McDonald"
# "Ian McDonald" => "Ian McDonald"
# "Ian Mcdonald" => "Ian McDonald"
唯一的灵丹妙药就是去上学...全部成功。但是谁愿意在他们的现代网络应用程序中看到这种眼神呢?