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.
