В Ruby я должен использовать || = или, если определен? для запоминания? - PullRequest
14 голосов
/ 08 июня 2009

Должен ли я использовать if defined?

 return @current_user_session if defined?(@current_user_session)
 @current_user_session = UserSession.find

Или ||=

@current_user_session ||= UserSession.find

Я заметил, что метод if defined? используется все чаще и чаще. Есть ли преимущество одного над другим? Лично я предпочитаю ||= для удобства чтения. Я также думаю, что в Rails может быть макрос memoize, который обеспечивает прозрачное поведение. Это тот случай?

Ответы [ 3 ]

25 голосов
/ 08 июня 2009

Будьте осторожны: x || = y назначает x = y, если x возвращает false. Это может означать, что x не определено, равно nil или false.

Много раз переменные будут определены и ложны, хотя, возможно, не в контексте переменной экземпляра @current_user_session.

Если вы хотите краткости, попробуйте условную конструкцию:

defined?(@current_user_session) ?
    @current_user_session : @current_user_session = UserSession.find

или просто:

defined?(@current_user_session) || @current_user_session = UserSession.find

если вам просто нужно инициализировать переменную.

1 голос
/ 09 июня 2009

В Rails есть памятка, посмотрите скриншот ниже, чтобы узнать больше

http://railscasts.com/episodes/137-memoization

class Product < ActiveRecord::Base
  extend ActiveSupport::Memoizable

  belongs_to :category

  def filesize(num = 1)
    # some expensive operation
    sleep 2
    12345789 * num
  end

  memoize :filesize
end
0 голосов
/ 08 июня 2009

Кроме того, более приятное ||= выдает предупреждение (по крайней мере, на 1.8.6 и 1.8.7) о неинициализированных переменных экземпляра, в то время как более подробная версия defined? не делает.

С другой стороны, это, вероятно, делает то, что вы хотите:

def initialize
  @foo = nil
end

def foo
  @foo ||= some_long_calculation_for_a_foo
end

Но это почти наверняка не так:

def initialize
  @foo = nil
end

def foo
  return @foo if defined?(@foo)
  @foo = some_long_calculation_for_a_foo
end

, поскольку @foo будет всегда определяться в этой точке.

...