문제

좋아, 그래서 나는 중복을 제거하고 일반적으로 내 삶을 더 쉽게 만들기 위해 작은 Rails 앱에서 내 코드를 리팩터링해 왔습니다(나는 쉬운 삶을 좋아하기 때문에).이 리팩토링의 일부는 내 모델 중 두 개에 공통된 코드를 필요한 곳에 포함할 수 있는 모듈로 이동하는 것이었습니다.

여태까지는 그런대로 잘됐다.문제가 해결될 것 같지만 어떻게 해결해야 할지 잘 모르겠는 문제가 발생했습니다.(보내기 가능이라고 부르는) 모듈은 문서의 팩스, 이메일 또는 PDF 인쇄를 처리하는 코드일 뿐입니다.예를 들어, 구매 주문서가 있고 내부 판매 주문서(상상적으로 ISO로 축약됨)가 있습니다.

내가 겪은 문제는 개체가 로드된 후 일부 변수를 초기화(철자가 올바르지 않은 사람들을 위해 초기화:P)하고 싶다는 것입니다. 초기화 후 훅.괜찮아요...믹스인을 더 추가하기 전까지는 말이죠.

내가 가진 문제는 내가 after_initialize 내 믹스인 중 하나에 포함해야 하므로 감독자 처음에 전화해서 다른 믹스인이 있는지 확인하세요. after_initialize 전화가 걸려옵니다.훌륭합니다. 결국 super를 호출했는데 호출할 super가 없기 때문에 오류가 발생하기 전까지는 말입니다.

충분히 혼란스럽지 않은 경우를 대비해 작은 예를 들어 보겠습니다.

class Iso < ActiveRecord::Base
  include Shared::TracksSerialNumberExtension
  include Shared::OrderLines
  extend  Shared::Filtered
  include Sendable::Model

  validates_presence_of   :customer
  validates_associated    :lines

  owned_by                :customer
  order_lines             :despatched # Mixin

  tracks_serial_numbers   :items  # Mixin

  sendable :customer                      # Mixin

  attr_accessor :address

  def initialize( params = nil )
    super
    self.created_at ||= Time.now.to_date
  end
end

따라서 각 믹스인에 after_initialize 호출이 있는 경우 감독자 전화해, 마지막으로 어떻게 그만둘 수 있어? 감독자 오류를 제기하여 전화를 걸었나요?슈퍼 메소드를 호출하기 전에 슈퍼 메소드가 존재하는지 어떻게 테스트할 수 있나요?

도움이 되었습니까?

해결책

다음을 사용할 수 있습니다.

super if defined?(super)

예는 다음과 같습니다.

class A
end

class B < A
  def t
    super if defined?(super)
    puts "Hi from B"
  end
end

B.new.t

다른 팁

시도해 보셨나요? alias_method_chain?기본적으로 모든 것을 연결할 수 있습니다. after_initialize 전화.데코레이터처럼 작동합니다.각각의 새로운 메소드는 새로운 기능 계층을 추가하고 제어를 "재정의된" 메소드에 전달하여 나머지 작업을 수행합니다.

포함 클래스(다음에서 상속받는 것) ActiveRecord::Base, 이 경우에는 Iso) ~할 수 있었다 자신의 정의 after_initialize, 그래서 이외의 다른 솔루션은 alias_method_chain (또는 원본을 저장하는 다른 앨리어싱) 코드를 덮어쓸 위험이 있습니다.@Orion Edwards의 솔루션은 제가 생각해 낼 수 있는 최고의 솔루션입니다.다른 것들도 있지만 그들은 그렇습니다 멀리 더 해킹적입니다.

alias_method_chain 또한 after_initialize 메서드의 명명된 버전을 생성할 수 있다는 이점이 있습니다. 즉, 중요한 경우에 호출 순서를 사용자 정의할 수 있다는 의미입니다.그렇지 않으면 포함 클래스에 믹스인이 포함된 순서가 무엇이든 상관없습니다.

나중에:

모든 콜백의 기본 빈 구현 생성에 관한 질문을 ruby-on-rails-core 메일링 리스트에 게시했습니다.저장 프로세스는 어쨌든 그것들을 모두 확인하므로 왜 거기에 있으면 안되는지 모르겠습니다.유일한 단점은 빈 스택 프레임을 추가로 생성한다는 점이지만 알려진 모든 구현에서는 비용이 매우 저렴합니다.

거기에 간단한 조건문을 던질 수 있습니다.

super if respond_to?('super')

그리고 당신은 괜찮을 것입니다 - 쓸모없는 방법을 추가하지 마십시오;좋고 깨끗합니다.

슈퍼 메소드가 존재하는지 확인하는 대신, 그냥 정의하면 됩니다.

class ActiveRecord::Base
    def after_initialize
    end
end

이것은 내 테스트에서 작동하며 기존 코드를 손상시키지 않아야 합니다. 왜냐하면 이를 정의하는 다른 모든 클래스는 어쨌든 자동으로 이 메서드를 재정의하기 때문입니다.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top