Сделать заглавными только первый символ строки и не трогать другие? (Рельсы)

102

Я пытаюсь заставить Rails использовать первый символ строки с заглавной буквы, а все остальные оставить такими, какие они есть. Я столкнулся с проблемой, когда «я из Нью-Йорка» превращается в «Я из Нью-Йорка».

Какой метод я бы использовал для выбора первого символа?

Спасибо

РЕДАКТИРОВАТЬ: Я попытался реализовать то, что предложил Мацек, но получаю ошибку «undefined method` capitalize '» . Код отлично работает без строки с заглавными буквами. Спасибо за помощь!

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title[0] = self.title[0].capitalize
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with? 'You know you'
end

РЕДАКТИРОВАТЬ 2: Получил работу. Спасибо за помощь!

РЕДАКТИРОВАТЬ 3: Подождите, нет, я не ... Вот что у меня есть в моей модели списка.

def fixlistname!
  self.title = self.title.lstrip + (title.ends_with?("...") ? "" : "...")
  self.title.slice(0,1).capitalize + self.title.slice(1..-1)
  errors.add_to_base("Title must start with \"You know you...\"") unless self.title.starts_with?  'You know you'
end

РЕДАКТИРОВАТЬ 4: Пробовал редактировать мацека, но по-прежнему получаю ошибку undefined method "capitalize" . Что я делал не так?

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

РЕДАКТИРОВАТЬ 5: Это странно. Я могу избавиться от ошибки неопределенного метода, используя строку ниже. Проблема в том, что кажется, что первая буква заменяется цифрой. Например, вместо того, чтобы использовать букву y в слове You , он превращает y в 121

self.title[0] = title[0].to_s.capitalize
Дэниел О'Коннор
источник
Исходя из EDIT 3, вам нужно начать строку 2 с self.title = . Кроме того, во всех трех строках вам нужно только self.titleслева от =(знака равенства). В других местах можно просто использовать title. Смотрите редактирование моего ответа для примера.
maček
2
Проблема в Edit4 состоит в том, что у вас есть только символ - больше не строка - поэтому он не распознает строковую функцию "capitalize".
Taryn East
Проблема с Edit 5 заключается в том, что title [0] является фиксированным числом, поэтому вызов title [0] .to_s просто даст вам номер символа (т.е. 121 в виде строки: «121»). Вы можете сделать self.title [0] = title.first.capitalize, если хотите!
Ник,
Я добавил #upcase_first_case и сделал запрос на перенос: github.com/rails/rails/pull/15319 . Не стесняйтесь оставлять здесь свои отзывы.
Aldo 'xoen' Giambelluca

Ответы:

93

Заголовок будет писать каждое слово с большой буквы. Эта строка кажется объемной, но гарантирует, что единственная измененная буква - первая.

new_string = string.slice(0,1).capitalize + string.slice(1..-1)

Обновить:

irb(main):001:0> string = "i'm from New York..."
=> "i'm from New York..."
irb(main):002:0> new_string = string.slice(0,1).capitalize + string.slice(1..-1)
=> "I'm from New York..."
Тарин Восток
источник
Подождите, все еще не работает. Ложная тревога: / Думаю, я просто неправильно это использую.
Дэниел О'Коннор,
1
Дэниел - это вообще хороший тоном «принять» ответ, который решил вашу проблему. Вы можете сделать это, нажав «галочку» слева от ответа. :)
Taryn East
1
Я неправильно понял вопрос, иначе я бы поставил вам 1 балл. Я искал .titleize вместо .capitalize. В любом случае спасибо, Тарин!
Eric Wanchic
OOC - Почему это мешает вам проголосовать за? Правильно ли я ответил на вопрос автора? Если вы так считаете - тогда проголосуйте. Это не обязательно должно зависеть от чего-то еще ... :)
Taryn East
2
Итак, вот оно: s[0].capitalize + s[1..-1] if s.present?
Алекс Эскаланте
126

Это должно сделать это:

title = "test test"     
title[0] = title[0].capitalize
puts title # "Test test"
Паскаль Ван Хекке
источник
40
Или более кратко,title[0] = title[0].capitalize
Джон Гарвин
Это очень элегантное решение.
Карев
1
@JonGarvin title [0] .capitalize не работает (по крайней мере, с Ruby 1.8.7), поскольку title [0] возвращает Fixnum, а capitalize ожидает строку .. поэтому я думаю, что title.first.capitalize - это способ идти.
Ник,
2
позор, что ты не можешьtitle.first.capitalize!
Адам Уэйт
1
capitalizeпреобразует все буквы после первой буквы в нижний регистр, поэтому это не работает для строки, представленной в вопросе («я из Нью-Йорка»).
Марк Шнайдер
57

Вы можете использовать humanize. Если вам не нужны подчеркивания или другие заглавные буквы в текстовых строках.

Вход:

"i'm from New_York...".humanize

Вывод:

"I'm from new york..."
Bartuzz
источник
7
ОП специально хотел избежать «Нью-
Йорка
Хм, действительно, мой ответ слишком быстр.
Bartuzz
17
@Bartuzz Хотя OP не хотел этого, это именно то, что я искал. Спасибо!
Йетти
Однако слово "Нью-Йорк" не грамматично, так как это имя собственное, и в нем следует использовать заглавные буквы.
Шейн
Будьте humanizeосторожны , это Rails, а точнее метод ActiveSupport. Обычный рубин не может этого сделать.
Penguin
51
str = "this is a Test"
str.sub(/^./, &:upcase)
# => "This is a Test"
Лассе Банк
источник
1
Лаконично и элегантно. Я считаю, что это должен быть главный ответ.
Крис
Я согласен. Я думаю, это должен быть принятый ответ.
Гарри
Одна причуда в том, что, поскольку ^означает начало строки, "\nfoo"становится "\nFoo". Вероятно, это нормально для большинства случаев использования. Поскольку это a, subа не a gsub, он по-прежнему будет отображать только одну букву, даже с многострочными строками.
Henrik N
Можно получить указанное выше ограничение, используя str.sub(/\S/, &:upcase), который найдет первый непробельный символ и повысит его.
Энтони
39

Начиная с Rails 5.0.0.beta4 вы можете использовать новый String#upcase_firstметод или ActiveSupport::Inflector#upcase_firstделать это. Проверьте это сообщение в блоге для получения дополнительной информации.

user1519240
источник
Это прекрасные новости! Я думал, что мы можем сделать прямо сейчас, и, может быть, полифилл для Rails 4 был бы неплохим.
Хакунин
Обратите внимание, что upcase_first и не обрабатывает акценты / специальные символы, даже с mb_chars
user3033467 02
14

Объектно-ориентированное решение:

class String
  def capitalize_first_char
    self.sub(/^(.)/) { $1.capitalize }
  end
end

Тогда вы можете просто сделать это:

"i'm from New York".capitalize_first_char
лманнеры
источник
Хоть кто-то написал элегантное решение с расширением Stringкласса.
Дмитрий
@Dmitriy, почему обезьяна исправляет класс строки элегантно?
Джерард Симпсон
6

Редактировать 2

Кажется, я не могу повторить вашу проблему. Продолжайте и запустите этот собственный сценарий Ruby. Он генерирует точный результат, который вы ищете, и Rails поддерживает все эти методы. С какими входами у вас проблемы?

#!/usr/bin/ruby
def fixlistname(title)
  title = title.lstrip
  title += '...' unless title =~ /\.{3}$/
  title[0] = title[0].capitalize
  raise 'Title must start with "You know you..."' unless title =~ /^You know you/
  title
end

DATA.each do |title|
  puts fixlistname(title)
end

__END__
you know you something WITH dots ...
you know you something WITHOUT the dots
  you know you something with LEADING whitespace...
  you know you something with whitespace BUT NO DOTS
this generates error because it doesn't start with you know you

вывод

You know you something WITH dots ...
You know you something WITHOUT the dots...
You know you something with LEADING whitespace...
You know you something with whitespace BUT NO DOTS...
RuntimeError: Title must start with "You know you..."

редактировать

Основываясь на ваших изменениях, вы можете попробовать что-то вроде этого.

def fixlistname!
  self.title = title.lstrip
  self.title += '...' unless title.ends_with?('...')
  self.title[0] = title[0].capitalize
  errors.add_to_base('Title must start with "You know you..."') unless title.starts_with?("You know you")
end

Оригинал

Это поможет

s = "i'm from New York"
s[0] = s[0].capitalize
#=> I'm from New York

При попытке использовать String#capitalizeдля всей строки вы видели, I'm from new yorkпотому что метод:

Возвращает копию str с первым символом, преобразованным в верхний регистр, а остаток в нижний регистр.

"hello".capitalize    #=> "Hello"
"HELLO".capitalize    #=> "Hello"
"123ABC".capitalize   #=> "123abc"
Мачек
источник
+1 потому что я не думал, что это сработает, пока не попробовал на своем компьютере :)
Джерико
Привет, спасибо за помощь. Что я делаю не так? Я отредактировал исходный вопрос, включив в него свой код.
Дэниел О'Коннор,
Я воспользовался предложением Тарин, и оно сработало. Спасибо за помощь!
Дэниел О'Коннор,
Привет, stackoverflow говорит, что вы внесли изменения, но я не вижу ничего другого?
Дэниел О'Коннор,
6
my_string = "hello, World"
my_string.sub(/\S/, &:upcase) # => "Hello, World"
Павел Правосуд
источник
Не терпит неудачу, если my_string пуста! Ницца. Это то, что мне нужно.
Huliax
4

Большинство из этих ответов редактируют строку на месте, когда вы просто форматируете для вывода представления, вы можете не захотеть изменять базовую строку, чтобы вы могли использовать tapпосле a, dupчтобы получить отредактированную копию

'test'.dup.tap { |string| string[0] = string[0].upcase }
Paul.s
источник
3

Если и только если OP захочет выполнить исправление обезьяны на объекте String, то это можно использовать

class String
  # Only capitalize first letter of a string
  def capitalize_first
    self.sub(/\S/, &:upcase)
  end
end

Теперь используйте это:

"i live in New York".capitalize_first #=> I live in New York
JVK
источник
2

Еще более короткая версия могла бы быть:

s = "i'm from New York..."
s[0] = s.capitalize[0]
Саим
источник
2

Никто не упомянул gsub, что позволяет сделать это кратко.

string.gsub(/^([a-z])/) { $1.capitalize }

Пример:

 > 'caps lock must go'.gsub(/^(.)/) { $1.capitalize }
=> "Caps lock must go"
Mahemoff
источник
1

Пожалуй, самый простой способ.

s = "test string"
s[0] = s[0].upcase
# => "Test string"
Лукас Балиак
источник
1

Обратите внимание, что если вам нужно иметь дело с многобайтовыми символами, то есть если вам нужно интернационализировать свой сайт, s[0] = ...решение не будет адекватным. Этот вопрос о переполнении стека предлагает использовать драгоценный камень unicode-util

Ruby 1.9: как правильно регистрировать и убирать многобайтовые строки?

РЕДАКТИРОВАТЬ

На самом деле более простой способ хотя бы избежать странных строковых кодировок - просто использовать String # mb_chars :

s = s.mb_chars
s[0] = s.first.upcase
s.to_s
внешний вид
источник
0

А как насчет метода классификации в строке?

'somESTRIng'.classify

вывод:

#rails => 'SomESTRIng'
mArtinko5MB
источник
1
Он делает много дополнительных вещей, например, выделяет слова в единственном числе. "hello worlds".classify # => "Hello world"
Павел Правосуд
-3
string = "i'm from New York"
string.split(/\s+/).each{ |word,i| word.capitalize! unless i > 0 }.join(' ')
# => I'm from New York
Джерико
источник
Кажется, так. Я новичок в рубине, и другие ответы на самом деле не делали того, что просил OP, поэтому я заставил его работать: D Исправьте меня, если я ошибаюсь, но AFAIK, изменяющий строку, изменяя строку [i], не работать на множестве языков?
Джерико
3
это вопрос, относящийся к Ruby. Неважно, работает ли string[i]он на других языках. Пожалуйста, помогите избавить StackOverflow от таких надуманных ответов. Мы не можем сказать RTFM, но даже беглый взгляд на Stringдокументацию помог бы избежать такого ответа ...
maček