Accessing the model class from within an rspec-rails spec


#1

Hi everybody,

New to the list, so apologies if this has been answered elsewhere, but I
didn’t find it. I’m trying to build up a plugin of useful rspec macros
for
rails development, eg. things like:

it_should_return_success
it_should_redirect_to { some_url }

I’m basing my ideas off of some stuff technoweenie has done, as well as
a
few others.

One thing I’d love to do is be able to figure out the model class in a
rails
model spec, so I can do something like:

describe User do
it_should_validate_presence_of :name
end

I can get it working if I pass in User as an argument:

describe User do
it_should_validate_presence_of User, :name
end

but that feels redundant. Is there a way to access the class itself that
I’m
missing? On the controller spec side, I see there is
controller_class_name,
but that needs to be set with the controller_name method. I could go for
something like that if required, but somehow it seems like it would be
overkill.

Any advice would be greatly appreciated, thanks!!

Cameron


#2

On 2008-10-28, at 09:09, Cameron B. wrote:

describe User do
it_should_validate_presence_of :name
end

I can get it working if I pass in User as an argument:

describe User do
it_should_validate_presence_of User, :name
end

Hi Cameron. I haven’t played with RSpec’s internals at all, but
considering that
#it_should_validate_presence_of
is nested within
describe User do
I would imagine that there’s a way to grab “User”. Have a look at the
structure of the Example, ExampleGroup, etc classes. It’ll be stored
in one of those, somewhere.
-Nick


#3

“Cameron B.” removed_email_address@domain.invalid writes:

Is there a way to access the class itself that I’m missing?

described_type

Pat


#4

On Tue, Oct 28, 2008 at 8:09 AM, Cameron B. removed_email_address@domain.invalid
wrote:

few others.
describe User do
it_should_validate_presence_of User, :name
end

but that feels redundant. Is there a way to access the class itself that I’m
missing? On the controller spec side, I see there is controller_class_name,
but that needs to be set with the controller_name method. I could go for
something like that if required, but somehow it seems like it would be
overkill.

Any advice would be greatly appreciated, thanks!!

You’re looking for example_group.described_type, which you can get to
like this:

describe Foo do
described_type # =>Foo

it “should be Foo” do
self.class.described_type # => Foo
end
end

Cheers,
David


#5

On Wed, Oct 29, 2008 at 12:01 PM, Nick H. removed_email_address@domain.invalid
wrote:

end

Hi Cameron. I haven’t played with RSpec’s internals at all, but considering
that
#it_should_validate_presence_of
is nested within
describe User do
I would imagine that there’s a way to grab “User”. Have a look at the
structure of the Example, ExampleGroup, etc classes. It’ll be stored in one
of those, somewhere.

described_type is what you want. This represents the object being
described,


#6

Part of the testing harness on one of our projects:

module Spec::Example::ExampleGroupMethods
def model
self.described_type.to_s.underscore
end

def should_require(*attrs)
raise “should require needs at least one attribute” if attrs.empty?
model = model()
attrs.each do |attribute|
it “should require :#{attribute}” do
m = Factory.build(model.to_sym)
m.send("#{attribute}=", nil)
m.should have(1).error_on(attribute)
end
end
end

end

Using FactoryGirl for spinning up instances, but of course easily
tweaked for other mocking.

Mike


#7

Hi again,

I think I may have partly found my own answer.

Looking at this gist http://gist.github.com/14050 by Andy F., it
seems
to do much of what I’m looking for right now (thanks, awesome!!).

But playing around with it a bit, calling self.described_type which I
thought would return the class, it’s not, it seems to be looking only
for a
module?

  def described_type
    description_parts.find {|part| part.is_a?(Module)}
  end

Is there something I’m missing?

Cameron


#8

Nick H. removed_email_address@domain.invalid writes:

Hi Cameron. I haven’t played with RSpec’s internals at all, but
considering that
#it_should_validate_presence_of
is nested within
describe User do
I would imagine that there’s a way to grab “User”. Have a look at the
structure of the Example, ExampleGroup, etc classes. It’ll be stored
in one of those, somewhere.

For some reason my emails are getting bounced or delayed or something,
so I’ll try again in case my first one didn’t go through…

You’re looking for described_type

Pat


#9

On Tue, Oct 28, 2008 at 8:40 AM, Cameron B. removed_email_address@domain.invalid
wrote:

  def described_type
    description_parts.find {|part| part.is_a?(Module)}
  end

Is there something I’m missing?

Some example groups describe modules, some classes. RSpec supports
both, and Module does it:

$ irb

module Foo; end
=> nil

Foo.is_a?(Module)
=> true

class Bar; end
=> nil

Bar.is_a?(Module)
=> true

whereas Class does not.

HTH,
David
Cheers,
David


#10

On Oct 28, 2008, at 9:09 AM, Cameron B. wrote:

as a few others.
describe User do
it_should_validate_presence_of User, :name
end

but that feels redundant. Is there a way to access the class itself
that I’m missing? On the controller spec side, I see there is
controller_class_name, but that needs to be set with the
controller_name method. I could go for something like that if
required, but somehow it seems like it would be overkill.

Any advice would be greatly appreciated, thanks!!

Why not something like this:

before(:each) { @user = User.new }

it { @user.validate_presence_of(:name) }

Scott