[rspec-devel] [ rspec-Bugs-10577 ] Rails with Oracle breaks 0.9.2

noreply at rubyforge.org noreply at rubyforge.org
Fri Jun 1 14:25:55 EDT 2007

Bugs item #10577, was opened at 2007-05-04 10:57
You can respond by visiting: 

Category: rails plugin
Group: None
Status: Open
Resolution: None
Priority: 3
Submitted By: John Andrews (jandrews)
Assigned to: Nobody (None)
Summary: Rails with Oracle breaks 0.9.2

Initial Comment:
Upgrading to rspec 0.9.2 from 0.8.2 using Oracle database with ActiveRecord breaks due to the following:

  (owner, table_name) = @connection.describe(table_name)

@connection is an instance of OCI8AutoRecover which itself delegates the describe method to OCI8.

  class OCI8AutoRecover < DelegateClass(OCI8)
    # no def describe method

DelegateClass internally uses method_missing to call the delegate class' describe

  class OCI8 #:nodoc:
    def describe(name)

The problem is that rspec defines Kernel#describe, so method_missing never catches the call to delegate and it fails from rspec because there is obviously no block given.

My work-around modifies 2 files. I will just include the methods I changed because I don't have diffs from trunk.
from file: rspec_on_rails/lib/spec/rails/extensions/kernel.rb
  def describe(*args, &block)
    # assuming that if a block is not given that it is not a call
    # for rspec
    if block_given?
      args << {} unless Hash === args.last
      args.last[:spec_path] = caller(0)[1]
    original_describe(*args, &block)

from file: rspec-0.9.2/lib/spec/runner/extensions/kernel.rb
  def describe(*args, &block)
    if block_given?
      raise ArgumentError if args.empty?
      register_behaviour(Spec::DSL::BehaviourFactory.create(*args, &block))
      # not the describe that we are looking for
      # it's probably a call from the oracle adapter
      super *args

I don't know if this is the best way to fix the issue, but it works for me and all my specs pass again. if you need more info or someone to test a fix for Oracle I am able to help.


Comment By: sinclair  bain (sinclair)
Date: 2007-06-01 13:25


I just ran into this problem in rspec_for_rails 1.0.0.

The solution I think we will settle for in the short term is a monkey patch to the OCI8AutoRecover class.
The patch implements the #describe method in the OCI8AutoRecover class (via a module include). 
The patch file is in our rails_app/lib directory and is #required in the environment.rb.
This is the implementation:

module OracleAdapterPatch
  # rspec method name collision patch
  def describe(obj)
puts "OCI8AutoRecover#describe( #{obj} ) forwarded to #{@connection}"


OCI8AutoRecover.send(:include, OracleAdapterPatch)

As is stated below this is (still) a band-aid approach. 



Comment By: David Chelimsky (dchelimsky)
Date: 2007-05-05 18:56

I'm uncomfortable with this solution. It's a band-aid for this particular example, but someone else might come along and do something similar - using method_missing to delegate to another object WITH a block expected in that object's #describe method.

Does anyone have any other suggestions?


You can respond by visiting: 

More information about the rspec-devel mailing list