Alister Scott
Alister Scott

Reputation: 3685

Passing ruby instance variables from Rspec to mix ins

I am trying to access instance variables I have defined in RSpec in the modules that I am mixing into RSpec, but I can't seem to get this to work.

A simplifed spec file shows the problem I am having:

my_spec.rb

require 'rspec'

describe 'passing instance variables from specs into ruby mixins' do
  it 'should pass the instance variable to the module' do
    @a = 'a'
    A.a.should == 'a'
  end

  it 'should pass the instance variable to the module in the module' do
    @b = 'b'
    A.b.should == 'b'
  end

  it 'should pass instance varisables from one module to the other' do
    A.c.should == 'c'
  end

end

module B
  def b
    return @b
  end

  def c
    return @c
  end
end

module A
  extend B
  @c = 'c'
  def self.a
    return @a
  end
end

Results:

1) passing instance variables from specs into ruby mixins should pass the instance variable to the module
     Failure/Error: A.a.should == 'a'
       expected: "a"
            got: nil (using ==)
     # ./spec/my_spec.rb:6:in `block (2 levels) in <top (required)>'

  2) passing instance variables from specs into ruby mixins should pass the instance variable to the module in the module
     Failure/Error: A.b.should == 'b'
       expected: "b"
            got: nil (using ==)
     # ./spec/my_spec.rb:11:in `block (2 levels) in <top (required)>'

Basically, I want to be able to access the instance variables @a, @b in both the modules A and B. I have tried using class variables @@a and @@b, but this doesn't work.

I can use global variables ($a and $b), and this works, but I feel this isn't elegant as they're global variables, which are evil.

Working code:

require 'rspec'

describe 'passing instance variables from specs into ruby mixins' do
  it 'should pass the instance variable to the module' do
    $a = 'a'
    A.a.should == 'a'
  end

  it 'should pass the instance variable to the module in the module' do
    $b = 'b'
    A.b.should == 'b'
  end

  it 'should pass instance varisables from one module to the other' do
    A.c.should == 'c'
  end

end

module B
  def b
    return $b
  end

  def c
    return @c
  end
end

module A
  extend B
  @c = 'c'
  def self.a
    return $a
  end
end

Any ideas?

Upvotes: 0

Views: 1093

Answers (1)

JMS
JMS

Reputation: 2193

Even though they share the same name, they are scoped separately, because they are scoped to the instance where they are defined.

That is to say, the instance variables you've set in the specs only exist within the scope of those specs. Similarly, the instance variables inside the modules are similarly scoped to that context.

I'm not sure if it matches what you're trying to accomplish given the example is abstracted, but try this:

require 'rspec'

module B
  def b= b
    @b = b
  end

  def b
    return @b
  end

  def c= c
    @c = c
  end

  def c
    return @c
  end
end

module A
  extend B

  @c = 'c'

  def self.a= a
    @a = a
  end

  def self.a
    return @a
  end
end

describe 'passing instance variables from specs into ruby mixins' do
  it 'should pass the instance variable to the module' do
    A.a = 'a'
    A.a.should == 'a'
  end

  it 'should pass the instance variable to the module in the module' do
    A.b = 'b'
    A.b.should == 'b'
  end

  it 'should pass instance varisables from one module to the other' do
    A.c.should == 'c'
  end
end

This could then be simplified to use attr_accessor instead of defining the getter/setter methods manually.

The problem is that you're then simply testing the guts of Ruby.

Did I misunderstand the problem you're trying to solve?

Upvotes: 1

Related Questions