Forwardable과 ActiveSupport::Delegate를 혼용하지 마십시오.

4959 단어
며칠 전 disposable gem 마이너 라인 0.6.0을 출시했습니다. 목표는 remove unnecessary coupling을 이전 uber gem으로 만드는 것이었습니다. 이전에는 모든 Trailblazer gem에 필요한 추상화 세트를 보유하도록 계획되었습니다.

내가 주로 작업한 것은 Uber::Delegate 을 제거하고 Ruby의 내장 Forwardable 으로 대체하는 것이었습니다. 한 개체에서 다른 개체로 여러 메서드를 위임하기만 하면 됩니다. Forwardable이 그렇게 합니다.



따라서 새 코드가 기본적으로 수행한 작업은 Disposable::Twin 클래스를 확장하고 def_delegators을 사용하여 자동 위임을 만드는 것입니다.

class Disposable::Twin
  extend Forwardable # this used to be Uber::Delegate

  def_delegators :model, :title, :title=
  def_delegators :model, :email, :email=


분명히 gem 종속성을 제거하는 것은 자신의 것일지라도 기분이 좋기 때문에 두 프로젝트에서 테스트를 실행한 후 이 새로운 gem을 밀고 값비싼 사무실 책상에 기대었습니다.

또 다른 대표가 온다!



하루 후 여러 사용자로부터 bug reports을 받았습니다. 그들 모두는 Reform개의 양식 개체를 사용하고 있었고 문제는 앱에 있는 Reform::Form개의 클래스에서 발생했습니다.

ArgumentError:
   wrong number of arguments (given 2, expected 1)
 # ruby/3.0.0/forwardable.rb:133:in `instance_delegate'


개발자들은 Disposable 0.6.0 으로 업그레이드하기 전에 다음과 같은 코드가 제대로 작동했다고 보고했습니다.

class CreateForm < Reform::Form
  delegate :assignment, to: :model
end


업그레이드 후에는 위에 설명된 ArgumentError과 함께 중단됩니다. 첫 번째 의심은 Ruby 3에서 실행되는 이전 코드에서 이러한 종류의 예외가 종종 관찰되기 때문에 이것이 Ruby 3에 대해 준비되지 않은 일부 코드라는 것입니다.

위임 또는 위임?



몇 시간 동안 Forwardable code을 살펴보고 좋은 사용자가 제공한 깨진 예제 앱을 사용해도 아무런 진전이 없었습니다.

어느 시점에서 나는 사용자가 위임을 만들기 위해 실제로 사용하고 있는 것이 delegate 이 아니라 ForwardableActiveSupport::Delegate 메서드라는 것을 깨달았습니다. docs enlightened me 이 모듈은 #delegate 메서드를 오류를 보고하는 모든 사용자가 사용한 메서드인 클래스에 혼합합니다.

주문이 중요합니다!



돌이켜보면 정말 바보 같았고 문제를 이해하는 데 최소 2시간이 걸렸습니다.

다음은 문제를 해결하는 일련의 스파크입니다.
  • Reform::Form 클래스는 Twin::Disposable 에서 상속됩니다. 이는 각 Form 클래스에 Forwardable 메서드가 혼합되어 있음을 의미합니다. 물론 disposable 을 0.6.0으로 업그레이드한 후에만 ForwardableTwin 에 자동으로 포함했습니다.
  • 0.6.0 이전에는 Uber::Delegate의 이전 대표단이 #delegates(s을 염두에 두십시오)이라는 한 가지 방법만 혼합했습니다.
  • Forwardable 모듈에는 #delegate이라는 메소드가 포함되어 있습니다.
  • 우리의 불쾌한 ActiveSupport::Delegate 모듈에는 #delegate이라는 메서드도 있습니다. Forwardable과 같습니다!
  • 일부 Rails 앱에서 ActiveSupport의 위임이 자동으로 모든 클래스에 포함됩니다.

  • 우리가 직면한 문제는 ActiveSupport와 그 위임 코드가 Reform::Form gem이 disposable을 포함하기 전에 Forwardable 클래스에 자동으로 포함되어 예상했던 #delegate 메서드를 재정의한다는 것입니다.

    즉, Forwardable은 ActiveSupport의 #delegate 메서드가 로드되고 나중에 포함됨에 따라 중단되었습니다.

    문제 해결됨



    지금은 removed Forwardable from disposable 으로 결정하고 모호한 문제를 수정했습니다. 양식에서 delegate을 사용할 때 이제 ActiveSupport의 구현을 참조합니다.

    좋은 웹페이지 즐겨찾기