15

我应该使用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宏可以透明地提供这种行为。是这样吗?

4

3 回答 3

26

注意:x ||= y 如果 x 返回 false,则分配 x = y。这可能意味着 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

如果您只需要初始化变量。

于 2009-06-08T08:28:25.947 回答
1

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
于 2009-06-09T01:49:59.383 回答
0

此外,更好的版本||=会产生关于未初始化实例变量的警告(至少在 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始终在该点定义。

于 2009-06-08T15:21:09.793 回答