В Ruby следует использовать || = или если определено? для воспоминаний?
Должен ли я использовать 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
, который обеспечивает это поведение прозрачно. Это тот случай?
Ответы
Ответ 1
Будьте осторожны: x || = y присваивает x = y, если x возвращает false. Это может означать, что x - undefined, 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
если вам просто нужно инициализировать переменную.
Ответ 2
У Rails есть memoization, посмотрите скринкаст ниже для отличного введения:
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
Ответ 3
Кроме того, более приятный ||=
выдает предупреждение (по крайней мере на 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
всегда будет определяться в этой точке.