dry-system-rails Join the chat at https://dry-rb.zulipchat.com

Gem Version Build Status Code Climate Test Coverage Inline docs

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'
end

The 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::Container
  • MyApp::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']
end

Working 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
end

TODO

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.