Module: Interjectable::ClassMethods
- Defined in:
- lib/interjectable.rb,
lib/interjectable/rspec.rb
Constant Summary collapse
- BLANK =
Object.new
Class Method Summary collapse
Instance Method Summary collapse
-
#inject(dependency, &default_block) ⇒ Object
Defines a helper methods on instances that memoize values per-instance.
-
#inject_static(dependency, &default_block) ⇒ Object
Defines helper methods on instances that memoize values per-class.
- #test_inject(dependency, &setter) ⇒ Object
Class Method Details
.test_inject(rspec_example_group, target, dependency, value, &setter) ⇒ Object
80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 |
# 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 |
Instance Method Details
#inject(dependency, &default_block) ⇒ Object
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
30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 |
# 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) ⇒ Object
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
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 |
# 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) ⇒ Object
71 72 73 74 75 76 77 78 |
# 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 |