Document directory
- 1. Create rails app
- 3. Create a database schema
- 4. Add some data to databases
- 5. Update environment. Rb
- 6. setup a controller
- 7. setup the index. rhtml View
- 8. test our multi-connection rails app
- 9. End
Warning
Despite the 1.1.0 version number, this gem is not quite production ready. various people have experienced problems using the 1.0.0 version. A solution was found to deal with this issue but it has not been fully tested, so please subscribe to the forum or rubyforge news for any updates.
What
Activerecord models are allowed one connection to a database at a time, per class. Ruby on Rails sets up the default connection based on your database. yml configuration to automatically selectDevelopment,TestOrProduction.
But, what if you want to access two or more databases-have 2 + connections open-at the same time. activerecord requires that you subclassActiveRecord::Base.
That prevents you doing migrations from one database to another. It prevents you using one set of model classes on two or more databases with the same schema.
Magic multi-connections allows you to write your models once, and use them for multiple database rails databases at the same time. How? Using magical namespacing.
class Person < ActiveRecord::Base; endActiveRecord::Base.establish_connection :productionPerson.connection # => productionmodule ContactRepositoryestablish_connection :contact_repoendContactRepository::Person.connection # => contact_repoold_person = ContactRepository::Person.find_by_email(email)person = old_person.create_as(Person)
You do not have to redefine your models for the multi-connection moduleContactRepository, They are automatically picked up for you. magically.
Todo: example about associations
Issues
Despite the 1.1.0 version of this gem there are still a number of issues with this gem:
- Single Table inheritance is not currently supported
- No Connection pooling for alternate Databases
Any help wowould be greatly appreciated
Installing
sudo gem install magic_multi_connections
Rails: add the following to the bottom of yourenvironment.rbFile
require 'magic_multi_connections'
Ruby scripts: add the following to the top of your script
require 'rubygems'require 'magic_multi_connections'
Demonstration with rails
A quick demonstration within rails to provide a parallel "private" database for an application.
1. Create rails app
Using sqlite3 here, but use your preferred DB:
> rails privacy -d sqlite3> cd privacy> ruby script/generate model Person> cp config/environments/development.rb config/environments/private.rb
The last line allows us to play with ourPrivateDatabase within the console and rake tasks.
2. Edit
Config/database. ymlAnd add our private database:
Add the following to the bottomConfig/database. yml
private:adapter: sqlite3database: db/private.sqlite3
3. Create a database schema
EditDB/migrate/00w.create_people.rb
class CreatePeople < ActiveRecord::Migrationdef self.upcreate_table :people do |t|t.column :name, :stringendenddef self.downdrop_table :peopleendend
From the command line, migrate this to ourDevelopmentAndPrivateDatabases:
> rake db:migrate> rake db:migrate RAILS_ENV=private
4. Add some data to databases
> ruby script/console development>> Person.create(:name => 'Nic')>> Person.create(:name => 'Banjo')>> exit> ruby script/console private>> Person.create(:name => 'Super Magical Nic')>> exit
Now it shoshould be obvious which database our app is accessing.
5. Update environment. Rb
EditConfig/environment. RbTo include the library and createPrivateModule.
Add the following to the end of the file.
require "magic_multi_connections"module Privateestablish_connection :privateend
This tellsPrivateModule that any model class that is requested will be assigned a connection toPrivateDatabase, as defined inConfig/database. ymlSpecification.
6. setup a controller
CreatePeopleController withIndexAction
> ruby script/generate controller people index
Edit your ControllerAPP/controllers/people_controller.rb
class PeopleController < ApplicationControllerbefore_filter :check_privatedef index@people = @mod::Person.find(:all)endprivatedef check_private@mod = params[:private] ? Private : Objectendend
TheCheck_privateAction is a hack to demonstrate one method for selecting the database. In reality, a stupid one for hiding a "private" database, but you get the point.
AfterCheck_privateIs called,@ ModIs eitherObject(Default) module orPrivateModule.PersonClass is accessible through either of them.
Yes,@mod::PersonIs uglier than justPerson. Sorry.
7. setup the index. rhtml View
EditAPP/views/people/index. rhtml
8. test our multi-connection rails app
Launch the app
> mongrel_rails start
In your browser, go to http: // localhost: 3000/people and see the list of people: Nic and banjo.
Now, to see the private database, go to http: // localhost: 3000/people? Private = 1 and see the private list. Its so private, I won't show it here.
Note: you may need to refresh the Private URL to see the results. perhaps rails is caching the SQL even though its a different connection to a different database. if you know what's happening here, please email me or the Forum. thanks.
9. End
There ends our example of a rails application using one model class to access multiple databases cleanly.
Pre-existing modules
In rails, model files are placed inAPP/modelsFolder. If you place them in a subfolder, sayAPP/models/admin, Then those model classes are access via module namespaces.
So,APP/models/admin/page. RbRepresentsAdmin::PageClass.
Magic multi-connections works for these model classes as well.
Admin.establish_connection :admin_devAdmin::Page.active_connection_name # => "Admin::Page"
Related Articles
- Original blog article-magic multi-connections: A "Facility in rails to talk to more than one database at a time
- Discussed by DHH
Dr Nic's blog
Http://www.drnicwilliams.com/-for future announcements and other stories and things.
Forum
Discussion about the magic multi-connections is on the magic models Forum:
Http://groups.google.com/group/magicmodels
Licence
This code is free to use under the terms of the MIT licence.
Contact
Comments are welcome. send an email to Dr Nic Williams
Activerecord is an object relationship ing (ORM) layer provided by rails. Starting from this article, we will learn some basic content of active record, connect to the database, map tables, and access data.
Active record uses the basic ORM mode: tables are mapped to classes, rows are mapped to objects, and columns are mapped to object attributes. Unlike many ORM libraries that use a large number of configurations, active record minimizes the configuration. Imagine a program using active record converts the orders table in the MySQL database to a class, finds the order through the specified ID, sets the name of the order, and saves it back to the database:
require "rubygems"require_gem "activerecord"ActiveRecord::Base.establish_connection(:adapter => "mysql",:host => "localhost", :database => "railsdb")class Order < ActiveRecord::Baseendorder = Order.find(123)order.name = "Dave Thomas"order.save
In the above example, no configuration is required. Active record does these tasks for us. Let's take a look at how activerecord works.
Tables and Classes
When you create a subclass of the activerecord: base class, the active record assumes that the table name is plural and the class name is singular. When the class name contains multiple words, the table name is assumed to contain underscores (_) between words, and the complex form is irregular. For example:
Class Name table name class name table name
Order orders lineitem line_items
Taxagency tax_agencies person people
Diagnosis diagnoses quantity quantities
Batch batches datum data
By default, the active record table name is plural and the class name is singular. If you are not familiar with it, you can disable it by setting a global tag. In the config directory, environment. settings in the RB file:
ActiveRecord::Base.pluralize_table_names = false
The single and multiple numbers rule can deal with most situations. In some special cases, active record allows us to overwrite the default generated table name and use the set_table_name command, for example:
class Sheep < ActiveRecord::Baseset_table_name "sheep" # Not "sheeps"endclass Order < ActiveRecord::Baseset_table_name "ord_rev99_x" # Wrap a legacy table...end
Active record abstracts the concept of database connection and helps applications process the details of underlying database links. As an alternative, active record uses common calls to delegate details to a group of database adapters.
You can use the establish_connection () method to establish a connection. The following example creates a MySQL database connection. The database name is railsdb, the host name of the server is dbserver.com, the username is railsuser, And the password is railspw.
ActiveRecord::Base.establish_connection(:adapter => "mysql",:host => "dbserver.com",:database => "railsdb",:username => "railsuser",:password => "railspw")
Active record supports DB2, MySQL, Oracle, S, sqlserver, and sqllite. The connection parameters of each database adapter vary slightly. The following table lists common parameters:
Note that the Oracle adapter is named OCI.
Database connections and model classes are associated. Each class inherits links from its parent class. activerecord: Base is the parent class of all active record classes, when the database connection is set here, the link is set for all activity record classes. Of course, you can also configure the override link if necessary.
In the following example, most of our tables are in the MySQL database and the database name is online. For some historical reasons, the customers table is in the database named backend,
ActiveRecord::Base.establish_connection(:adapter => "mysql",:host => "dbserver.com",:database => "online",:username => "groucho",:password => "swordfish")class LineItem < ActiveRecord::Base# ...endclass Order < ActiveRecord::Base# ...endclass Product < ActiveRecord::Base# ...endclass Customer < ActiveRecord::Base# ...endCustomer.establish_connection(:adapter => "mysql",:host => "dbserver.com",:database => "backend",:username => "chicho",:password => "piano")
In the depot program we wrote earlier, we didn't use the establish_connection method, but in config/database. the yaml file specifies the database connection parameter information. For most rails programs, This is the preferred method, not only because the configuration information is separated from the code, in addition, it is convenient to test and deploy. The parameters listed in the preceding table can be applied to the yaml file. This is described in the previous configuration file section.
Finally, if you access establish_connection () through a tag, rails will be in the database. search for the configuration section corresponding to the name in the yaml file to obtain the link parameters. In this way, all database connection configurations can be separated from the code.
config = YAML::load(File.open('config/database.yml')) ActiveRecord::Base.establish_connection(config["production"])