2010-03-23 27 views
43

Vì vậy, tôi biết làm thế nào để ghi đè lên thu khí mặc định cho các thuộc tính của một đối tượng sử dụng ActiveRecordray ghi đè getter mặc định cho một mối quan hệ (belongs_to)

def custom_getter 
    return self[:custom_getter] || some_default_value 
end 

Tôi đang cố gắng để đạt được điều tương tự tuy nhiên đối với một thuộc liên kết. Ví dụ.

class Foo < AR 
    belongs_to :bar 

    def bar 
    return self[:bar] || Bar.last 
    end 
end 

class Bar < AR 
    has_one :foo 
end 

Khi tôi nói:

f = Foo.last 

Tôi muốn có phương pháp f.bar trả lại Bar cuối cùng, chứ không phải là con số không nếu hiệp hội không tồn tại được nêu ra.

Điều này không hoạt động. Lý do là bản thân [: bar] luôn không xác định. Nó thực sự là bản thân [: bar_id].

tôi có thể làm điều gì đó ngây thơ như:

def bar 
    if self[:bar_id] 
    return Bar.find(self[:bar_id]) 
    else 
    return Bar.last 
    end 
end 

Tuy nhiên điều này sẽ luôn thực hiện cuộc gọi db, ngay cả khi Bar đã được lấy, mà chắc chắn không phải là lý tưởng.

Có ai có thông tin chi tiết về cách tôi có thể có mối quan hệ sao cho thuộc tính depends_to chỉ được tải một lần và có giá trị mặc định nếu không được đặt.

Trả lời

70

alias_method là bạn của bạn ở đây.

alias_method :original_bar, :bar 
def bar 
    self.original_bar || Bar.last 
end 

Cách này hoạt động là bạn đặt bí danh "thanh" mặc định là "thanh gốc" và sau đó triển khai phiên bản "thanh" của riêng bạn. Nếu lệnh gọi hàm original_bar trả về nil thì bạn trả lại cá thể Bar cuối cùng.

+0

Bạn không có một vòng lặp với điều đó? bởi vì thanh cuộc gọi trong thanh? – shingara

+0

Không, bạn gọi "original_bar" là tên mới của "bar". –

+0

hoạt động như một sự quyến rũ! Cảm ơn rất nhiều – brad

10

Randy của câu trả lời là tại chỗ trên, nhưng có một cách dễ dàng hơn để viết nó, sử dụng alias_method_chain:


def bar_with_default_find 
    self.bar_without_default_find || Bar.last 
end 
alias_method_chain :bar, :default_find 

Điều đó tạo ra hai phương pháp - bar_with_default_findbar_without_default_find và bí danh bar với phương pháp with. Bằng cách đó bạn có thể gọi một cách rõ ràng hoặc cái khác, hoặc chỉ để mặc định như vậy.

+0

Giải pháp mát mẻ vì bạn có thể sử dụng '_without_default_find' để có khái niệm về phương thức xác nhận gốc. Là người duy nhất tôi có thể làm việc. Cảm ơn – grant

13

tôi phát hiện ra rằng sử dụng "siêu" là cách tốt nhất

def bar 
    super || Bar.last 
end 

Tôi hy vọng điều này sẽ giúp bạn: D

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