Simple attempt to inject dependencies through method decorators (https://github.com/michaelfairley/method_decorators) or meta programming.
Add this line to your application's Gemfile:
gem 'service_provider'
And then execute:
$ bundle
Or install it yourself as:
$ gem install service_provider
Service provider comes with an automatic service provider, which registers every provided service under its name. You can specify your own service provider (see below).
The class that provides a dependency has to extend the ServiceProvider
module and to decorate its initialize method with the Provides
decorator:
class SquareService
extend ServiceProvider
+Provides
def initialize
end
end
The (suggested) name of the service provided defaults to the underscored class name, and can also be given as a parameter: +Provides.new(:square_service)
. The standard service provider used will use this name as the name of the service. Custom service providers (see below) might not make use of this information.
The class that requires a service has to extend the MethodDecorators
module and to decorate its initialize method with the Requires
decorator. The argument passed into the Requires
decorator will be the name of the getter that will return that service.
class SquareSample
extend MethodDecorators
+Requires.new(:square_service)
def initialize
end
def do_work(num)
square_service.square(num)
end
end
You can also use the require_service method to inject a service. You will have to use this method if your instances are not created with a call to Class.new, but with a call to Class.allocate. This is the case for all instances of ActiveRecord::Base that are returned from a find call. See here for some information about that
class SquareSample
require_service(:square_service)
def do_work(num)
square_service.square(num)
end
end
After a service has been required it can be manually set on the object, through a setter for the instance variable, i.e. square_service=
.
You might want to specify how services are provided when you have multiple classes that implement the same service or when you want to change the implementations completely, i.e. for tests. To do so, provide your own service provider and register it with ServiceProvider
:
class CustomServiceProvider
def provide(service_class, service_class_provided_service_name)
#how to store services
end
def get_service(service_name)
#how to retrieve services by name
end
end
ServiceProvider.provider_implementation = CustomServiceProvider.new
- Each class has to have an empty constructor to put the MethodDecorators before it.
- Provider has to extend the ServiceProvider, Requirer has to extend MethodDecorators
- Fork it
- Create your feature branch (
git checkout -b my-new-feature
) - Commit your changes (
git commit -am 'Added some feature'
) - Push to the branch (
git push origin my-new-feature
) - Create new Pull Request
Copyright (c) Johannes Tuchscherer
Released under the MIT license. See LICENSE file for details.