I'd definitely advocate a low-touch DI approach as per Andrew's suggestion.
Stephen Best gave a talk on this subject at LRUG a few years ago and it had
a big impact on me.

Here's the talk:

https://skillsmatter.com/skillscasts/4437-improve-your-code-with-dependency-injection

And here's the accompanying blog post, which is a bit too short and doesn't
explain all of the good ideas from the talk:

http://theaudaciouscodeexperiment.com/articles/ruby-dependency-injection.html

My approach, stolen from Bestie, is to mainly just pass in collaborators
into constructors. Here's a simple example to get something from an API:

```
class Widget
end

class WidgetFetcher
  def initialize(http_client:)
    @http_client = http_client
  end

  def call(id)
    url = "https://myapi.com/#{id}.json";
    @http_client.get(url)
  end
end

widget_fetcher = WidgetFetcher.new(http_client: HTTParty)

widget_attrs = widget_fetcher.call(11)

widget = Widget.new(widget_attrs)
```

It would be tempting to give Widget the ability to pull itself from the
API, but by separating these concerns and limiting the scope of Widget,
it's way easier to test. No more mocking out the whole internet using
WebMock, you can just inject a double into WidgetFetcher#new http_client.

I also follow the pattern of having the main action of a
fetcher/builder/whatever class as *#call* - because lambdas respond to
this, you can inject those too. You can even inject methods - consider this
instead:

```
class Widget
end

class WidgetFetcher
  def initialize(http_client:)
    @http_client = http_client
  end

  def call(id)
    url = "https://myapi.com/#{id}.json";
    @http_client.call(url)
  end
end

widget_fetcher = WidgetFetcher.new(http_client: HTTParty.method(:get))

widget_attrs = widget_fetcher.call(11)

widget = Widget.new(widget_attrs)
```

Here, we simply pass a method into WidgetFetcher#new that promises it can
run a get on an API endpoint. Now `http_client` can be tested by simply
injecting a lambda, a function, or a double that responds to call. Easy and
you're not polluting your app with ConstantReferences all over the shop -
you can keep them all in one or two places.

That said, I will check out the dry-rb talk as it would be great to have a
standardised, lightweight approach for this stuff...

Cheers,

Sam



On 14 July 2016 at 13:40, Andrew Premdas <[email protected]> wrote:

> Jamis Buck famously wrote a couple of di frameworks for ruby which became
> sorta popular, then realised that with ruby it was completely unnecessary.
> This blog post whilst quite long and old gives some interesting insite into
> DI, Ruby and moving from Java to Ruby (
> http://weblog.jamisbuck.org/2008/11/9/legos-play-doh-and-programming).
>
> So you can do DI in ruby easily without frameworks or gems
>
> I don't know if dry-rb is repeating Jamis's mistakes or doing something
> elegant and useful with DI. I suspect that its DI parts are useful in its
> context of tying together a number of small components which together
> produce a framework. Whether they are appropriate for use outside that
> context is another matter.
>
> Personally I think its best to start small with things like this and get
> some depth to ones understanding before making a big commitment to a
> framework or gems.
>
>
>
> On 12 July 2016 at 13:02, David Craddock <[email protected]>
> wrote:
>
>> We are getting to the stage on the product I'm working on, that it might
>> be useful to use Dependency Injection.
>> https://en.wikipedia.org/wiki/Inversion_of_control
>>
>> What do you fellow Rubyists think about using DI in Ruby? Are there any
>> frameworks or gems that can help this?
>>
>> --
>> You received this message because you are subscribed to the Google Groups
>> "North West Ruby User Group (NWRUG)" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send an email to [email protected].
>> Visit this group at https://groups.google.com/group/nwrug-members.
>> For more options, visit https://groups.google.com/d/optout.
>>
>
>
>
> --
> ------------------------
> Andrew Premdas
> blog.andrew.premdas.org
>
> --
> You received this message because you are subscribed to the Google Groups
> "North West Ruby User Group (NWRUG)" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
>
> Visit this group at https://groups.google.com/group/nwrug-members.
> For more options, visit https://groups.google.com/d/optout.
>

-- 
You received this message because you are subscribed to the Google Groups 
"North West Ruby User Group (NWRUG)" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send an email to [email protected].
Visit this group at https://groups.google.com/group/nwrug-members.
For more options, visit https://groups.google.com/d/optout.

Reply via email to