2015-06-04 23 views
6

Tôi muốn ghi đè hành vi của phương pháp update_attributes trên một ví dụ đơn của một lớp mô hình. Giả sử biến được gọi là @alert cách tốt nhất để thực hiện điều này là gì? Để rõ ràng, tôi không muốn sửa đổi hành vi của phương pháp này cho toàn bộ lớp học.Phương pháp vá khỉ trên một đối tượng


SỰ TỪ BỎ:

tôi cần phải làm điều này để buộc phương pháp để trở về false khi tôi muốn nó để tôi có thể viết các unit test cho xử lý mã sau lỗi. Tôi hiểu nó có thể không phải là thực hành tốt nhất.

+1

Tôi sắp sửa sử dụng thuật ngữ "vá khỉ" - nghĩ rằng nó chỉ áp dụng cho sửa đổi các phương pháp tích hợp sẵn của Ruby - nhưng sau khi googling nó xuất hiện không có sự đồng thuận về ý nghĩa của nó. Xem, ví dụ, [câu hỏi SO này] (http://stackoverflow.com/questions/394144/what-does-monkey-patching-exactly-mean-in-ruby). –

+0

@CarySwoveland Trong lịch sử "vá tiền" đề cập đến dậm các phương pháp hiện có với việc triển khai của riêng bạn, nơi chúng chiếm toàn bộ. Trong trường hợp này, nó hoạt động nhiều hơn "mô hình", nơi nó chỉ thay đổi một đối tượng duy nhất, và các đối tượng khác, cả hiện tại và những đối tượng được tạo ra trong tương lai, đều không bị ảnh hưởng. – tadman

+0

Điều này có mùi giống như một phương pháp, mà bất kỳ khuôn khổ kiểm tra phong nha sẽ phù hợp. – zetetic

Trả lời

7

Chỉ cần xác định một phương pháp trên đối tượng:

class Thing 
    def greeting 
    'yo, man' 
    end 
end 

Thing.instance_methods(false) 
    #=> [:greeting] 

object = Thing.new 
    #=> #<Thing:0x007fc4ba276c90> 

object.greeting 
    #=> "yo, man" 

Xác định hai phương thức trên object (đây sẽ là các phương thức thể hiện trong lớp đơn của object.

def object.greeting 
    'hey, dude' 
end 

def object.farewell 
    'see ya' 
end 

object.methods(false) 
    #=> [:greeting, :farewell] 
object.singleton_class.instance_methods(false) #=> [:greeting, :farewell] 

object.greeting 
    #=> "hey, dude" 
object.farewell 
    #=> "see ya" 

new_obj = Thing.new 
new_obj.greeting 
    #=> "yo, man" 
new_obj.farewell 
    #NoMethodError: undefined method `farewell' for #<Thing:0x007fe5a406f590> 

Xóa phương thức singleton 'greeting.

object.singleton_class.send(:remove_method, :greeting) 

object.methods(false) 
    #=> [:farewell] 
object.greeting 
    #=> "yo, man" 

Một cách khác để xóa :greeting từ lớp đơn của object như sau.

class << object 
    remove_method(:greeting) 
end 
+1

Đôi khi điều này được thực hiện rõ ràng hơn bằng cách tạo mô-đun và trộn vào đối tượng riêng lẻ. – tadman

+0

Typo: 'Thing.new hi' nên là 'Thing.new.hi'. Ngoại lệ sau đó sẽ là 'NoMethodError: phương thức không xác định \ 'hi' cho # ' thay vì 'NameError: ...' – nitsas

+0

@nitsas, cảm ơn bạn. –

2

Sau khi tạo một đối tượng, gọi là "define_method" vào nó:

object = Thing.new 
object.define_method("update_attributes") { return false } 

Đó done, object.update_attributes bây giờ sẽ trở false

+0

Đối tượng kế thừa từ 'ActiveRecord :: Base' và tôi nhận được một' NoMethodError' cố gắng gọi 'define_method' trên nó. Bất kỳ ý tưởng? Nó có thể là hiển nhiên nhưng tôi tương đối mới với sự tinh tế của Ruby on Rails. – steve

+0

'define_method' chỉ được định nghĩa trên' Mô-đun', nhưng 'đối tượng' không phải là một' Mô-đun', đó là một 'Điều'. –

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