2012-09-12 3 views
1

Ruby에서 인스턴스 속성에 대한 메소드를 어떻게 정의합니까?Ruby에서 속성에 메소드 추가하기

우리는 ActiveRecord :: Base of Rails를 확장하고 content 속성을 가지고있는 HtmlSnippet이라는 클래스가 있다고 가정 해 봅시다. 그리고, 나는 그것에 대해 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 

은 String 클래스의 인스턴스이므로, String 클래스를 재정의하는 것이 하나의 옵션입니다. 하지만 모든 String 인스턴스의 동작을 덮어 쓰므로 감당할 생각이 없습니다.

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

제안 사항을 알려주십시오.

+0

싱글 톤이 원하는 것입니다. – oldergod

+0

oops, 나는 항상 코멘트에 의해 당신을 감사하지만 Stackoverflow에서 어떤 작업에 의해. 나는이 시간에 그것을 할 것입니다 – suzukimilanpaak

+0

@oldergod 당신이 샘플을 줄 수 있습니까? – suzukimilanpaak

답변

0

코드가 작동하지 않는 이유는 간단합니다. 실행 컨텍스트에서 nil 인 @content로 작업하고 있습니다 (self은 인스턴스가 아니라 클래스 임). 그래서 기본적으로 nil의 eigenclass를 수정하고 있습니다.

그래서 @content가 설정되면 인스턴스를 확장해야합니다. 몇 가지 방법이 있습니다, 하나가 : 나는 "전무 시나리오를"ommited 한 간단하게하기 위해서

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

관련 문제