Create a gist now

Instantly share code, notes, and snippets.

What would you like to do?
Active Record Spec Helper - Loading just active record
--colour
-I app
require 'active_record'
connection_info = YAML.load_file("config/database.yml")["test"]
ActiveRecord::Base.establish_connection(connection_info)
RSpec.configure do |config|
config.around do |example|
ActiveRecord::Base.transaction do
example.run
raise ActiveRecord::Rollback
end
end
end
class Coderetreat < ActiveRecord::Base
def self.running_today
where(scheduled_on: Date.today)
end
end
require 'active_record_spec_helper'
require 'models/coderetreat'
describe Coderetreat do
describe ".running_today" do
it "returns a coderetreat scheduled for today" do
coderetreat = Coderetreat.create! city: "Chicago", scheduled_on: Date.today
Coderetreat.running_today.all.should =~ [coderetreat]
end
it "does not return a coderetreat not scheduled for today" do
coderetreat = Coderetreat.create! city: "Chicago", scheduled_on: Date.today.advance(:days => -1)
Coderetreat.running_today.should be_empty
end
end
end
#Some databases get upset if you try to start a new transaction while a transaction is already in play, so running the whole spec suite chokes when rspec is trying to start a transaction. You need to update your spec_helper to rely on active_record_spec_helper to do this for you.
#Replace this line
config.use_transactional_fixtures = true
#With this
require 'active_record_spec_helper'
#TADA
@jcf

This comment has been minimized.

Show comment Hide comment
@jcf

jcf Jun 10, 2012

Very nice.

jcf commented Jun 10, 2012

Very nice.

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Jun 10, 2012

Thanks. It is a very handy addition.

Owner

coreyhaines commented Jun 10, 2012

Thanks. It is a very handy addition.

@steveklabnik

This comment has been minimized.

Show comment Hide comment
@steveklabnik

steveklabnik Jul 14, 2012

Thanks! I wasn't sure if you were doing something to mock AR, or just isolating AR stuff to one spec helper.

Thanks! I wasn't sure if you were doing something to mock AR, or just isolating AR stuff to one spec helper.

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Jul 14, 2012

No. I don't agree with mocking AR. This is really about a step forward in making progress towards a realistic approach to keeping things fast.

Owner

coreyhaines commented Jul 14, 2012

No. I don't agree with mocking AR. This is really about a step forward in making progress towards a realistic approach to keeping things fast.

@rubysolo

This comment has been minimized.

Show comment Hide comment
@rubysolo

rubysolo Jul 25, 2012

I have started wrapping my active_record_spec_helper in an "unless defined?(Rails)" block so that I can run the model specs alone or as part of the entire suite.

I have started wrapping my active_record_spec_helper in an "unless defined?(Rails)" block so that I can run the model specs alone or as part of the entire suite.

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Jul 25, 2012

@rubysolo I've not found the need to do that in order to have them run in both situations. What error are you seeing that causes you to need this?

Owner

coreyhaines commented Jul 25, 2012

@rubysolo I've not found the need to do that in order to have them run in both situations. What error are you seeing that causes you to need this?

@rubysolo

This comment has been minimized.

Show comment Hide comment
@rubysolo

rubysolo Jul 25, 2012

Interesting. If I run "rake", I get the following error:

activerecord-3.2.2/lib/active_record/connection_adapters/postgresql_adapter.rb:645:in `async_exec': PG::Error: connection is closed: SELECT tablename (ActiveRecord::StatementInvalid)
FROM pg_tables
WHERE schemaname = ANY (current_schemas(false))

which traces back to:

DatabaseCleaner.clean_with(:truncation)

in the active_record_spec_helper.

Interesting. If I run "rake", I get the following error:

activerecord-3.2.2/lib/active_record/connection_adapters/postgresql_adapter.rb:645:in `async_exec': PG::Error: connection is closed: SELECT tablename (ActiveRecord::StatementInvalid)
FROM pg_tables
WHERE schemaname = ANY (current_schemas(false))

which traces back to:

DatabaseCleaner.clean_with(:truncation)

in the active_record_spec_helper.

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Jul 25, 2012

Does your spec_helper set the config.use_transactional_fixtures? Take that out, replace by requiring this spec helper in your regular spec helper

Owner

coreyhaines commented Jul 25, 2012

Does your spec_helper set the config.use_transactional_fixtures? Take that out, replace by requiring this spec helper in your regular spec helper

@rubysolo

This comment has been minimized.

Show comment Hide comment
@rubysolo

rubysolo Jul 26, 2012

@coreyhaines Indeed it did, and this fixed the problem. :) Thanks!

@coreyhaines Indeed it did, and this fixed the problem. :) Thanks!

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Jul 26, 2012

@rubysolo Thanks so much for bringing this up. Glad it worked. I forgot to put that in here, so now we have it documented in the comments. :) I'll try to get it into the gist, itself, as well.

Owner

coreyhaines commented Jul 26, 2012

@rubysolo Thanks so much for bringing this up. Glad it worked. I forgot to put that in here, so now we have it documented in the comments. :) I'll try to get it into the gist, itself, as well.

@rmcastil

This comment has been minimized.

Show comment Hide comment
@rmcastil

rmcastil Aug 5, 2012

@coreyhaines is there a need for the double requires of "database_cleaner"? Isn't it unnecessary in the spec_helper?

rmcastil commented Aug 5, 2012

@coreyhaines is there a need for the double requires of "database_cleaner"? Isn't it unnecessary in the spec_helper?

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Aug 5, 2012

@rmcstil A good point.

Owner

coreyhaines commented Aug 5, 2012

@rmcstil A good point.

@rmcastil

This comment has been minimized.

Show comment Hide comment
@rmcastil

rmcastil Aug 5, 2012

@coreyhaines Thanks for posting this! Although I'm starting to get spoiled by the near instantaneous feedback and am considering dropping model specs all together. Right now I've got it costing me about 6 seconds to load active record. Is that what you do with mercuryapp?

rmcastil commented Aug 5, 2012

@coreyhaines Thanks for posting this! Although I'm starting to get spoiled by the near instantaneous feedback and am considering dropping model specs all together. Right now I've got it costing me about 6 seconds to load active record. Is that what you do with mercuryapp?

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Aug 5, 2012

@rmcastil Yeah, that's the eventual goal. I tend to only want to load active record when I'm dealing with scopes. Those make sense to have the database loaded up.
This technique is very useful to shrink the feedback loop, so you can start effectively making changes to your design.

Owner

coreyhaines commented Aug 5, 2012

@rmcastil Yeah, that's the eventual goal. I tend to only want to load active record when I'm dealing with scopes. Those make sense to have the database loaded up.
This technique is very useful to shrink the feedback loop, so you can start effectively making changes to your design.

@revans

This comment has been minimized.

Show comment Hide comment
@revans

revans Aug 22, 2012

@coreyhaines Instead of DatabaseCleaner you could do something like this: ActiveRecord::Base.subclasses.each(&:delete_all) DatabaseCleaner is such a beast to load.

revans commented Aug 22, 2012

@coreyhaines Instead of DatabaseCleaner you could do something like this: ActiveRecord::Base.subclasses.each(&:delete_all) DatabaseCleaner is such a beast to load.

@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Dec 3, 2012

Thanks @revans. I'll try that.

Owner

coreyhaines commented Dec 3, 2012

Thanks @revans. I'll try that.

@elight

This comment has been minimized.

Show comment Hide comment
@elight

elight Dec 27, 2012

Very glad that you gist'd this. I had similar thoughts as @steveklabnik. I appreciate the insight!

elight commented Dec 27, 2012

Very glad that you gist'd this. I had similar thoughts as @steveklabnik. I appreciate the insight!

@brandonhilkert

This comment has been minimized.

Show comment Hide comment
@brandonhilkert

brandonhilkert Dec 28, 2012

@coreyhaines

Not using database_cleaner and using the below code cut off 0.2-0.3 sec.

  config.around do |example|
    ActiveRecord::Base.transaction do
      example.run
      raise ActiveRecord::Rollback
    end
  end

@coreyhaines

Not using database_cleaner and using the below code cut off 0.2-0.3 sec.

  config.around do |example|
    ActiveRecord::Base.transaction do
      example.run
      raise ActiveRecord::Rollback
    end
  end
@coreyhaines

This comment has been minimized.

Show comment Hide comment
@coreyhaines

coreyhaines Dec 28, 2012

@brandonhilkert Thanks. I'm going to try that.

Owner

coreyhaines commented Dec 28, 2012

@brandonhilkert Thanks. I'm going to try that.

@gvc

This comment has been minimized.

Show comment Hide comment
@gvc

gvc Dec 28, 2012

What happens with a class with a lot of relations? We may end up manually requiring a lot of things, won't we? Or is there a catch that I'm not seeing?

gvc commented Dec 28, 2012

What happens with a class with a lot of relations? We may end up manually requiring a lot of things, won't we? Or is there a catch that I'm not seeing?

@felipeelias

This comment has been minimized.

Show comment Hide comment
@felipeelias

felipeelias Jan 6, 2013

@brandonhilkert that's cool! But if you use capybara-webkit for example, this doesn't work :(

@brandonhilkert that's cool! But if you use capybara-webkit for example, this doesn't work :(

@felipeelias

This comment has been minimized.

Show comment Hide comment
@felipeelias

felipeelias Jan 6, 2013

@brandonhilkert I mean, unless you workaround https://gist.github.com/4469873

@zamith

This comment has been minimized.

Show comment Hide comment
@zamith

zamith Jan 8, 2013

Two things I've noticed:

  • I had to require the model like this require_relative '../../app/models/coderetreat
  • When loading the full stack I had an ActiveModel::MassAssignmentSecurity::Error which passed with this approach

Not sure if I'm doing anything wrong. The idea is awesome though.

zamith commented Jan 8, 2013

Two things I've noticed:

  • I had to require the model like this require_relative '../../app/models/coderetreat
  • When loading the full stack I had an ActiveModel::MassAssignmentSecurity::Error which passed with this approach

Not sure if I'm doing anything wrong. The idea is awesome though.

@jfelchner

This comment has been minimized.

Show comment Hide comment
@jfelchner

jfelchner Jan 30, 2013

@zamith, I had the same problem. Were you sure to add the -I app line to your .rspec file? Then you require 'models/coderetreat'. That fixed it for me.

@zamith, I had the same problem. Were you sure to add the -I app line to your .rspec file? Then you require 'models/coderetreat'. That fixed it for me.

@gmodarelli

This comment has been minimized.

Show comment Hide comment
@gmodarelli

gmodarelli Sep 7, 2013

If you are using Rails 4 with SQLite and database_cleaner 1.1.1 you get this error
undefined local variable or method `postgresql_version'

to solve the problem downgrade to database_cleaner 1.0.1

Thank you @coreyhaines for sharing this.

If you are using Rails 4 with SQLite and database_cleaner 1.1.1 you get this error
undefined local variable or method `postgresql_version'

to solve the problem downgrade to database_cleaner 1.0.1

Thank you @coreyhaines for sharing this.

@georgemillo

This comment has been minimized.

Show comment Hide comment
@georgemillo

georgemillo Nov 22, 2014

I had to add require "yaml" to the top of active_record_spec_helper to get this to work. RSpec 3.1.7, Rails 4.1.8.

I had to add require "yaml" to the top of active_record_spec_helper to get this to work. RSpec 3.1.7, Rails 4.1.8.

@georgemillo

This comment has been minimized.

Show comment Hide comment
@georgemillo

georgemillo Nov 26, 2014

I love this idea, and I really want to implement it more in my test suites. But I'm having the problem that my ActiveRecord models just have too damn many dependencies, and I have to add so many "requires" at the top of my spec file that I might as well just require spec_helper.

Of course, the obvious solution here is to reduce the number of dependencies. And in some cases this is pretty easy, but it's often not, because a lot of the dependencies are due to my associations.

E.g. say I have an model User that looks like this:

class Comment < ActiveRecord::Base
  belongs_to :design
end

If I set up my spec like this:

require 'active_record_spec_helper'

require "comment"

describe Comment do
  ... whatever
end

... then it will fail, because when it tries to load "comment.rb", it hits the line belongs_to :design, and starts looking for a Design class - which hasn't been required, so the whole thing crashes with uninitialized constant Comment::Design.

So I add require 'design' to the top of my spec - but within my Design class I have the line belongs_to :user, which crashes with uninitialized constant Design::User... so I add require 'user' to the top of my spec, which hits the line has_many :posts and raises uninitialized constant User::Post... and so on until I've required almost my entire app/models directory.

Is there something conceptual I'm missing? How do I get around this? Basic Rails associations don't seem like something I should be refactoring out into a separate class or module, and stubbing out the associations feels a bit icky too (plus I'm not entirely sure how to do it anyway.)

Anyone have any pointers?

I love this idea, and I really want to implement it more in my test suites. But I'm having the problem that my ActiveRecord models just have too damn many dependencies, and I have to add so many "requires" at the top of my spec file that I might as well just require spec_helper.

Of course, the obvious solution here is to reduce the number of dependencies. And in some cases this is pretty easy, but it's often not, because a lot of the dependencies are due to my associations.

E.g. say I have an model User that looks like this:

class Comment < ActiveRecord::Base
  belongs_to :design
end

If I set up my spec like this:

require 'active_record_spec_helper'

require "comment"

describe Comment do
  ... whatever
end

... then it will fail, because when it tries to load "comment.rb", it hits the line belongs_to :design, and starts looking for a Design class - which hasn't been required, so the whole thing crashes with uninitialized constant Comment::Design.

So I add require 'design' to the top of my spec - but within my Design class I have the line belongs_to :user, which crashes with uninitialized constant Design::User... so I add require 'user' to the top of my spec, which hits the line has_many :posts and raises uninitialized constant User::Post... and so on until I've required almost my entire app/models directory.

Is there something conceptual I'm missing? How do I get around this? Basic Rails associations don't seem like something I should be refactoring out into a separate class or module, and stubbing out the associations feels a bit icky too (plus I'm not entirely sure how to do it anyway.)

Anyone have any pointers?

@georgemillo

This comment has been minimized.

Show comment Hide comment
@georgemillo

georgemillo Dec 16, 2014

Sorry, me again. StackOverflow bounty is available to anyone who can help me out with the above question:

https://stackoverflow.com/questions/27427072/requiring-an-activerecord-model-without-having-to-require-the-entire-class-diagr

Sorry, me again. StackOverflow bounty is available to anyone who can help me out with the above question:

https://stackoverflow.com/questions/27427072/requiring-an-activerecord-model-without-having-to-require-the-entire-class-diagr

@christianrolle

This comment has been minimized.

Show comment Hide comment
@christianrolle

christianrolle Jul 8, 2015

Did anyone came up with a solution to the question of georgemillo? I also struggle with the idea of loading all dependent models, which is undesireable to me.

Did anyone came up with a solution to the question of georgemillo? I also struggle with the idea of loading all dependent models, which is undesireable to me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment