Почему заглавная буква Rails добавляет пробел к имени? - PullRequest
17 голосов
/ 11 апреля 2011

Почему 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

Я пытаюсь убедиться, что все имена являются заглавными буквами в БД, но в ситуациях с именем верблюдного имени это не удается.Есть идеи как это исправить?

Ответы [ 9 ]

16 голосов
/ 11 апреля 2011

Вы всегда можете сделать это самостоятельно, если 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 
3 голосов
/ 11 апреля 2011

Хм, это странно ... но вы можете написать быстрое пользовательское регулярное выражение, чтобы избежать использования этого метода.

class String
    def custom_titlecase
        self.gsub(/\b\w/) { |w| w.upcase }
    end
end

"John Mark McMillan".custom_titlecase    # => "John Mark McMillan"

Источник

3 голосов
/ 11 апреля 2011

Если все, что вам нужно, это убедиться, что каждое слово начинается с заглавной буквы:

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 голосов
/ 11 апреля 2011

Отредактировано (вдохновлено предложением Железного Человека)

Хак будет:

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"
1 голос
/ 31 марта 2017

Если вы хотите обработать случай, когда кто-то ввел 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;)

1 голос
/ 11 апреля 2011

Документация для заглавной буквы гласит ([выделение добавлено]):

Прописывает все слова и заменяет некоторые символы в строке до создать более привлекательный заголовок. titleize предназначен для создания красивой продукции. Он не используется во внутренностях Rails.

Я только догадываюсь здесь, но, возможно, он рассматривает PascalCase как проблему - возможно, он думает, что это имя ActiveRecordModelClass.

0 голосов
/ 13 февраля 2019

На вопрос "Почему" уже был ответ ... но, как свидетельствуют выбранные ответы и отклики, я думаю, что большинство из нас на самом деле хотят серебряную пулю, чтобы справиться с адом, который такое форматирование имен ... Хотя такое поведение запускается несколькими прописными буквами, я обнаружил, что дефисные имена делают то же самое.

Эти и многие другие случаи уже были обработаны в геме, 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"

Если вы чувствуете, что вам нужно обработать все угловые случаи на этой странице, и вам нет дела до потери имен, которые могли быть отформатированы в начале, например. Йен Макдональд (из Ирландии) ... сначала вы могли бы использовать 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"

Единственная серебряная пуля - идти в старую школу ... ВСЕ КОПЫ. Но кому нужна эта глазница в их современном веб-приложении?

0 голосов
/ 08 сентября 2016

Вы также можете встретить имена с двумя заглавными буквами, такие как McLaren, McDonald и т. Д.

Не потратил времени на его улучшение, но вы всегда можете сделать

Код

# 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"
0 голосов
/ 11 апреля 2011

Вы пытаетесь использовать универсальный метод для преобразования внутренних строк Rail в более удобочитаемые имена.Он не предназначен для работы с «Mc», «Mac», «Van Der» и любым другим составным написанием.

Вы можете использовать его в качестве отправной точки, затем в специальном случае результаты, искать места, где он ломается и делать некоторые исправления, или вы можете написать свой собственный метод, который включает специальный случай этих крайних случаев.За эти годы мне приходилось делать это несколько раз в разных приложениях.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...