def let_context(*args, &block)
      context_string, hash =
        case args.map(&:class)
        when [String, Hash] then ["#{args[0]} #{args[1]}", args[1]]
        when [Hash] then [args[0].inspect, args[0]]
        end

      context(context_string) do
        hash.each { |var, value| let(var) { value } }

        instance_eval(&block)
      end
    end
def let_context(*args, &block)
      context_string, hash =
        case args.map(&:class)
        when [String, Hash] then ["#{args[0]} #{args[1]}", args[1]]
        when [Hash] then [args[0].inspect, args[0]]
        end

      context(context_string) do
        hash.each { |var, value| let(var) { value } }

        instance_eval(&block)
      end
    end
This allows us to simplify the case where we want to
 have a context which contains one or more `let` statements

 Supports giving either a Hash or a String and a Hash as arguments
 In both cases the Hash will be used to define `let` statements
 When a String is specified that becomes the context description
 If String isn't specified, Hash#inspect becomes the context description

 @example Defining a simple let variable
   # Before
   subject { a + 1 }
   context('a is 1') do
     let(:a) { 1 }
     it { should eq 2 }
   end

   # After
   subject { a + 1 }
   let_context(a: 1) { it { should eq 2 } }

 @example Giving a descriptive string
   subject { a + 1 }
   let_context('Negative number', a: -1) { it { should eq 0 } }

 @example Multiple variables
   subject { a + b }
   let_context(a: 1, b: 2) { it { should eq 3 } }