Перевірити, якщо не нуль і не порожній у ярлику Rails?


76

У мене є сторінка шоу для моїх Користувачів, і кожен атрибут повинен бути видимим на цій сторінці, лише якщо це не нуль і не порожній рядок. Нижче у мене є свій контролер, і це дуже дратує, коли потрібно писати однаковий рядок коду @user.city != nil && @user.city != ""для кожної змінної. Я не надто обізнаний у створенні власних методів, але чи можу я якось створити ярлик, щоб зробити щось подібне @city = check_attr(@user.city):? Або є кращий спосіб скоротити цю процедуру?

users_controller.rb

def show 
  @city = @user.city != nil && @user.city != ""
  @state = @user.state != nil && @user.state != ""
  @bio = @user.bio != nil && @user.bio != ""
  @contact = @user.contact != nil && @user.contact != ""
  @twitter = @user.twitter != nil && @user.twitter != ""
  @mail = @user.mail != nil && @user.mail != ""
end

Відповіді:


197

Існує метод, який робить це за вас:

def show
  @city = @user.city.present?
end

Тест present?методу на не- nilплюс має зміст. Порожні рядки, рядки, що складаються з пробілів або вкладок, вважаються відсутніми.

Оскільки цей шаблон настільки поширений, у ActiveRecord є навіть ярлик:

def show
  @city = @user.city?
end

Це приблизно рівнозначно.

Як зауважимо, тестування проти nilмайже завжди зайве. У Ruby є лише два логічно хибних значення: nilі false. Якщо можливо, що змінна не є буквальною false, цього буде достатньо:

if (variable)
  # ...
end

Це краще, ніж звичайне if (!variable.nil?)або if (variable != nil)речі, які з’являються зрідка. Рубі схильна до підопічних до більш редукціоністського типу виразу.

Однією з причин, з якою ви хочете порівняти, nilє те, що у вас є змінна три стану, яка може бути true, falseабо nilвам потрібно розрізняти два останні стани.


11
Зверніть увагу, що станом на Ruby 2.3.0 ви можете позбутися багатьох зайвих перевірок на нуль за допомогою самотнього оператора, щось подібне if @user && @user.authenticatedможе просто статиif @user&.authenticated

1
Ще одна причина , ви хочете зробити if object.present?більш if object, якщо ви пізніше обернути об'єкт декоратора, то результат зміниться , якщо не використовується .present?. philihp.com/2018/prefer-if-object-present-over-if-object.html
Philihp Busby

12

Ви можете використовувати .present? який постачається в комплекті з ActiveSupport.

@city = @user.city.present?
# etc ...

Можна навіть написати так

def show
  %w(city state bio contact twitter mail).each do |attr|
    instance_variable_set "@#{attr}", @user[attr].present?
  end
end

Варто зазначити, що якщо ви хочете перевірити, чи щось пусте, ви можете використовувати .blank?(це протилежне .present?)

Також не використовуйте foo == nil. Використовуйте foo.nil?замість цього.


@Mayank, OP встановлює для змінної екземпляра значення true/ falsevalue. reciever.present?поверне true, якщо receiverзначення не є порожнім. Будь ласка, перегляньте документи, на які я зв’язав, для подальшого пояснення.
Дякую,

дякую, я зрозумів вашу думку, але я не можу зрозуміти, як instance_variable_set "@ # {attr}", @user [attr] .present? буду працювати..?
нео-код

@Mayank, instance_variable_set("@foo", "bar")це те саме, що @foo = "bar". Це просто програмний спосіб встановлення змінних екземплярів ^^
Дякую

okz спасибі зараз я зрозумів ... але ще одне, що javascript: atob ("bmFreW90b0BnbWFpbC5jb20 ="); засоби ?
нео-код

Mayank, запустіть його в консолі javascript, щоб дізнатись!
Дякую
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.