
Research
Security News
The Growing Risk of Malicious Browser Extensions
Socket researchers uncover how browser extensions in trusted stores are used to hijack sessions, redirect traffic, and manipulate user behavior.
Dependency Injection For The Win! A small, yet surprisingly powerful, dependency injection library for Ruby.
If your only concern is testing, mocks/stubs and webmock
might be all you need. But if you're working on a large project that hooks into all kinds of enterprisey services, and those services aren't always available in dev/testing/staging, a dash of DI might be just the thing.
# Create your root injector/container
DI = DiFtw::Injector.new do
singleton :foo do
OpenStruct.new(message: "Everyone will get this same object")
end
factory :bar do
OpenStruct.new(message: "Everyone will get a NEW version of this object")
end
# inject dependencies into your dependency
factory :foobar, [:foo, :bar] do
OpenStruct.new(message: foo.message + bar.message)
end
end
# Or register things out here
DI.singleton :zorp do
OpenStruct.new(message: "Bar")
end
class Widget
include DI.inject :foo, :bar
end
widget = Widget.new
# foo isn't actually injected until it's first called
puts widget.foo.message
=> "Foo"
Lazy injection is usually fine. But if it isn't, use inject!
:
class Widget
include DI.inject :foo, :bar
def initialize
inject!
end
end
# foo and bar are immediately injected
widget = Widget.new
# Inject :baz into all Widget instance objects
class Widget
include DI.inject :baz
end
puts Widget.new.baz.message
=> 'Baz'
# Inject :baz into one specific instance
x = SomeClass.new
DI.inject_instance x, :baz
puts x.baz.message
=> 'Baz'
# Inject :baz as a class method
class SomeClass
extend DI.inject :baz
end
puts SomeClass.baz.message
=> 'Baz'
# Inject :baz as a module method
module SomeModule
extend DI.inject :baz
end
puts SomeModule.baz.message
=> 'Baz'
This is maybe the coolest part. Each time you call inject
(or inject_instance
) you're creating a fresh, empty child DiFtw::Injector
. It will recursively look up dependencies through the parent chain until it finds the nearest registration of that dependency.
This means you can re-register a dependency on a child injector, and it will be injected instead of whatever is registered above it in the chain.
# Create your root injector and register :foo
DI = DiFtw::Injector.new
DI.singleton(:foo) { 'Foo' }
class Widget
include DI.inject :foo
end
class Spline
include DI.inject :foo
end
# Widget and Spline each get a new injector instance
Widget.injector.object_id != DI.object_id
=> true
Widget.injector.object_id != Spline.injector.object_id
=> true
# Each Widget instance gets a new injector instance. Same for Spline.
w1 = Widget.new
w1.injector.object_id != Widget.injector.object_id
=> true
w2 = Widget.new
w1.injector.object_id != w2.injector.object_id
=> true
# But all those child injectors are empty. They'll all resolve :foo
# to whatever is in DI[:foo]
Widget.new.foo
=> 'Foo'
Spline.new.foo
=> 'Foo'
Widget.new.foo.object_id == Spline.new.foo.object_id
=> true
# But we could re-register/override :foo in Spline.injector, and all new
# Spline instances would resolve :foo differently.
Spline.injector.singleton(:foo) { 'Bar' }
Spline.new.foo
=> 'Bar'
# But DI and Widget.injector would be unchanged
Widget.new.foo
=> 'Foo'
# We can go even further and override :foo in just one specific instance of Spline
# NOTE This only works if you're using lazy injection (the default) AND if you haven't called #foo yet
s = Spline.new
s.injector.singleton(:foo) { 'Baz' }
s.foo
=> 'Baz'
# Other Spline instances will still get their override from Spline.injector
Spline.new.foo
=> 'Bar'
# While Widget instances will all still get the original value from DI
Widget.new.foo
=> 'Foo'
To inject different dependencies in these environments, you have several options. You can simply re-register dependencies in your root injector:
DI.singleton(:foo) { OpenStruct.new(message: 'Test Foo') }
And/Or you can use the parent-child injector features described above to great effect:
before :each do
# Give all MyService instances 'Test foo' as #foo
MyService.injector.singleton(:foo) {
'Test foo'
}
end
after :each do
# Remove the override & fallback to whatever was registered in the root injector
MyService.injector.delete :foo
end
FAQs
Unknown package
We found that diftw demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket researchers uncover how browser extensions in trusted stores are used to hijack sessions, redirect traffic, and manipulate user behavior.
Research
Security News
An in-depth analysis of credential stealers, crypto drainers, cryptojackers, and clipboard hijackers abusing open source package registries to compromise Web3 development environments.
Security News
pnpm 10.12.1 introduces a global virtual store for faster installs and new options for managing dependencies with version catalogs.