2012-09-12 17 views
1

如何为Ruby中的实例的属性定义方法?将方法添加到Ruby中的属性

假设我们有一个名为HtmlSnippet的类,它扩展了ActiveRecord :: Base of Rails,并且有一个属性content。而且,我想为它定义一个方法replace_url_to_anchor_tag!,并按以下方式调用它:

html_snippet = HtmlSnippet.find(1) 
html_snippet.content = "Link to http://stackoverflow.com" 
html_snippet.content.replace_url_to_anchor_tag! 
# => "Link to <a href='http://stackoverflow.com'>http://stackoverflow.com</a>" 



# app/models/html_snippet.rb 
class HtmlSnippet < ActiveRecord::Base  
    # I expected this bit to do what I want but not 
    class << @content 
    def replace_url_to_anchor_tag! 
     matching = self.match(/(https?:\/\/[\S]+)/) 
     "<a href='#{matching[0]}'/>#{matching[0]}</a>" 
    end 
    end 
end 

由于content是String类的一个实例,所以重新定义String类是一个选项。但我不喜欢这样做,因为它覆盖了所有String实例的行为;

class HtmlSnippet < ActiveRecord::Base  
    class String 
    def replace_url_to_anchor_tag! 
     ... 
    end 
    end 
end 

有什么建议吗?

+0

单身是你想要的。 – oldergod

+0

哎呀,我总是说评论谢谢你,但不是在Stackoverflow中的任何操作。我会这样做 – suzukimilanpaak

+0

@oldergod你能给我一个样本吗? – suzukimilanpaak

回答

0

你的代码不工作的原因很简单 - 你正在使用@content,它在执行的上下文中是nilself是类,而不是实例)。所以你基本上修改了nil的特征类。

因此,您需要在设置时扩展@content的实例。有几种方法,有一个:

class HtmlSnippet < ActiveRecord::Base 

    # getter is overrided to extend behaviour of freshly loaded values 
    def content 
    value = read_attribute(:content) 
    decorate_it(value) unless value.respond_to?(:replace_url_to_anchor_tag) 
    value 
    end 

    def content=(value) 
    dup_value = value.dup 
    decorate_it(dup_value) 
    write_attribute(:content, dup_value) 
    end 

    private 
    def decorate_it(value) 
    class << value 
     def replace_url_to_anchor_tag 
     # ... 
     end 
    end 
    end 
end 

为了简单起见,我中省略了“零方案” - 你应该进行不同的处理nil值。但这很简单。

另一件事是你可能会问是为什么我在设置中使用dup。如果代码中没有dup,下面的代码的行为可能是错误的(显然这取决于您的要求):

x = "something" 
s = HtmlSnippet.find(1) 
s.content = x 

s.content.replace_url_to_anchor_tag # that's ok 
x.content.replace_url_to_anchor_tag # that's not ok 

Wihtout dup要扩展不仅x.content而且原来的字符串,你已分配。

+0

哇,这太美了!我看到我如何访问类中的实例属性。 – suzukimilanpaak

+0

非常感谢。这工作完美! – suzukimilanpaak