Techioz Blog

同じモジュールの他のクラスの属性を拡張およびオーバーライドするにはどうすればよいですか?

概要

Rails でgraphql を使用しているときに、これを使用して、Product レコードに対して実行する突然変異/更新の引数を定義しています。これまでのところ、引数の定義に使用しているファイルは次のとおりです。

 module Types
  module Input
    class ProductInputType < Types::BaseInputObject
      argument :name,           String, required: false
      argument :description,    String, required: false
      argument :initial_price,  Float, required: false
    end
  end
end

重要なのは、製品の作成時に必要なすべてを定義したいのですが、モデルを更新するときにすべてが必要になるわけではないということです。そこで、2 つの異なるファイルに 2 つの異なるクラスを作成して、それらを必須にするかどうかを決めたいと思いました。

製品を作成するには、次のすべてが必要です。

module Types
  module Input
    class CreateProductInputType
      argument :name,           String, required: true
      argument :description,    String, required: true
      argument :initial_price,  Float, required: true
    end
  end
end

ただし、更新するときは、必須の属性を 1 つだけ必要とし、残りはすべて false にする必要があります。

 module Types
  module Input
    class UpdateProductInputType
      argument :name,           String, required: true
    end
  end
end

最初の ProductInputType をすべて false として要求するデフォルトの動作として設定し、その ProductInputType を拡張して必要な引数のみをオーバーライドするだけで、これらの新しいクラス (CreateProductInputType と UpdateProductInputType) を作成できることを期待していました。次のように動作が変更されました。

    module Types
      module Input
        class CreateProductInputType < ProductInputType
          argument :name,           String, required: true
          argument :initial_price,  Float, required: true
        end
      end
    end

    module Types
      module Input
        class UpdateProductInputType < ProductInputType
          argument :name,           String, required: true
        end
      end
    end

しかし、このままではうまくいきません。これらがすべて同じモジュール内にあることを認識しながら、ProductInputType をこれらのクラスに拡張し、引数をオーバーライドするにはどうすればよいでしょうか?

解決策

1 つの方法は、ActiveSupport::Concern を使用して共通の属性を定義し、それらを InputType クラスに含めることです。

このようにして、入力型クラス内に新しい属性を追加したり、共通の属性をオーバーライドしたりすることもできます。

例:


module Types
  module Input
    module ProductInputAttributes
      extend ActiveSupport::Concern

      included do
        argument :name,           String, required: false
        argument :description,    String, required: false
        argument :initial_price,  Float, required: false
      end
    end
  end
end

module Types
  module Input
    class CreateProductInputType
      include ProductInputAttributes

      argument :name, String, required: true
    end
  end
end

module Types
  module Input
    class UpdateProductInputType
      include ProductInputAttributes

      argument :id, ID, required: true
      argument :name, String, required: true
    end
  end
end