class CreateArticle attr_reader :validate_article, :persist_article def initialize(validate_article, persist_article) @validate_article = validate_article @persist_article = persist_article end def call(params) result = validate_article.call(params) if result.success? persist_article.call(params) end end end
validate_article
and persist_article
. It explains how dry-container can be used (a simple thread-safe container designed to be used as half the container implementation with inversion control) so that dependencies are available when needed: require "dry-container" # class MyContainer extend Dry::Container::Mixin end # MyContainer.register "validate_article" do ValidateArticle.new end MyContainer.register "persist_article" do PersistArticle.new end MyContainer.register "create_article" do CreateArticle.new( MyContainer["validate_article"], MyContainer["persist_article"], ) end # `CreateArticle` MyContainer["create_article"].("title" => "Hello world")
create_article
.MyApp::Container["create_article"]
, and the object will be fully configured and ready to use. Having a container, you can register objects once and reuse them later.dry-container
supports declaring objects without using a namespace in order to facilitate working with a large number of objects. In real-world applications, the most commonly used namespace is “articles.validate_article” and “persistence.commands.persist_article” instead of simple identifiers, which can be found in the example being described. require "dry-container" require "dry-auto_inject" # class MyContainer extend Dry::Container::Mixin end # MyContainer.register "validate_article", -> { ValidateArticle.new } MyContainer.register "persist_article", -> { PersistArticle.new } MyContainer.register "create_article", -> { CreateArticle.new } # AutoInject AutoInject = Dry::AutoInject(MyContainer) # CreateArticle class CreateArticle include AutoInject["validate_article", "persist_article"] # AutoInject `validate_article` and `persist_article` def call(params) result = validate_article.call(params) if result.success? persist_article.call(params) end end end
CreateArticle.new
method when it is declared. Instead, you can define dependencies directly in the class. A plug-in using AutoInject[*dependencies]
defines the .new
, #initialize
and attr_readers
that “pull” dependencies out of the container, and allow them to be used.dry-component
, a system that has all the necessary dependency management functions and is based on dry-container
and dry-auto_inject
. This system itself controls what is needed to use control inversion between all parts of the application.lib/validate_article.rb
, lib/persist_article.rb
and lib/create_article.rb
. All of them can be included in the container automatically using the special settings in the top-level file my_app.rb
: require "dry-component" require "dry/component/container" class MyApp < Dry::Component::Container configure do |config| config.root = Pathname(__FILE__).realpath.dirname config.auto_register = "lib" end # "lib/" $LOAD_PATH load_paths! "lib" end # MyApp.finalize! # MyApp["validate_article"].("title" => "Hello world")
Articles::ValidateArticle
class in the lib/articles/validate_article.rb
file will be available to the developer in the articles.validate_article
container without the need for any additional actions. This provides a convenient conversion that is similar to the conversion in Ruby on Rails, without any problems with the automatic loading of classes.dry-container
, dry-auto_inject
, and dry-component
is all that is needed to work with small separate components that are easily connected together using dependency injection. Application of these tools simplifies the creation of applications and, even more importantly, facilitates their support, expansion and redesign.Source: https://habr.com/ru/post/301338/
All Articles