<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Pass By Value &#187; patterns</title>
	<atom:link href="http://passbyvalue.com/tag/patterns/feed/" rel="self" type="application/rss+xml" />
	<link>http://passbyvalue.com</link>
	<description>... or is it pass by reference?</description>
	<lastBuildDate>Thu, 26 Jan 2012 03:09:41 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>Dependency injection for Rails</title>
		<link>http://passbyvalue.com/2008/09/dependency-injection-for-rails/</link>
		<comments>http://passbyvalue.com/2008/09/dependency-injection-for-rails/#comments</comments>
		<pubDate>Tue, 23 Sep 2008 02:49:21 +0000</pubDate>
		<dc:creator>Trent</dc:creator>
				<category><![CDATA[Software development]]></category>
		<category><![CDATA[patterns]]></category>
		<category><![CDATA[rails]]></category>
		<category><![CDATA[ruby]]></category>

		<guid isPermaLink="false">http://blog.passbyvalue.com/?p=49</guid>
		<description><![CDATA[I&#8217;d been looking around for how to do Dependency Injection (Inversion of Control) in my Rails App. I don&#8217;t need anything particularly fancy, just the ability for classes (controllers in particular) to have different service implementations injected into them depending on the environment that they&#8217;re in. Something which I take for granted in the Java [...]]]></description>
			<content:encoded><![CDATA[<p>I&#8217;d been looking around for how to do Dependency Injection (Inversion of Control) in my Rails App.  I don&#8217;t need anything particularly fancy, just the ability for classes (controllers in particular) to have different service implementations injected into them depending on the environment that they&#8217;re in.  Something which I take for granted in the Java world with Spring&#8217;s IoC container.</p>
<p>Now I know that Ruby is a vastly different language than Java and that means that somethings that make sense in the Java world (i.e. Dependency Injection) just may not add up at all in the Ruby world.  But I still think that a simple IoC container in my Rails app is required.  It helps with unit/mock testing and in particular, it helps when working in an enterprise environment.</p>
<p>I found what appears to be quite a famous article about DI with Rails using Needle here:</p>
<p><a href="http://www.jamisbuck.org/ruby/rails-injected.html">http://www.jamisbuck.org/ruby/rails-injected.html</a></p>
<p>Although it does appear to be thorough (if a little old now), I still felt that I could get what I needed without as much complexity, so this is what I did in my Rails app&#8230;</p>
<p>I created a simple service locator module that classes include to access services:</p>
<pre>lib/ioc/service_locator.rb</pre>
<pre class="ruby">module IOC
  module ServiceLocator
    def self.included(base)
      base.class_eval do
        extend ClassMethods
        include IOC::ServiceLocator::InstanceMethods
      end
    end

    module ClassMethods
      def has_dependency(*names)
        names.each {|n| class_variable_set("@@#{n}", Registry.instance.get_service(n)) }
      end
    end
  end
end</pre>
<p>A registry for all the services to be cataloged in:</p>
<pre>lib/ioc/registry.rb</pre>
<pre class="ruby">module IOC
  class Registry
    include Singleton

    def initialize
      @registry = {}
    end

    def self.register(name, instance)
      self.instance.register(name, instance)
    end

    def register(name, instance)
      @registry[name] = instance
    end

    def self.register_if_not_defined(name, instance)
      self.instance.register_if_not_defined(name, instance)
    end

    def register_if_not_defined(name, instance)
      register(name, instance) unless has_service(name)
    end

    def self.get_service(name)
      self.instance.get_service(name)
    end

    def get_service(name)
      @registry[name]
    end

    def self.has_service(name)
      self.instance.has_service(name)
    end

    def has_service(name)
      !@registry[name].nil?
    end
  end
end</pre>
<p>Now my controllers can include the ServiceLocator module and nominate dependencies which can then be accessed as class variables, in this case the</p>
<pre>workflow_service</pre>
<pre class="ruby">class WorktrackerController &lt; ApplicationController
  include IOC::ServiceLocator
  has_dependency :workflow_service 

  def wip
    @wip = @@workflow_service.get_work_in_progress
  end
end</pre>
<p>Wiring this up, I add the base registry components at the bottom of:</p>
<pre>config/environment.rb</pre>
<pre class="ruby">...
# Default IOC configuration - overridden by environments
# Each environment needs to call the config.to_prepare first for the
# Dispatcher class to be loaded!
Dispatcher.callbacks[:prepare].insert(0, lambda do
  IOC::Registry.register(:workflow_service, Service::FakeWorkflowService.new)
end)</pre>
<p>The registry&#8217;s entries can then be overridden by the particular environment, ie:</p>
<pre>config/environment/development.rb</pre>
<pre class="ruby">...
config.to_prepare do
    IOC::Registry.register(:workflow_service,
      Service::WebserviceWorkflowService.new('http://tiger:8888/proxy/service/WorkflowInquiry'))
end</pre>
<p>So there you go, its simple and it works.</p>
]]></content:encoded>
			<wfw:commentRss>http://passbyvalue.com/2008/09/dependency-injection-for-rails/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
	</channel>
</rss>

