ruby-on-railsrspecrubygemsdsl

Source code for rspec "describe" method (and others)?


I'm sauntering through Michael Hartl's Rails Tutorial right now, and am finding that I'm constantly encouraged to use wonderful methods that inexplicably do amazing things. He does a generally competent job of explaining what they do, but there is no real nitty gritty of why and how they work.

Specifically, I have just been plundering the rspec gem on github searching for the source code to the "describe" method. I cannot find it. Having now read a large amount of the source code (at an apprehension rate of about 25%) searching for it, I know that once found, I will need to look at its parent classes and modules to understand a certain amount of inheritance before I can really grasp (and then never let go of) the flesh and bones of "describe".

I don't mind struggling to grasp the concept, I'm a fan of attempting to read code in new languages before I fully understand it so that I can read it again later and use the comparison of my comprehension as a gauge of my fluency. I'd just like a kicker. Either a description or a file location with maybe a little helper hint to get me started.

For example...

I found this:

  #     RSpec.describe "something" do # << This describe method is defined in
  #                                   # << RSpec::Core::DSL, included in the
  #                                   # << global namespace (optional)

and rpsec/core/dsl states:

# DSL defines methods to group examples, most notably `describe`,
# and exposes them as class methods of {RSpec}. They can also be
# exposed globally (on `main` and instances of `Module`) through
# the {Configuration} option `expose_dsl_globally`.

but then there is no "class Describe" or def "describe" or such in that file.

SO: can anyone tell me where the "describe" method is, how it works, exactly, or (if not) why I am naively searching for the wrong thing in the wrong locations?


Solution

  • As you may know, there is no difference between describe and context methods and you can use them interchangably. Rspec developers could not let themselves to repeat the same code for different method names, so they moved the declaration to

    module RSpec
      module Core
        class ExampleGroup
          def self.define_example_group_method(name, metadata={})
            # here they really define a method with given name using ruby metaprogramming
            define_singleton_method(name) do |*args, &example_group_block|
    

    And call that method a bit later for all the same-functionality DSL methods:

    define_example_group_method :example_group
    define_example_group_method :describe
    define_example_group_method :context
    

    So in case you are looking for describe method source, dive into define_example_group_method with assumption that name argument equals to describe and example_group_block is your block body.