Posts Tagged ‘ruby’

Making your Rails app work on Java

September 26th, 2009

So you’ve written a Rails app and you want to show it off to your boss at work because you know that it will impress them. Problem is that your company only uses Java and won’t consider it for their production environment if it can’t be deployed under a JVM. Let’s go:

  1. Install JRuby http://jruby.org
  2. Install the required gems for Ruby on Rails to work with JRuby
  3. jgem install mongrel activerecord-jdbcsqlite3-adapter rails
  4. Install the gems particular to your application
  5. jruby -S rake gems:install
  6. Update your database.xml file, prefixing your adapter with jdbc
  7. development:
      adapter: jdbcsqlite3
      database: db/development.sqlite3
      pool: 5
      timeout: 5000
  8. Start your JVM
  9. jruby script/server
  10. Demonstrate
  11. Sit back and wait for promotion

Some notes on whats going on above:

Getting Ruby to talk to Oracle with Cygwin

January 7th, 2009

I need to be able to use Ruby to talk to Oracle databases to help us easily build scripts for maintenance and support. So, I started doing some googling and found ruby-oci8. Excellent!

I’m also mainly PC bound so I needed to get this working on my cygwin installation. My entire Ruby environment is running through cygwin.

So I started through the installation instructions on the ruby-oci8 site but started to find it pretty confusing to follow for the cygwin-specific installation. Finally, after a bit of trial and error, here are the steps I followed to get this baby humming:

  1. Download and unzip the Oracle Instant Client Basic and SDK packages. I successfully did this with version 11.1.0.7.0. The path I chose was:
    C:\oracle\instantclient_11_1
  2. Add the instant client to the front of your system path (through Control Panel –> System)
  3. Launch cygwin
  4. Install the gem
    $ gem install ruby-oci8
    Building native extensions.  This could take a while...
    Successfully installed ruby-oci8-1.0.3
    1 gem installed
    Installing ri documentation for ruby-oci8-1.0.3...
    Installing RDoc documentation for ruby-oci8-1.0.3...

That’s it! You’re now all installed! You’ll notice that the gem compiles some native extensions, this is why you need the instant client to be available in your path.

Now to give it a test run, open up and irb session and give it a go:

irb(main):001:0> require 'oci8'
=> true
irb(main):002:0> conn = OCI8.new('username', 'password', '//server:port/sid')
=> #<OCI8:0x7fdb3d44 @privilege=nil, @prefetch_rows=nil, @ctx=[0, #<Mutex:0x7fdb3cf4>, nil, 65535], @svc=#<ocisvcctx:0x7fdb3ce0>>

We have a connection!

SSL setup for Ruby

December 18th, 2008

I found recently that I wanted to get SSL enabled when making HTTP connections with Ruby. However, if you’re wishing to talk to servers that have certificates signed by commercial certificate authorities then you won’t be able to verify them when you make a connection:

require 'net/http'
require 'net/https'
http = Net::HTTP.new('www.google.com', 443)
http.use_ssl = true
http.get('/mail')
"warning: peer certificate won't be verified in this SSL session"
=<#net::httpfound 302="" found="" readbody="true">

Notice line 6? Not good as its really important to be able to verify SSL certificates on the web to make sure that you’re talking to who you think you’re talking to!

So to verify these certificates, download commercial certificate authorities used by Mozilla (Firefox) that have been kindly pre-packaged for you:

http://curl.haxx.se/docs/caextract.html

Store in a logical location:

/usr/share/ssl/cert.pem

Now, test out that they are working, try this code (IRB works well!):

require 'net/http'
require 'net/https'
http = Net::HTTP.new('www.google.com', 443)
http.ca_file = '/usr/share/ssl/cacert.pem'
http.use_ssl = true
http.get('/mail')
=<#net::httpfound 302="" found="" readbody="true">

Yah! No more warnings, we’re properly verify the server’s SSL certificate!

Tip: If you’re behind a proxy, then you’ll need to change the third step to be:

http = Net::HTTP::Proxy('myproxyserver', 8080).new('www.google.com', 443)

The above code creates a HTTP class with your proxy configuration baked in. Then you can create an instance from it, just like a regulard HTTP class!

Dependency injection for Rails

September 23rd, 2008

I’d been looking around for how to do Dependency Injection (Inversion of Control) in my Rails App. I don’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’re in. Something which I take for granted in the Java world with Spring’s IoC container.

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.

I found what appears to be quite a famous article about DI with Rails using Needle here:

http://www.jamisbuck.org/ruby/rails-injected.html

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…

I created a simple service locator module that classes include to access services:

lib/ioc/service_locator.rb
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

A registry for all the services to be cataloged in:

lib/ioc/registry.rb
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

Now my controllers can include the ServiceLocator module and nominate dependencies which can then be accessed as class variables, in this case the

workflow_service
class WorktrackerController < ApplicationController
  include IOC::ServiceLocator
  has_dependency :workflow_service 

  def wip
    @wip = @@workflow_service.get_work_in_progress
  end
end

Wiring this up, I add the base registry components at the bottom of:

config/environment.rb
...
# 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)

The registry’s entries can then be overridden by the particular environment, ie:

config/environment/development.rb
...
config.to_prepare do
    IOC::Registry.register(:workflow_service,
      Service::WebserviceWorkflowService.new('http://tiger:8888/proxy/service/WorkflowInquiry'))
end

So there you go, its simple and it works.