Module: RSpec::Core::MemoizedHelpers
Relationships & Source Files | |
Namespace Children | |
Modules:
| |
Classes:
| |
Extension / Inclusion / Inheritance Descendants | |
Included In:
| |
Defined in: | rspec-core/lib/rspec/core/memoized_helpers.rb |
Overview
This module is included in ExampleGroup
, making the methods available to be called from within example blocks.
Class Method Summary
- .define_helpers_on(example_group) Internal use only Internal use only
-
.get_constant_or_yield(example_group, name)
Internal use only
Internal use only
Gets the named constant or yields.
-
.module_for(example_group)
Internal use only
Internal use only
Gets the LetDefinitions module.
Instance Attribute Summary
-
#__memoized
readonly
private
Internal use only
Internal use only
should just be placed in private section, but Ruby issues warnings on private attributes.
Instance Method Summary
-
#is_expected
Wraps the #subject in
expect
to make it the target of an expectation. - #should(matcher = nil, message = nil)
-
#should_not(matcher = nil, message = nil)
Just like #should, #should_not delegates to the subject (implicit or explicit) of the example group.
- #subject
- #__init_memoized private Internal use only Internal use only
- #enforce_value_expectation(matcher, method_name) private Internal use only Internal use only
- #initialize private Internal use only Internal use only
- #matcher_supports_value_expectations?(matcher) ⇒ Boolean private
Class Method Details
.define_helpers_on(example_group)
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 542
def self.define_helpers_on(example_group) example_group.__send__(:include, module_for(example_group)) end
.get_constant_or_yield(example_group, name)
Gets the named constant or yields. On 1.9, const_defined? / const_get take into account the the inheritance by default, and accept an argument to disable this behavior. It’s important that we don’t consider inheritance here; each example group level that uses a let
should get its own LetDefinitions
module.
See additional method definition at line 553.
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 570
def self.get_constant_or_yield(example_group, name) if example_group.const_defined?(name) example_group.const_get(name) else yield end end
.module_for(example_group)
Gets the LetDefinitions module. The module is mixed into the example group and is used to hold all let definitions. This is done so that the block passed to let
can be forwarded directly on to define_method
, so that all method constructs (including super
and return
) can be used in a let
block.
The memoization is provided by a method definition on the example group that supers to the LetDefinitions definition in order to get the value to memoize.
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 528
def self.module_for(example_group) get_constant_or_yield(example_group, :LetDefinitions) do mod = Module.new do include(Module.new { example_group.const_set(:NamedSubjectPreventSuper, self) }) end example_group.const_set(:LetDefinitions, mod) mod end end
Instance Attribute Details
#__memoized (readonly, private)
should just be placed in private section, but Ruby issues warnings on private attributes. and expanding it to the equivalent method upsets Rubocop, b/c it should obviously be a reader
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 129
attr_reader :__memoized
Instance Method Details
#__init_memoized (private)
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 141
def __init_memoized @__memoized = if RSpec.configuration.threadsafe? ThreadsafeMemoized.new else NonThreadSafeMemoized.new end end
#enforce_value_expectation(matcher, method_name) (private)
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 150
def enforce_value_expectation(matcher, method_name) return if matcher_supports_value_expectations?(matcher) RSpec.deprecate( "#{method_name} #{RSpec::Support::ObjectFormatter.format(matcher)}", : => "The implicit block expectation syntax is deprecated, you should pass " \ "a block to `expect` to use the provided block expectation matcher " \ "(#{RSpec::Support::ObjectFormatter.format(matcher)}), " \ "or the matcher must implement `supports_value_expectations?`." ) end
#initialize (private)
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 135
def initialize(*) __init_memoized super end
#is_expected
This only works if you are using rspec-expectations.
Wraps the #subject in expect
to make it the target of an expectation. Designed to read nicely for one-liners.
#matcher_supports_value_expectations?(matcher) ⇒ Boolean
(private)
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 163
def matcher_supports_value_expectations?(matcher) matcher.supports_value_expectations? rescue true end
#should(matcher = nil, message = nil)
This only works if you are using rspec-expectations.
If you are using RSpec’s newer expect-based syntax you may want to use is_expected.to
instead of should
.
When should
is called with no explicit receiver, the call is delegated to the object returned by #subject. Combined with an implicit subject this supports very concise expressions.
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 80
def should(matcher=nil, =nil) enforce_value_expectation(matcher, 'should') RSpec::Expectations::PositiveExpectationHandler.handle_matcher(subject, matcher, ) end
#should_not(matcher = nil, message = nil)
This only works if you are using rspec-expectations.
If you are using RSpec’s newer expect-based syntax you may want to use is_expected.to_not
instead of should_not
.
Just like #should, should_not
delegates to the subject (implicit or explicit) of the example group.
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 100
def should_not(matcher=nil, =nil) enforce_value_expectation(matcher, 'should_not') RSpec::Expectations::NegativeExpectationHandler.handle_matcher(subject, matcher, ) end
#subject
subject
was contributed by Joe Ferris to support the one-liner syntax embraced by shoulda matchers:
RSpec.describe Widget do
it { is_expected.to validate_presence_of(:name) }
# or
it { should validate_presence_of(:name) }
end
While the examples below demonstrate how to use subject
explicitly in examples, we recommend that you define a method with an intention revealing name instead.
Because subject
is designed to create state that is reset between each example, and ‘before(:context)` is designed to setup state that is shared across all examples in an example group, subject
is not intended to be used in a before(:context)
hook.
# File 'rspec-core/lib/rspec/core/memoized_helpers.rb', line 57
def subject __memoized.fetch_or_store(:subject) do described = described_class || self.class. .fetch(:description_args).first Class === described ? described.new : described end end