module Interjectable::ClassMethods
Constants
- BLANK
- RESTORE_HOOKS
Public Class Methods
test_inject(rspec_example_group, target, dependency, value, &setter)
click to toggle source
# File lib/interjectable/rspec.rb, line 80 def self.test_inject(rspec_example_group, target, dependency, value, &setter) unless value || setter raise ArgumentError, "missing value or setter for #{target}'s #{dependency.inspect}" end unless rspec_example_group < RSpec::Core::ExampleGroup raise "#test_inject can only be called from an RSpec ExampleGroup (e.g.: it, before, after)" end injector = if target.singleton_methods(false).include?(dependency) # inject_static(dependency) on this class InjectStatic.new(target, dependency) elsif target.singleton_methods.include?(dependency) # inject_static(dependency) on a superclass of this class SuperclassInjectStatic.new(target, dependency) elsif target.instance_methods(false).include?(dependency) # inject(dependency) on this class Inject.new(target, dependency) elsif target.instance_methods.include?(dependency) # inject(dependency) on a superclass of this class SuperclassInject.new(target, dependency) else raise ArgumentError, "tried to override a non-existent dependency: #{dependency.inspect}" end injector.override(value, &setter) scope = rspec_example_group.currently_executing_a_context_hook? ? :context : :each key = [target, dependency, scope] # If we already have a restore after(:each) hook for this class + # dependency + scope, don't add another. To check if we already have an # after(:each) hook, we look at all previous after(:each) hooks we've # registered and see if we are currently in a subclass (i.e. we are # nested within) of any of them. # # We don't need to guard against multiple after(:context / :all) hooks # for the same #test_inject call since those before hooks only run once, # and therefore only setup a single after hook. return if scope == :each && RESTORE_HOOKS[key].any? { |group| rspec_example_group <= group } RESTORE_HOOKS[key] << rspec_example_group rspec_example_group.after(scope) do injector.restore end end
Public Instance Methods
inject(dependency, &default_block)
click to toggle source
Defines a helper methods on instances that memoize values per-instance.
Calling a second time is an error. Use `#test_inject` for overriding in RSpec tests. You need to `require “interjectable/rspec”` to use `#test_inject`. See the README.md.
Similar to writing
attr_writer :dependency def dependency @dependency ||= instance_eval(&default_block) end
# File lib/interjectable.rb, line 30 def inject(dependency, &default_block) if instance_methods(false).include?(dependency) raise MethodAlreadyDefined, "#{dependency} is already defined" end attr_writer dependency define_method(dependency) do ivar_name = :"@#{dependency}" if instance_variable_defined?(ivar_name) instance_variable_get(ivar_name) else instance_variable_set(ivar_name, instance_eval(&default_block)) end end end
inject_static(dependency, &default_block)
click to toggle source
Defines helper methods on instances that memoize values per-class. (shared across all instances of a class, including instances of subclasses).
Calling a second time is an error. Use `#test_inject` for overriding in RSpec tests. You need to `require “interjectable/rspec”` to use `#test_inject`. See the README.md.
Similar to writing
cattr_writer :dependency def dependency @@dependency ||= instance_eval(&default_block) end
# File lib/interjectable.rb, line 62 def inject_static(dependency, &default_block) if instance_methods(false).include?(dependency) || methods(false).include?(dependency) raise MethodAlreadyDefined, "#{dependency} is already defined" end cvar_name = :"@@#{dependency}" setter = :"#{dependency}=" define_method(setter) do |value| self.class.send(setter, value) end define_singleton_method(setter) do |value| class_variable_set(cvar_name, value) end define_method(dependency) do self.class.send(dependency) end define_singleton_method(dependency) do if class_variable_defined?(cvar_name) class_variable_get(cvar_name) else class_variable_set(cvar_name, instance_eval(&default_block)) end end end
test_inject(dependency, &setter)
click to toggle source
# File lib/interjectable/rspec.rb, line 71 def test_inject(dependency, &setter) unless setter raise ArgumentError, "missing setter #{dependency.inspect}, correct usage: #test_inject(#{dependency.inspect}) { FakeDependency.new }" end rspec_example_group = setter.binding.receiver.class ClassMethods.test_inject(rspec_example_group, self, dependency, BLANK, &setter) end