Railtie for dry-system (つ◕౪◕)つ━☆゚.*・。゚
Installation
Add it to your Gemfile:
gem 'dry-system-rails'
Usage
To configure auto-registration create config/initializers/system.rb with the following content:
Dry::System::Rails.container do
# you can set it to whatever you want and add as many dirs you want
config.auto_register << 'lib'
endThe Dry::System::Rails::Railtie creates a container and injector on your behalf at runtime and assign them to two constants Container and Import
under your applications root module. E.g. if your application is named MyApp, the Railtie will add the following constants:
MyApp::ContainerMyApp::Import
Now you can use MyApp::Import to inject components into your objects and framework components:
# lib/user_repo.rb
class UserRepo
end
# lib/create_user.rb
class CreateUser
include MyApp::Import['user_repo']
end
# app/controllers/users_controller.rb
class UsersController < ApplicationController
include MyApp::Import['create_user']
endWorking with Framework Dependencies
The Rails API is designed around the usage of class methods. If you choose to write domain logic in objects you will likely encounter a situation where your code will have to use one of the framework components. That is where manual registration using bootable dependency will come in handy.
E.g. You have an object CreateWidget that needs to process widgets asynchronously with an Widgets:NotificationJob but you want to leverage dependency injection to decouple the components:
# config/initializers/system.rb
Dry::System::Rails.container do
# changes `self` to the container
config.auto_register << 'lib'
end
# app/jobs/widgets/notification_job.rb
class Widgets::NotificationJob < ApplicationJob
end
# config/system/boot/application.rb
# Use bootable componets to manually register framework dependencies
MyApp::Container.boot(:application) do |app|
setup do
app.namespace(:widgets) do |widgets|
widgets.register(:notification, memoize: true) { Widgets::NotificationJob }
end
end
end
# lib/create_widget.rb
class CreateWidget
include MyApp::Import[job: 'widgets.notification']
def call(args)
# some logic that creates a widget command
job.perform_later(create_widget_command)
end
endTODO
This is super alpha and it's missing a couple of things:
- Some generators to make UX nicer
- Tests for loading scripts (console etc)
- Tests for running rake tasks
License
See LICENSE file.