런타임 시 Ruby 인스턴스 메서드 재정의

또는 큰 힘에는 큰 책임이 따른다



나는 이전에 2018년에 다른 사이트에 이것을 게시했지만 Ruby에서 작업하는 사람들에게 여전히 도움이 된다고 생각합니다.

요약 - Ruby에서 각 개체는 클래스이고 클래스는 개체입니다. 한 개체의 메서드를 재정의하고 해당 클래스의 다른 개체 인스턴스에 영향을 주지 않을 수 있습니다.

작업



어느 시점에서 우리는 데이터 모델을 위반한 테스트 개체를 시스템에 로드했습니다. 약간의 실험으로 대체 방법을 통해 로드를 수행했습니다.

이 개체는 완고하여 기본적인 파괴 시도를 거부했습니다.

나는 우리 머신에 껍질을 벗기고 루비 콘솔을 로드하고 다음을 실행했습니다.

rails $ gf = GenericFile.find('my-id')
rails $ gf.destroy
=> NoMethodError: undefined method 'representative' for nil:NilClass



나는 코드를 모르고 평소처럼 시도했습니다 : gf.representative = nil . 작동하지 않았습니다. 대표자는 식별자의 별칭인 것으로 밝혀졌습니다. 그래서 유효성 검사 논리를 살펴보았습니다.

def check_and_clear_parent_representative
  if batch.representative == self.pid
    batch.representative = batch.generic_file_ids
                 .select {|i| i if i != self.pid}.first
    batch.save!
  end
end



이것에 너무 많은 노력을 기울이고 싶지 않았기 때문에 저는 Ruby의 개발자 무기 중 하나를 꺼냈습니다.

def gf.check_and_clear_parent_representative; true; end



그런 다음 gf.destroy "펑!"객체가 유효성 검사를 통과했고 폐기되었습니다.

설명



Ruby의 모든 개체에 대해 인스턴스 메서드를 별도로 재정의할 수 있습니다. (예. def my_instance.the_method ) 이는 각 Ruby 객체에 자체 싱글톤 클래스가 있기 때문입니다. 본질적으로 개체 클래스의 복사본입니다.

위의 예에서 def gf.check_and_clear_parent_representative; true; end 를 작성할 때 이전에 찾은 특정check_and_clear_parent_representative 개체에 대한 GenericFile 메서드를 다시 작성하고 있었습니다. 과거나 미래의 다른 어떤 객체GenericFile도 그러한 변화를 겪지 않을 것입니다.

저는 이 도구를 많이 사용하지 않습니다. 사실 일회성 솔루션의 맥락에서만 사용하는 것이 좋습니다. 이것은 다른 개발자를 혼란스럽게 할 수 있으며 invalidate the method cache . 전자의 경우 애플리케이션의 인지 밀도를 높이고 있습니다. 후자의 경우 성능이 저하됩니다.

그러나 때로는 임의의 장벽을 통과하기 위해 위험한 도구를 가져와야 합니다. 그러나 그 결과를 아십시오.

좋은 웹페이지 즐겨찾기