Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails 3 - Multiple database with joins condition

My environment: Ruby 1.9.2p290, Rails 3.0.9 and RubyGem 1.8.8

unfortunately I have an issue when come across multiple database.

The situation is this: I have two model connect with two different database and also establishing association between each other. database connection specifying in each model, look likes

class Visit < ActiveRecord::Base
  self.establish_connection "lab"
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  self.establish_connection "main"
  has_many :visits
end

I got an error when meet following scenario

@visits = Visit.joins(:patient)

Errors: Mysql2::Error: Table 'lab.patients' doesn't exist: SELECT visits.* FROM visits INNER JOIN patients ON patients.id IS NULL

Here 'patients' table is in 'main' database and 'visits' table in 'lab' database I doubt when executing the code, that Rails is considering 'patients' table is part of 'lab' database [which holds 'visits' table].

like image 659
Manivannan Jeganathan Avatar asked Nov 01 '11 14:11

Manivannan Jeganathan


People also ask

Can Rails connect to multiple databases?

Rails now has support for multiple databases so you don't have to store your data all in one place. At this time the following features are supported: Multiple writer databases and a replica for each. Automatic connection switching for the model you're working with.

What is the difference between includes and joins in Rails?

:joins uses inner join, :includes uses outer join. the main reason of :includes is eager loading, to avoid the N+1 problem of loading in attributes of each object using a separate query.

What is ActiveRecord in Ruby on Rails?

What is ActiveRecord? ActiveRecord is an ORM. It's a layer of Ruby code that runs between your database and your logic code. When you need to make changes to the database, you'll write Ruby code, and then run "migrations" which makes the actual changes to the database.

What is ActiveRecord base?

ActiveRecord::Base indicates that the ActiveRecord class or module has a static inner class called Base that you're extending.


2 Answers

Well, I don't know if this is the most elegant solution, but I did get this to work by defining self.table_name_prefix to explicitly return the database name.

class Visit < ActiveRecord::Base
  def self.table_name_prefix
    renv = ENV['RAILS_ENV'] || ENV['RACK_ENV']
    (renv.empty? ? "lab." : "lab_#{renv}.")
  end

  self.establish_connection "lab"
  belongs_to :patient
end

class Patient < ActiveRecord::Base
  def self.table_name_prefix
    renv = ENV['RAILS_ENV'] || ENV['RACK_ENV']
    (renv.empty? ? "main." : "main_#{renv}.")
  end

  self.establish_connection "main"
  has_many :visits
end

I'm still working through all the details when it comes to specifying the join conditions, but I hope this helps.

like image 143
srosenhamer Avatar answered Oct 05 '22 02:10

srosenhamer


Might be cleaner to do something like this:

  def self.table_name_prefix
    "#{Rails.configuration.database_configuration["#{Rails.env}"]['database']}."
  end

That will pull the appropriate database name from your database.yml file

like image 21
Alexander Sweeney Avatar answered Oct 05 '22 01:10

Alexander Sweeney