How to extend and override attributes from other class from same module?

86 Views Asked by At

While working with graphql in Rails, I am using this to define the arguments of a mutation/update that I want to perform on a Product record. So far, this is the file that I use to define the arguments:

 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

The point is, I want to define all of them required when creating the product, but not all of them required when updating the model. So I wanted to create two different classes in two different files, to make them required or not, for example

To create a product I want all of them required:

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

But when updating, I want only one of the attributes as required, while all the rest should be false:

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

I was hoping that I could have the first ProductInputType as the default behavior where all of them have required as false, and then create those new classes (CreateProductInputType and UpdateProductInputType) by just extending that ProductInputType and overriding only the arguments that I want to have its behavior changed, like this:

    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

However, it does not work like this. How could I manage to extend the ProductInputType into those classes and override the arguments, knowing that they are all into the same module?

1

There are 1 best solutions below

0
Imam On

One way is to use ActiveSupport::Concern to define the common attributes and include them in the InputType classes.

This way you can add new attributes inside input type classes or override the common attributes as well.

Example:


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