Module Remarkable::DSL::Assertions::ClassMethods
In: lib/remarkable/dsl/assertions.rb


Protected Instance methods

It sets the arguments your matcher receives on initialization.


  • :collection - if a collection is expected.
  • :as - how each item of the collection will be available.
  • :block - tell the matcher can receive blocks as argument and store
                      them under the variable given.

Note: the expected block cannot have arity 1. This is already reserved for macro configuration.


Let‘s see for each example how the arguments declarion reflects on the matcher API:

  arguments :assign
  # Can be called as:
  #=> should_assign :task
  #=> should_assign :task, :with =>

This is roughly the same as:

  def initialize(assign, options = {})
    @assign   = name
    @options = options

As you noticed, a matcher can always receive options on initialization. If you have a matcher that accepts only options, for example, have_default_scope you just need to call arguments:

  # Can be called as:
  #=> should_have_default_scope :limit => 10

  arguments :collection => :assigns, :as => :assign
  # Can be called as:
  #=> should_assign :task1, :task2
  #=> should_assign :task1, :task2, :with =>

  arguments :collection => :assigns, :as => :assign, :block => :buildeer
  # Can be called as:
  #=> should_assign :task1, :task2
  #=> should_assign(:task1, :task2){ }

The block will be available under the instance variable @builder.


All the parameters given to arguments are available for interpolation in I18n. So if you have the following declarion:

  class InRange < Remarkable::Base
    arguments :range, :collection => :names, :as => :name

You will have {{range}}, {{names}} and {{name}} available for I18n messages:

    description: "have {{names}} to be on range {{range}}"

Before a collection is sent to I18n, it‘s transformed to a sentence. So if the following matcher:

  in_range(2..20, :username, :password)

Has the following description:

  "should have username and password in range 2..20"


     # File lib/remarkable/dsl/assertions.rb, line 119
119:           def arguments(*names)
120:             options = names.extract_options!
121:             args = names.dup
123:             @matcher_arguments[:names] = names
125:             if collection = options.delete(:collection)
126:               @matcher_arguments[:collection] = collection
128:               if options[:as]
129:                 @matcher_arguments[:as] = options.delete(:as)
130:               else
131:                 raise ArgumentError, 'You gave me :collection as option but have not give me :as as well'
132:               end
134:               args          << "*#{collection}"
135:               get_options    = "#{collection}.extract_options!"
136:               set_collection = "@#{collection} = #{collection}"
137:             else
138:               args          << 'options={}'
139:               get_options    = 'options'
140:               set_collection = ''
141:             end
143:             if block = options.delete(:block)
144:               block = :block unless block.is_a?(Symbol)
145:               @matcher_arguments[:block] = block
146:             end
148:             # Blocks are always appended. If they have arity 1, they are used for

149:             # macro configuration, otherwise, they are stored in the :block variable.

150:             #

151:             args << "&block"
153:             assignments = do |name|
154:               "@#{name} = #{name}"
155:             end.join("\n  ")
157:             class_eval "def initialize(\#{args.join(',')})\n_builder, block = block, nil if block && block.arity == 1\n\#{assignments}\n\#{\"@\#{block} = block\" if block}\n@options = default_options.merge(\#{get_options})\n\#{set_collection}\nrun_after_initialize_callbacks\ if _builder\nend\n", __FILE__, __LINE__
158:           end
assertion(*methods, &block)

Alias for assertions

Declares the assertions that are run once per matcher.


A matcher that checks if an element is included in an array can be done just with:

  class IncludedMatcher < Remarkable::Base
    arguments :value
    assertion :is_included?

      def is_included?

Whenever the matcher is called, the :is_included? action is automatically triggered. Each assertion must return true or false. In case it‘s false it will seach for an expectation message on the I18n file. In this case, the error message would be on:

    description: "check {{value}} is included in the array"
      is_included: "{{value}} is included in the array"

In case of failure, it will output:

  "Expected {{value}} is included in the array"

Notice that on the yml file the question mark is removed for readability.

Shortcut declaration

You can shortcut declaration by giving a name and block to assertion method:

  class IncludedMatcher < Remarkable::Base
    arguments :value

    assertion :is_included? do


     # File lib/remarkable/dsl/assertions.rb, line 243
243:           def assertions(*methods, &block)
244:             if block_given?
245:               define_method methods.last, &block
246:               protected methods.last
247:             end
249:             @matcher_single_assertions += methods
250:           end
collection_assertion(*methods, &block)

Declare the assertions that are runned for each element in the collection. It must be used with arguments methods in order to work properly.


The example given in assertions can be transformed to accept a collection just doing:

  class IncludedMatcher < Remarkable::Base
    arguments :collection => :values, :as => :value
    collection_assertion :is_included?

      def is_included?

All further consideration done in assertions are also valid here.


     # File lib/remarkable/dsl/assertions.rb, line 191
191:           def collection_assertions(*methods, &block)
192:             define_method methods.last, &block if block_given?
193:             @matcher_collection_assertions += methods
194:           end

Class method that accepts a block or a hash to set matcher‘s default options. It‘s called on matcher initialization and stores the default value in the @options instance variable.


  default_options do
    { :name => }

  default_options :message => :invalid


     # File lib/remarkable/dsl/assertions.rb, line 265
265:           def default_options(hash = {}, &block)
266:             if block_given?
267:               define_method :default_options, &block
268:             else
269:               class_eval "def default_options; #{hash.inspect}; end"
270:             end
271:           end