zoukankan      html  css  js  c++  java
  • Magic MultiConnections

    WARNING

    Sponsors

    Mocra will Rescue your Rails project

    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 select development, test or production.

    But, what if you want to access two or more databases – have 2+ connections open – at the same time. ActiveRecord requires that you subclass ActiveRecord::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; end
    ActiveRecord::Base.establish_connection :production
    Person.connection # => production
    module ContactRepository
    establish_connection :contact_repo
    end
    ContactRepository::Person.connection # => contact_repo
    old_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 module ContactRepository, 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 would be greatly appreciated

    Installing

    sudo gem install magic_multi_connections

    Rails: Add the following to the bottom of your environment.rb file

    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 our private database within the console and rake tasks.

    2. Edit config/database.yml and add our private database:

    Add the following to the bottom of config/database.yml

    private:
    adapter: sqlite3
    database: db/private.sqlite3
    

    3. Create a database schema

    Edit db/migrate/001_create_people.rb

    class CreatePeople < ActiveRecord::Migration
    def self.up
    create_table :people do |t|
    t.column :name, :string
    end
    end
    def self.down
    drop_table :people
    end
    end
    

    From the command line, migrate this to our development and private databases:

    > 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 should be obvious which database our app is accessing.

    5. Update environment.rb

    Edit config/environment.rb to include the library and create the Private module.

    Add the following to the end of the file.

    require "magic_multi_connections"
    module Private
    establish_connection :private
    end
    

    This tells the Private module that any model class that is requested will be assigned a connection to the private database, as defined in the config/database.yml specification.

    6. Setup a controller

    Create a people controller with a index action

    > ruby script/generate controller people index

    Edit your controller app/controllers/people_controller.rb

    class PeopleController < ApplicationController
    before_filter :check_private
    def index
    @people = @mod::Person.find(:all)
    end
    private
    def check_private
    @mod = params[:private] ? Private : Object
    end
    end
    

    The check_private action 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.

    After check_private is called, @mod is either the Object (default) module or the Private module. The Person class is accessible through either of them.

    Yes, @mod::Person is uglier than just Person. Sorry.

    7. Setup the index.rhtml view

    Edit app/views/people/index.rhtml

    <h1><%= @mod::Person %></h1>
    <h2><%= @mod::Person.active_connection_name %></h2>
    <ol>
    <% @people.each do |person| -%>
    <li><%= "#{person.name} - #{person.class}" %></li>
    <% end -%>
    </ol>
    

    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 in the app/models folder. If you place them in a subfolder, say app/models/admin, then those model classes are access via module namespaces.

    So, app/models/admin/page.rb represents the Admin::Page class.

    Magic Multi-Connections works for these model classes as well.

    Admin.establish_connection :admin_dev
    Admin::Page.active_connection_name # => "Admin::Page"
    

    Related articles

    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.

  • 相关阅读:
    ASP.NET MVC案例教程(基于ASP.NET MVC beta)——第二篇:第一个页面
    HTML5网页录音和压缩,边猜边做..(附源码)
    策划编写一个新的Helper类
    正由另一进程使用,因此该进程无法访问此文件。
    第三方组件引用另一个第三方组件的悲剧
    数据库连接池的计数器设计
    让Ajax更简单
    更新Literacy
    多说
    利用C#自带组件强壮程序日志
  • 原文地址:https://www.cnblogs.com/hannover/p/1423541.html
Copyright © 2011-2022 走看看