Skip to content
Mathieu Derelle edited this page Jan 5, 2023 · 14 revisions

Commands only take hashes as input, but those hashes can contain a variety of things: strings, numbers, other hashes, arrays, and other objects.

For instance, given this definition of inputs:

class DoImportantStuff < Mutations::Command
  required do
    string :name, min_length: 5
    model :user
  end

  optional do
    integer :amount
  end

  def execute
    # do important work with self.inputs
  end
end

This input hash would be valid:

{name: "Bobby", user: User.find(params[:id]), amount: 9}

Note that the input hash can contain extra fields -- they're just filtered out.

The following is the current set of filters available to you.

StringFilter

Allows values to be strings. By default, nil and blank strings aren't permitted, and strings are stripped of leading and trailing whitespace. Additionally, various non-strings (like numbers) are converted to strings. Example:

string :email, min_length: 5

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options
  • empty: [true/false]. Default: false. false disallows "". true allows "" and overrides other validations (because they couldn't be valid if the value is empty)
  • strict: [true/false]. Default: false. If false, then symbols, numbers, and booleans are converted to a string with to_s. true means an explicit string must be passed.
  • strip: [true/false]. Default: true. true calls data.strip (removing leading/trailing whitespace).
  • min_length: [nil or number]. Default: nil. Can be a number like 5, meaning that at least 5 codepoints are required
  • max_length: [nil or number]. Default: nil. Can be a number like 10, meaning that at most 10 codepoints are permitted
  • matches: [nil or Regexp]. Default: nil. Input must match given regexp.
  • in: [nil or array]. Default: nil. Can be an array like %w(red blue green), meaning only those values are permitted.
  • allow_control_characters: [true/false]. Default: false. false removes unprintable characters from the string

BooleanFilter

Allows values to be booleans. Also converts strings like "1", "0", "true", and "false" to their corresponding boolean value. Example:

boolean :is_enabled

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options

IntegerFilter

Allows values to be Fixnums. Converts strings to Fixnums via .to_i if the string starts with a digit (negatives are handled). Example:

integer :amount, max: 100

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options
  • min: [nil or integer]. Default: nil. Can be an like 8, meaning 8 (inclusive) is the lowest allowed value.
  • max: [nil or integer]. Default: nil. Can be an like 12, meaning 12 (inclusive) is the highest allowed value.

ModelFilter

Allows you to specify that values need to be instances of a certain class, such as a User model. These models can be ActiveRecord models, or any other Ruby object you may have. By default, the field name is camelized and constantized to get the class. So the key 'user' implies the class is User. Example:

model :account
model :created_by, class: User
model :created_by, class: 'User'
model :email_address, builder: EmailAddressBuilder

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options
  • class: [nil or class constant or string]. Default: attribute_name.to_s.camelize.constantize. You can override that by passing in a class contsant or a string that will be constantized.
  • new_records: [true/false]. Default: false. If false, unsaved ActiveRecord objects are not valid. Things that don't respond to new_record? are valid. true: anything is valid
  • builder: [nil or class constant or string]. Default: nil. If present, and a hash is passed, then we use that to construct a model. The builder is another Mutations::Command that accepts a hash and returns an object of the appropriate class.

HashFilter

Allows your inputs to contain nested hashes. Those hashes themselves can have required and optional fields. Hashes are always converted to a hash with indifferent access for you.

Example:

# Simple hash with two booleans inside. Both nested booleans are required.
hash :email_permissions do
  boolean :newsletter
  boolean :daily_digests
end

hash :comment_attributes do
  required do
    string :title
    string :body
  end

  optional do
    boolean :subscribe
  end
end

hash :key_value_pairs do
  string :* # Allows any key to pass through. Useful for dynamic key / value objects
end

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options

ArrayFilter

Allows arrays to be passed. You can specify a class for each element, or you can pass a block and filter each element with a filter defined in this document. Example:

# Must be an array. Array can contain anything.
array :list_of_things

# Array of strings:
array :names, class: String

# Array of integers:
array :ids do
  integer
end

# Array of hashes (attributes for comments):
array :comments do
  hash do
    required do
      string :body
      string :title
    end
    
    optional do
       integer :id
       boolean :_destroy
    end
  end
end

Options:

  • nils: [true/false]. Default: false. true allows an explicit nil to be valid. Overrides any other options
  • class: [nil or constant or string]. Default: nil. Indicates that each element of the array needs to be one of these classes
  • arrayize: [true/false]. Default: false. true will convert non-arrays into arrays. For instance, "hi" will be converted to ["hi"] and "" will be converted to [].
  • min_length: [nil or number]. Default: nil. Can be a number like 5, meaning that at least 5 objects are required
  • max_length: [nil or number]. Default: nil. Can be a number like 10, meaning that at most 10 objects are permitted

Others

FileFilter and others can be seen here: https://github.com/cypriss/mutations/tree/master/lib/mutations