2009-06-08 22 views
14

Tôi có nên sử dụng if defined?Trong Ruby, tôi nên sử dụng || = hoặc nếu được xác định? để ghi nhớ?

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

Hoặc ||=

@current_user_session ||= UserSession.find 

tôi nhận thấy phương pháp if defined? đang được sử dụng nhiều hơn và gần đây hơn. Có lợi thế nào so với cái kia không? Cá nhân tôi thích ||= để dễ đọc. Tôi cũng nghĩ Rails có thể có macro memoize cung cấp hành vi này một cách minh bạch. Đây có phải là trường hợp không?

+0

Nó được gọi là memoize – nasmorn

Trả lời

24

Hãy cẩn thận: x || = y gán x = y nếu x trả về false. Điều đó có thể có nghĩa là x là không xác định, nil hoặc false.

Có nhiều biến số sẽ được xác định và sai, mặc dù có thể không nằm trong ngữ cảnh của biến thể hiện @current_user_session.

Nếu bạn mong muốn conciseness, hãy thử các cấu trúc điều kiện:

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

hoặc chỉ:

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

nếu bạn chỉ cần khởi tạo biến.

+1

Bạn có nghĩa là 'định nghĩa (@ current_user_session) hoặc @current_user_session = UserSession? .find' ('hoặc' thay vì '||')? – Jimothy

0

Ngoài ra, đẹp hơn ||= sẽ tạo cảnh báo (ít nhất 1.8.6 và 1.8.7) về các biến mẫu chưa được khởi tạo, trong khi phiên bản defined? dài hơn không.

Mặt khác, điều này có lẽ những gì bạn muốn:

def initialize 
    @foo = nil 
end 

def foo 
    @foo ||= some_long_calculation_for_a_foo 
end 

Nhưng điều này gần như chắc chắn không:

def initialize 
    @foo = nil 
end 

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

từ @foo sẽ luôn được xác định tại thời điểm đó.

+0

toàn bộ điểm được xác định? là kiểm tra các biến cá thể chưa được khởi tạo. – Sam

+0

Ngoài ra, được xác định? (: @ Foo) ALWAYS trả về "biểu thức". Bạn đã định nghĩa? (@ Foo). được xác định? (@ foo) trả về giá trị nil hoặc "instance-variable". –

+0

cảm ơn bạn đã nắm bắt, Sporkmonger. Typo hiện đã được sửa. –

1

Rails không có memoization, hãy kiểm tra screencast dưới đây để giới thiệu lớn:

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

Tuy nhiên, KHÔNG sử dụng bản ghi nhớ của Rails nếu bất kỳ tham số nào của bạn là Hashes trừ khi bạn đang sử dụng Ruby 1.9. –

+5

'ActiveSupport :: Memoizable' không được chấp nhận trong Rails 3.2. –

+0

@BobAman Tôi đang sử dụng Ruby 1.9 nhưng tôi vẫn gặp sự cố khi sử dụng tính năng ghi nhớ với thông số băm. Tôi cũng đang trên đường ray 3.0 – sjobe

Các vấn đề liên quan