• Home

  • Custom Ecommerce
  • Application Development
  • Database Consulting
  • Cloud Hosting
  • Systems Integration
  • Legacy Business Systems
  • Security & Compliance
  • GIS

  • Expertise

  • About Us
  • Our Team
  • Clients
  • Blog
  • Careers

  • VisionPort

  • Contact
  • Our Blog

    Ongoing observations by End Point Dev people

    Simple Example of Dependency Injection with Rails

    Brian Buchalter

    By Brian Buchalter
    June 25, 2012

    Today I came across a great opportunity to illustrate dependency injection in a simple context. I had a Rails partial that was duplicated across two subclasses. The partial was responsible for displaying options to create a new record from the data of the current record. It also offered two types of copy, shallow and deep. The shallow copy used a button to POST data, while the deep copy offered a form with some additional options. The only difference between the partials was the path to post data to. Let’s see this in code.

    button_to(t("create_and_edit_shallow_copy"), fun_event_path(:from_event => @event.id, :return => true), :    id => "shallow_copy_btn")
    form_tag(fun_event_path(:return => true)) do
      #form code
    button_to(t("create_and_edit_shallow_copy"), boring_event_path(:from_event => @event.id, :return => true), :    id => "shallow_copy_btn")
    form_tag(boring_event_path(:return => true)) do
      #form code

    The first, failed iteration

    To remove the duplication, I passed in a path option into the partial, replacing specific references with the generic.

    <%= render :partial => "events/copy_options", :event_path => fun_event_path %>
    <%= render :partial => "events/copy_options, :event_path => boring_event_path %>
    button_to(t("create_and_edit_shallow_copy"), event_path(:from_event => @event.id, :return => true), :    id => "shallow_copy_btn")
    form_tag(event_path(:return => true)) do
      #form code

    Can you guess where this led?

    undefined method `event_path' for ActionView::Base:0xd6acf18

    Dude! Inject the dependency!

    Obviously the event_path variable I was passing was a string, not a method. I needed the method so I could pass in the appropriate arguments to construct the URL I needed. Had there not been two different calls to the routes, I would likely have just passed in the string needed in each context. But in this case, I was forced to think outside the box. Here’s what I ended up with.

    <%= render :partial => "events/copy_options", :event_path => method(:fun_event_path) %>
    <%= render :partial => "events/copy_options, :event_path => method(:boring_event_path) %>
    button_to(t("create_and_edit_shallow_copy"), event_path.call(:from_event => @event.id, :return => true), :    id => "shallow_copy_btn")
    form_tag(event_path.call(:return => true)) do
      #form code

    The changes are really quite subtle, but we use Object’s method method to pass the reference to the method we want to call, and simply pass in the arguments when needed. Mind == Blown