У Ruby в деяких методах є знак питання ( ?
), який задає подібне include?
запитання, якщо включений відповідний об'єкт, то потім повертається true / false.
Але чому деякі методи мають знаки оклику ( !
), де інші не мають?
Що це означає?
У Ruby в деяких методах є знак питання ( ?
), який задає подібне include?
запитання, якщо включений відповідний об'єкт, то потім повертається true / false.
Але чому деякі методи мають знаки оклику ( !
), де інші не мають?
Що це означає?
Відповіді:
Загалом, методи, які закінчуються, !
вказують на те, що метод буде модифікувати об'єкт, на який він викликається . Рубі називає це " небезпечними методами ", оскільки вони змінюють стан, на який може посилатися хтось інший. Ось простий приклад для рядків:
foo = "A STRING" # a string called foo
foo.downcase! # modifies foo itself
puts foo # prints modified foo
Це виведе:
a string
У стандартних бібліотеках є багато місць, де ви побачите пари аналогічно названих методів, один з методом !
і один без. Ті, які не називаються, називаються "безпечними методами", і вони повертають копію оригіналу зі змінами, застосованими до копії , при цьому виклик не змінюється. Ось такий же приклад без !
:
foo = "A STRING" # a string called foo
bar = foo.downcase # doesn't modify foo; returns a modified string
puts foo # prints unchanged foo
puts bar # prints newly created bar
Цей результат:
A STRING
a string
Майте на увазі, що це лише умова, але багато класів Ruby слідують за нею. Це також допомагає вам відстежувати, що змінюється у вашому коді.
save
and save!
inActiveRecord
Знак оклику означає багато речей, і іноді ви не можете сказати багато чого, окрім "це небезпечно, будьте обережні".
Як говорили інші, в стандартних методах його часто використовують для позначення методу, який змушує об'єкт мутувати себе, але не завжди. Зверніть увагу , що багато стандартні методи змінюють свій приймач і не мають знак оклику ( pop
, shift
, clear
), а також деякі методи з знаками оклику не змінюють свій приймач ( exit!
). Дивіться, наприклад, цю статтю .
Інші бібліотеки можуть використовувати його по-різному. У "Рейлах" знак оклику часто означає, що метод викине виняток на провал, а не на беззвучність.
Це ідентифікація, але багато людей використовують її в тонко різних способах. У вашому власному коді хорошим правилом великих пальців є використання його завжди, коли метод робить щось "небезпечне", особливо коли існують два методи з однаковою назвою і один з них більш "небезпечний", ніж інший. "Небезпечний" може означати майже все, що завгодно.
Ця угода про іменування знята зі схеми .
1.3.5 Названня конвенцій
За умовами, назви процедур, які завжди повертають булеве значення, зазвичай закінчуються на "?". Такі процедури називаються предикатами.
За умовами, назви процедур, які зберігають значення у раніше виділених місцях (див. Розділ 3.4), зазвичай закінчуються на ``! ''. Такі процедури називаються мутаційними процедурами. За умовою, значення, повернене процедурою мутації, не визначено.
! зазвичай означає, що метод діє на об'єкт замість повернення результату. З книги програмування Ruby :
Методи, які є "небезпечними" або модифікують приймач, можуть бути названі "".
Найточніше сказати, що методи з вибухом! є більш небезпечною чи дивною версією. Існує безліч методів, які мутують без удару, наприклад, .destroy
і, як правило, є лише чубки, де в основній зоні існує більш безпечна альтернатива.
Наприклад, у Array у нас є, .compact
і .compact!
обидва методи мутують масив, але .compact!
повертає нуль замість self, якщо в масиві немає нуля, що більш дивно, ніж просто повернення self.
Тільки не мутує метод , який я знайшов з чубчиком це Kernel
«s , .exit!
який більш дивно , ніж .exit
тому , що ви не можете зловити в SystemExit
той час як процес закриття.
Rails та ActiveRecord продовжують цю тенденцію, оскільки вона використовує удар для більш "дивовижних" ефектів, таких як, .create!
що призводить до помилок при відмові.
Від themomorohoax.com:
Чуб можна використовувати в нижченаведеному порядку, в порядку моїх особистих уподобань.
1) Активний метод запису викликає помилку, якщо метод не робить те, що каже, що буде.
2) Активний метод запису зберігає запис або метод зберігає об'єкт (наприклад, смужка!)
3) Метод робить щось «зайве», як-от повідомлення в іншому місці чи якесь дію.
Справа в тому, що використовуйте чубок лише тоді, коли ви дійсно замислювались над тим, чи потрібно це, щоб врятувати інших розробників від роздратування від необхідності перевіряти, чому ви використовуєте чуб.
Банг надає дві підказки іншим розробникам.
1) що не потрібно зберігати об'єкт після виклику методу.
2) при виклику методу db буде змінено.
http://www.themomorohoax.com/2009/02/11/when-to-use-a-bang-exclamation-point-after-rails-methods
Просте пояснення:
foo = "BEST DAY EVER" #assign a string to variable foo.
=> foo.downcase #call method downcase, this is without any exclamation.
"best day ever" #returns the result in downcase, but no change in value of foo.
=> foo #call the variable foo now.
"BEST DAY EVER" #variable is unchanged.
=> foo.downcase! #call destructive version.
=> foo #call the variable foo now.
"best day ever" #variable has been mutated in place.
Але якщо ви коли-небудь закликали метод downcase!
у поясненні вище, foo
змінили б його на постійне зменшення. downcase!
не поверне новий об'єкт рядка, але замінить рядок на місці, повністю змінивши foo
на нижній регістр. Я пропоную вам не користуватися, downcase!
якщо це абсолютно не потрібно.
!
Мені подобається думати про це як про вибухову зміну, яка знищує все, що відбулося до цього. Вибух або знак оклику означає, що ви вносите постійні збережені зміни в свій код.
Якщо ви використовуєте, наприклад, метод Рубі для глобальної заміни, gsub!
заміна, яку ви робите, є постійною.
Ще один спосіб уявити це - відкрити текстовий файл і зробити пошук і заміну, а потім зберегти. !
робить те саме у вашому коді.
Ще одне корисне нагадування, якщо ви приїхали зі світу баш - sed -i
це подібний ефект від внесення постійних збережених змін.
Називають "руйнівними методами" Вони, як правило, змінюють оригінальну копію об'єкта, про який ви посилаєтесь.
numbers=[1,0,10,5,8]
numbers.collect{|n| puts n*2} # would multiply each number by two
numbers #returns the same original copy
numbers.collect!{|n| puts n*2} # would multiply each number by two and destructs the original copy from the array
numbers # returns [nil,nil,nil,nil,nil]
Підсумок: !
методи просто змінюють значення об'єкта, на який вони викликаються, тоді як метод без !
повернення маніпульованого значення, не записуючи над об'єктом, метод був покликаний.
Використовуйте лише, !
якщо ви не плануєте потребувати оригінального значення, збереженого у змінній, на яку ви викликали метод.
Я вважаю за краще робити щось на кшталт:
foo = "word"
bar = foo.capitalize
puts bar
АБО
foo = "word"
puts foo.capitalize
Замість
foo = "word"
foo.capitalize!
puts foo
На всякий випадок, я хотів би знову отримати вихідне значення.
!
мутує об'єкт, а не повертає модифіковану копію.
User.create!