Techioz Blog

クラスまたはモジュールでプライベート メソッドを呼び出さずに送信する

概要

ここで何が間違っているのかわかりません。クラスまたはモジュールを作成して、そのクラス/モジュール内のプライベート メソッドを呼び出すために使用できるようにしようとしています。

次のエラーが発生します: NoMethodError (MixPanelService:Class の未定義メソッド ‘call’)

MixPanelService.call(shop, “install”) を実行しようとすると

私の簡略化したコードは次のとおりです。

class MixPanelService

  def call(shop, event_type)
    send(event_type, shop)
  end

  private

  def install
    ap "do something"
  end

end

そこでモジュールを試してみたところ、次のエラーが発生しました。 NoMethodError (MixPanelService:Module の未定義メソッド「install」)

基本的に同じことを試してみると: MixPanelService.call(ショップ, “インストール”)

次のコードを使用します。

module MixPanelService
  module_function

  def call(shop, event_type)
    send(event_type, shop)
  end

  private

  def install
    ap "do something"
  end

end

私の何が間違っているのでしょうか?

解決策

クラスでは呼び出しをインスタンス メソッドとして定義しましたが、クラス メソッドとして呼び出しています。 def self.call を使用してクラスメソッドにすることができます。

class MixPanelService
  def self.call(shop, event_type)
    send(event_type, shop)
  end

  def self.install(shop)
    # do something
  end
  private_class_method :install # ugly :(
end

# Call it like this:
MixPanelService.call(shop, 'install')

ただし、それは最良のデザインではありません。クラスメソッドを使用して引数を渡すのは面倒です。インスタンスを操作できますが、すべてを実行するためのクラス メソッドもあります。このパターンを見てください。

class MixPanelService
  def self.call(shop, event_type)
    new(shop).call(event_type)
  end

  def initialize(shop)
    @shop = shop
  end

  def call(event_type)
    send(event_type)
  end

  private

  def install
    # Install something on `@shop`. Since it's an instance variable,
    # we don't need to pass it around via params! :)
  end
end

# Call it the same way as before:
MixPanelService.call(shop, 'install')