zoukankan      html  css  js  c++  java
  • ActiveRecord::Base.establish_connection

    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 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

    ActiveRecord是Rails提供的一个对象关系映射(ORM)层,从这篇开始,我们来了解Active Record的一些基础内容,连接数据库,映射表,访问数据等。

    Active Record使用基本的ORM模式:表映射成类,行映射成为对象,列映射成对象的属性。与很多大量使用配置的ORM库不同,Active Record最小化了配置。想象一下,有一个使用Active Record的程序把Mysql数据库中的orders表转换到类,通过制定的ID查找到order,设定order的名称,然后保存回数据库:

    require "rubygems"
    
    require_gem "activerecord"
    
    ActiveRecord::Base.establish_connection(:adapter => "mysql",
    
    :host => "localhost", :database => "railsdb")
    
    class Order < ActiveRecord::Base
    
    end
    
    order = Order.find(123)
    
    order.name = "Dave Thomas"
    
    order.save
    

    在上面的例子里不需要任何配置,Active Record为我们做了这些事情,下面我们来看看ActiveRecord是怎样工作的。

    表和类

        当你创建了一个ActiveRecord::Base类的子类,Active Record假定表名是复数的,而类名是单数的,当类名包括多个单词时,表名被假定为单词间带有下划线,复数形式不规则,例如:

    类名                表名                    类名               表名

    Order               orders                LineItem           line_items

    TaxAgency          tax_agencies          Person             people

    Diagnosis           diagnoses             Quantity           quantities

    Batch               batches               Datum              data

    默认的,Active Record的表名是复数的,类名是单数的,如果你不太习惯,可以通过设置一个全局标记来禁用它,在config目录的environment.rb文件中设置:

    ActiveRecord::Base.pluralize_table_names = false
    

    单复数规则可以对付大部分情况,对于一些特殊情况,Active Record允许我们覆盖默认的生成的表名,使用set_table_name命令,例如:

    class Sheep < ActiveRecord::Base
    
    set_table_name "sheep" # Not "sheeps"
    
    end
    
    class Order < ActiveRecord::Base
    
    set_table_name "ord_rev99_x" # Wrap a legacy table...
    
    end
    

     Active Record抽象了数据库连接的概念,帮助应用程序来处理底层的数据库链接的细节,作为替代,Active Record使用通用的调用,将细节委托给一组数据库适配器。

      可以使用establish_connection( )方法来制定连接,下面的例子创建了一个mysql数据库连接,数据库的名字是railsdb,服务器的Host名为dbserver.com,用户名为railsuser,密码为railspw。

    ActiveRecord::Base.establish_connection(
    :adapter => "mysql",
    :host => "dbserver.com",
    :database => "railsdb",
    :username => "railsuser",
    :password => "railspw"
    )
    
    

      Active Record支持DB2,MySql,Oracle,Postgres,SqlServer,以及SqlLite,每一种数据库适配器在链接的参数上都有一些细小的差别,下表列出了常用的参数:

    Ruby on rails开发从头来(四十三)- ActiveRecord基础(连接数据库)

      注意Oracle适配器的名字为oci。

      数据库连接和Model类是关联的,每个类都从父类那里继承了链接,ActiveRecord::Base作为所有的Active Record类的父类,设置这里的数据库连接就给所有的活动记录类设置了链接,当然,如果需要的话,你也可以复写(override)链接配置。

      下面的例子里,我们的大多数表都在MySql数据库中,库名为online,由于一些历史原因,customers表在名为backend的数据库中,

    ActiveRecord::Base.establish_connection(
    :adapter => "mysql",
    :host => "dbserver.com",
    :database => "online",
    :username => "groucho",
    :password => "swordfish")
    class LineItem < ActiveRecord::Base
    # ...
    end
    class Order < ActiveRecord::Base
    # ...
    end
    class Product < ActiveRecord::Base
    # ...
    end
    class Customer < ActiveRecord::Base
    # ...
    end
    Customer.establish_connection(
    :adapter => "mysql",
    :host => "dbserver.com",
    :database => "backend",
    :username => "chicho",
    :password => "piano")
    
    

      在我们前面所写的depot程序中,我们没有使用establish_connection方法,而是在config/database.yaml文件中指定了数据库连接的参数信息,对于大多数rails程序来说,这是首选的方式,不仅因为将配置信息和代码分离,而且在测试和部署时也能带来方便,上面的表格里列出的参数都可以应用在YAML文件中,这一点我们在前面的配置文件一节已经有介绍。

      最后,如果你通过一个标记访问establish_connection(),Rails会在database.yaml文件中查找名字对应的配置节,来获取链接的参数,这样就可以将所有的数据库连接配置从代码中分离出来。

    config = YAML::load(File.open('config/database.yml'))
        ActiveRecord::Base.establish_connection(config["production"]) 
    
  • 相关阅读:
    python基础(str,list,tuple)
    MySQL数据类型概念
    Ubuntu安装sublime
    Ubuntu安装pycharm
    ubuntu安装mysql
    微信小程序注册开发流程
    新开篇
    被玩坏了的题——马的遍历
    一道数学恶心题——小凯的疑惑
    搜索基础题:八皇后
  • 原文地址:https://www.cnblogs.com/mingforyou/p/2768303.html
Copyright © 2011-2022 走看看