Использование «или» опасно. 'or' имеет более низкий уровень присутствия операторов, чем '=', поэтому следующее имеет неожиданное поведение: a = false или true #a ложно после этого оператора
Tom G
20
@xiy в настоящее время руководство рекомендует делать вид или и и не существует (|| это или && и?)
user3125280
67
Текущие "Ruby Style Guide" стоит The and and or keywords are banned. It's just not worth it. Always use && and || instead.. И это правильно по причинам Дэвида и Тома.
Андре Фигейредо
40
classObjectdef nil_zero?self.nil?||self==0endend# which lets you donil.nil_zero?# returns true0.nil_zero?# returns true1.nil_zero?# returns false"a".nil_zero?# returns falseunless discount.nil_zero?# do stuff...end
Остерегайтесь обычных заявлений об отказе от ответственности ... великой власти / ответственности, исправлений обезьян, ведущих на темную сторону и т. Д.
Обратите внимание, что это специфичный для рельсов ответ. Ванильный рубин не имеет tryметода.
Том Лорд
Верный. Хотя это больше похоже на спецификацию ActiveSupport, которая намного легче и широко используется, чем полные рельсы. В любом случае, ответ @ ndn верный.
переписано
Отредактировано для использования безопасной навигации
переписано
1
Ответ теперь дублирует stackoverflow.com/a/34819818/1954610 ... Я думаю, что есть смысл оставить его так, tryчтобы показать альтернативный вариант (именно поэтому он был отклонен в первую очередь!), При условии, что это ясно для читатель, который ActiveSupportне ванильный рубин.
Том Лорд
Точка занята, ответ откатан.
переписано
27
если только [nil, 0] .include? (скидка)
# ...
конец
Прекрасный? Да. Удобочитаемый? На самом деле, нет.
Эль Ниндзя Трепадор
1
Я нахожу это прекрасно читаемым, и я бы предпочел его новому классу. Отлично сработано.
colincr
Наиболее рубиновый подход к обработке двух условий.
Югендран
23
Начиная с версии 2.3.0, вы можете комбинировать оператор безопасной навигации ( &.) с Numeric#nonzero?. &.возвращает, nilесли экземпляр был nilи nonzero?- если число было 0:
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String.... Это не безопасно использовать на произвольных объектах.
Том Лорд
2
@TomLord, как указано в предыдущем комментарии, не предназначался для работы с произвольными объектами. Вместо этого это касается случая, когда у вас есть что-то, что вы знаете, должно быть числом, но также может быть nil.
ndnenkov
Я хотел бы прояснить этот факт в ответе, вместо того, чтобы кто-то прочитал это и не заметил отказ от комментариев в комментариях.
Том Лорд
@TomLord, это указано в ответе " nonzero?- если номер был 0" . Также необходимость проверять, возникает ли совершенно произвольный объект 0крайне редко по сравнению с тем, чтобы проверять число, которое может или не может быть nil. Следовательно, это почти подразумевается. Даже если кто-то делает противоположное предположение, он сразу же поймет, что происходит, когда попытается его выполнить.
Здесь важен порядок, потому что если discountесть nil, то у него не будет zero?метода. Оценка Руби по короткому замыканию должна препятствовать тому, чтобы он пытался оценить discount.zero?, однако, если discountесть nil.
Не работает для произвольных объектов . "".to_i == "foo".to_i == "0".to_i == 0, Ваш метод сделает все виды непреднамеренных приведения типов. Он также потерпит неудачу, NoMethodErrorесли discountне отвечает to_i.
Том Лорд
2
def is_nil_and_zero(data)
data.blank?|| data ==0end
Если мы передадим "", он вернет false, тогда как пусто? возвращает истину. То же самое в случае, когда data = false blank? возвращает true для nil, false, empty или строки пробела. Так что лучше использовать бланк? метод, чтобы избежать пустой строки.
Вы можете инициализировать скидку до 0, если ваш код гарантированно не будет пытаться использовать ее до инициализации. Полагаю, это сняло бы одну проверку, я больше ни о чем не думаю.
Я считаю, что следующее достаточно для рубинового кода. Я не думаю, что смогу написать модульный тест, который показал бы разницу между этим и оригиналом.
discount
ложь?discount.in? [0, nil]
что более чистый способ возможенОтветы:
источник
The and and or keywords are banned. It's just not worth it. Always use && and || instead.
. И это правильно по причинам Дэвида и Тома.Остерегайтесь обычных заявлений об отказе от ответственности ... великой власти / ответственности, исправлений обезьян, ведущих на темную сторону и т. Д.
источник
хорошо, через 5 лет прошло ....
Важно отметить, что
try
он определен в геме ActiveSupport, поэтому он недоступен в обычном ruby.источник
try
метода.try
чтобы показать альтернативный вариант (именно поэтому он был отклонен в первую очередь!), При условии, что это ясно для читатель, которыйActiveSupport
не ванильный рубин.источник
Начиная с версии 2.3.0, вы можете комбинировать оператор безопасной навигации (
&.
) сNumeric#nonzero?
.&.
возвращает,nil
если экземпляр былnil
иnonzero?
- если число было0
:Или постфикс:
источник
"foo"&.nonzero? # => NoMethodError: undefined method 'nonzero?' for "foo":String
.... Это не безопасно использовать на произвольных объектах.nil
.nonzero?
- если номер был0
" . Также необходимость проверять, возникает ли совершенно произвольный объект0
крайне редко по сравнению с тем, чтобы проверять число, которое может или не может бытьnil
. Следовательно, это почти подразумевается. Даже если кто-то делает противоположное предположение, он сразу же поймет, что происходит, когда попытается его выполнить.источник
Вы могли бы сделать это:
Здесь важен порядок, потому что если
discount
естьnil
, то у него не будетzero?
метода. Оценка Руби по короткому замыканию должна препятствовать тому, чтобы он пытался оценитьdiscount.zero?
, однако, еслиdiscount
естьnil
.источник
Вы можете преобразовать вашу пустую строку в целочисленное значение и проверить ноль ?.
источник
обновить, это будет
false
дляdiscount = false
источник
Вы можете воспользоваться
NilClass
предоставленным#to_i
методом, который будет возвращать ноль дляnil
значений:Если это
discount
могут быть дробные числа, вы можете использовать#to_f
вместо них, чтобы предотвратить округление числа до нуля.источник
"".to_i == "foo".to_i == "0".to_i == 0
, Ваш метод сделает все виды непреднамеренных приведения типов. Он также потерпит неудачу,NoMethodError
еслиdiscount
не отвечаетto_i
.Если мы передадим "", он вернет false, тогда как пусто? возвращает истину. То же самое в случае, когда data = false blank? возвращает true для nil, false, empty или строки пробела. Так что лучше использовать бланк? метод, чтобы избежать пустой строки.
источник
blank?
это метод для рельсов, недоступный в ванильном рубине.При работе с записями в базе данных мне нравится инициализировать все пустые значения с 0, используя помощник по миграции:
источник
Вы можете инициализировать скидку до 0, если ваш код гарантированно не будет пытаться использовать ее до инициализации. Полагаю, это сняло бы одну проверку, я больше ни о чем не думаю.
источник
источник
Я предпочитаю использовать более чистый подход:
val.to_i
вернет,0
если val являетсяnil
,после этого все, что нам нужно сделать, это проверить, равно ли окончательное значение нулю .
источник
Альтернативное решение - использовать уточнения, например:
источник
Я считаю, что следующее достаточно для рубинового кода. Я не думаю, что смогу написать модульный тест, который показал бы разницу между этим и оригиналом.
источник
true
если бы были скидкиnil
.