Forum: Ruby on Rails Strategies for Unit testing 2 databases

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Mike E. (Guest)
on 2006-02-08 18:17
(Received via mailing list)
Hi,

My application spans 2 (or more) databases for some very specific
reasons... My models are working fine, even dynamically establishing
connections as needed at runtime, and spanning relationships across the
databases (which really impressed me).  The problem is, I can't seem to
force Units for these models (that use a secondary db) to load their
fixtures into and use the secondary database.

I tried applying this:

Project.establish_connection(:test_group)
(where :test_group is a database connection defined in database.yml)

at various locations within the test itself, and test_helper.rb... but
my unit is failing with this error:

ActiveRecord::StatementInvalid: Mysql::Error: Table
'scoot_test.projects' doesn't exist: DELETE FROM projects
(and scoot_test is the 'main' database, but projects should be a table
in the 'secondary' database)

So, any advice on how I might be able to get this to work?

Thanks,
Mike
sayoyo S. (Guest)
on 2006-02-08 18:46
(Received via mailing list)
Hi Mikes,

Rails stores the database tablename within the
corresponding ActiveRecord::base subclass. inside the
"connection_specification" class there is a hash which
contains information about which class is using which
db connection. and if there is no connection define
for a class it will go to its parent.

So what I understand, is that your have two databases,
 and the class can finf its table? am I right.

if it is the case, it is because the class is using
the wrong connection, so the worng database.

SO I suggestion you to create two parents for your
databases. like db1 <activeRecords::base and db2
<activeRecords::base. all the table-class from db1
should inherited not directly form
activeRecords::base, but db1 and same for the
table-class from db2.  when you connect dynamically to
your database, uses

db1.establish_connection(...) so all the table-class
used db1 will have the same db connection and the same
for db2.

actually, I'm using 2 db also. it works for me, so I
hope it will work for you.

Saiho



--- Mike E. <removed_email_address@domain.invalid> wrote:

> force Units for these models (that use a secondary
> test_helper.rb... but
> work?
>
> Thanks,
> Mike
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Mike E. (Guest)
on 2006-02-08 19:07
(Received via mailing list)
Thanks Saiho,

If I understand you correctly, that's kind of what I'm doing...
Project < ActiveRecord::Base
  Project.establish_connection(:db2)
end
And all other models in db2 inherit from Project.

That works fine from the console... the problem is, when trying to write
unit tests, the fixtures for Project are being loaded into (well,
attempted at least) db1, but I can't figure out why that would be.

I tried this:
Project < ActiveRecord::Base
  Project.establish_connection(:db2)
  if (RAILS_ENV == "test") then
    Project.establish_connection(:db2_test)
  end
end

But it's still trying to load things into db1_test... it almost seems
like ActiveRecord::Base.establish_connection is turned off during
testing...

M.
sayoyo S. (Guest)
on 2006-02-08 21:05
(Received via mailing list)
Hi Mike,

Did you try to connect to 2 db within the same action?
if it is the case, I have an example code, that may
help, but not for all db, I'm using postgresql. so not
sure that it will work for all other databse.

if you are trying to use two different database in two
different action/controllers, there is an example on
http://wiki.rubyonrails.org/rails/pages/HowtoUseMu...

 May be you should try:
Project < ActiveRecord::Base
  if (RAILS_ENV == "test") then
     Project.establish_connection(:db2_test)

 Project.establish_connection(:db2)


>   end
> end





--- Mike E. <removed_email_address@domain.invalid> wrote:

> when trying to write
>   end
> Saiho Y. wrote:
> define
> > SO I suggestion you to create two parents for your
> > used db1 will have the same db connection and the
>
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


If God really exists, I would like to
know what the dinosaurs have done to
deserve their extinction.

Water is unknown to fishes,
until they discover air.

http://www.geocities.com/sayoyo/

__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Tom F. (Guest)
on 2006-02-08 21:11
(Received via mailing list)
I took a look at this a few months ago.

It looks like the test code is just broken for multiple databases.  The
only
database the code uses is the one set for Base, so your per-model
database
won't work during testing.

It looked to be a non-trivial piece of work to make the test code work
with
multiple databases, so I moved on to something else.

In my case, it doesn't matter too much, as I only have one very simple
model
in my second DB, and it's real obvious in my app when it breaks!
sayoyo S. (Guest)
on 2006-02-08 21:17
(Received via mailing list)
sorry,

I pressed on the wrong button:) what I want ot say is:

May be you should try:
Project < ActiveRecord::Base
 if (RAILS_ENV == "test") then
   Project.establish_connection(:db2_test)
 else
   Project.establish_connection(:db2)
end

I think this is better, because the class will not be
assigned two times.





--- Saiho Y. <removed_email_address@domain.invalid> wrote:

> two
> different action/controllers, there is an example on
>
http://wiki.rubyonrails.org/rails/pages/HowtoUseMu...
> > end
> > I'm doing...
> > attempted at least) db1, but I can't figure out
> >
> > >
> > > for a class it will go to its parent.
> your
> > table-class
> > > Saiho
>
> Do You Yahoo!?
> Tired of spam?  Yahoo! Mail has the best spam
> protection around
> http://mail.yahoo.com
> _______________________________________________
> Rails mailing list
> removed_email_address@domain.invalid
> http://lists.rubyonrails.org/mailman/listinfo/rails
>


__________________________________________________
Do You Yahoo!?
Tired of spam?  Yahoo! Mail has the best spam protection around
http://mail.yahoo.com
Mike E. (Guest)
on 2006-02-08 21:47
(Received via mailing list)
Tom F. wrote:
> in my second DB, and it's real obvious in my app when it breaks!
> Did you try to connect to 2 db within the same action?
>   if (RAILS_ENV == "test") then
>      Project.establish_connection(:db2_test)
>
>  Project.establish_connection(:db2)
>
>
>
Ok, I've been digging into ActiveRecord and fixtures.rb and it looks
like the reason this is broken is because fixtures don't really look at
models to do their magic... they (by default) use the db connection of
ActiveRecord::Base.

I found a couple ways around this... The more complicated way (which
doesn't seem to work anyway) was to create your own instance of
Fixtures:
class ProjectTest < Test::Unit::TestCase
  fixtures :groups
  Project.establish_connection(:test_group)
  @fix = Fixtures.new(Project.connection, "projects",
File.dirname(__FILE__) + "/../fixtures")
  @fix.insert_fixtures
  ....

The problem is insert_fixtures isn't really doing anything... I'm sure
there's a way I just don't completely understand the API.

I moved onto another method, which is to create my own custom rake tasks
that will load my custom fixtures into the 2nd database as needed.  Then
I'll insert it into the default test_units and test_functional tasks.
I'll post the results as soon as I'm done.

m
Agnieszka F. (Guest)
on 2006-02-22 13:49
Mike E. wrote:

> Ok, I've been digging into ActiveRecord and fixtures.rb and it looks
> like the reason this is broken is because fixtures don't really look at
> models to do their magic... they (by default) use the db connection of
> ActiveRecord::Base.
>
> I found a couple ways around this... The more complicated way (which
> doesn't seem to work anyway) was to create your own instance of
> Fixtures:
> class ProjectTest < Test::Unit::TestCase
>   fixtures :groups
>   Project.establish_connection(:test_group)
>   @fix = Fixtures.new(Project.connection, "projects",
> File.dirname(__FILE__) + "/../fixtures")
>   @fix.insert_fixtures
>   ....
>
> The problem is insert_fixtures isn't really doing anything... I'm sure
> there's a way I just don't completely understand the API.
>
> I moved onto another method, which is to create my own custom rake tasks
> that will load my custom fixtures into the 2nd database as needed.  Then
> I'll insert it into the default test_units and test_functional tasks.
> I'll post the results as soon as I'm done.
>
> m


Hello,

this seems to be working:

in the model:

if ENV["RAILS_ENV"]=="test"
  Person.establish_connection "db_test"
else
  Person.establish_connection "db"
end

in the test - instead of "fixtures :people" something like this:

Fixtures.create_fixtures(File.dirname(__FILE__) + "/../fixtures",
["people"]){Person.connection}

the connection can be passed in a block. I'd love to see this or better
solution in the chapter on using multiple databases in Rails Recipes.
Please :)

--
Agnieszka F.
Chad F. (Guest)
on 2006-02-23 00:03
(Received via mailing list)
> end
>
> in the test - instead of "fixtures :people" something like this:
>
> Fixtures.create_fixtures(File.dirname(__FILE__) + "/../fixtures",
> ["people"]){Person.connection}
>
> the connection can be passed in a block. I'd love to see this or better
> solution in the chapter on using multiple databases in Rails Recipes.
> Please :)
>

Great idea!  I'm adding this (or something like it) to my TODO list.

Thanks!
--
Chad F.
http://chadfowler.com
http://pragmaticprogrammer.com/titles/fr_rr/ (Rails Recipes - In Beta!)
http://pragmaticprogrammer.com/titles/mjwti/ (My Job Went to India,
and All I Got Was This Lousy Book)
http://rubycentral.org
http://rubygarden.org
http://rubygems.rubyforge.org (over one million gems served!)
This topic is locked and can not be replied to.