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)
When ‘should` is called with no explicit receiver, the call is delegated to the object returned by #subject.
-
#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