Skip to content

Instantly share code, notes, and snippets.

@timriley
Created November 3, 2016 09:15
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save timriley/d314a58da9784912159006e208ba8ea9 to your computer and use it in GitHub Desktop.
Save timriley/d314a58da9784912159006e208ba8ea9 to your computer and use it in GitHub Desktop.
dry-auto_inject strategy for Trailblazer 2 operations
require "bundler/setup"
require "dry-auto_inject"
module Cerealblazer
class InjectStrategy < Module
ClassMethods = Class.new(Module)
attr_reader :container
attr_reader :dependency_map
attr_reader :class_mod
def initialize(container, *dependency_names)
@container = container
@dependency_map = Dry::AutoInject::DependencyMap.new(*dependency_names)
@class_mod = ClassMethods.new
end
def included(klass)
define_call
klass.singleton_class.prepend @class_mod
super
end
private
def define_call
class_mod.class_exec(container, dependency_map) do |container, dependency_map|
define_method :call do |params, options = {}, *dependencies|
options_with_deps = dependency_map.to_h.each_with_object({}) { |(name, identifier), obj|
obj[name] = options[name] || container[identifier]
}.merge(options)
super(params, options_with_deps, *dependencies)
end
end
end
end
def self.AutoInject(container)
Dry::AutoInject(container, strategies: {default: Cerealblazer::InjectStrategy})
end
class Operation
def self.call(params, options = {}, *dependencies)
puts "#{name} called"
puts "params: #{params.inspect}"
puts "options: #{options.inspect}"
puts "dependencies: #{dependencies.inspect}"
puts
end
end
end
module MyApp
Container = {
"foo" => "this is foo",
"bar" => "this is bar",
}
Inject = Cerealblazer::AutoInject(Container)
class MyOperation < Cerealblazer::Operation
include MyApp::Inject["foo"]
end
end
# Calling the operation and accepting the auto-injected dependency
MyApp::MyOperation.({"page" => "1"})
# =>
# MyApp::MyOperation called
# params: {"page"=>"1"}
# options: {:foo=>"this is foo"}
# dependencies: []
# Calling the operation and supplying a replacement for the auto-injected dependency
MyApp::MyOperation.({"page" => "1"}, foo: "my foo")
# =>
# MyApp::MyOperation called
# params: {"page"=>"1"}
# options: {:foo=>"my foo"}
# dependencies: []
# Calling the operation and supplying other dependencies not covered by the auto-injection
MyApp::MyOperation.({"page" => "1"}, baz: "my baz")
# =>
# MyApp::MyOperation called
# params: {"page"=>"1"}
# options: {:foo=>"this is foo", :baz=>"my baz"}
# dependencies: []
source "https://rubygems.org"
gem "dry-auto_inject"
GEM
remote: https://rubygems.org/
specs:
concurrent-ruby (1.0.2)
dry-auto_inject (0.4.2)
dry-container (>= 0.3.4)
dry-configurable (0.3.0)
concurrent-ruby (~> 1.0)
dry-container (0.5.0)
concurrent-ruby (~> 1.0)
dry-configurable (~> 0.1, >= 0.1.3)
PLATFORMS
ruby
DEPENDENCIES
dry-auto_inject
BUNDLED WITH
1.13.2
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment