2011-08-25 18 views
31

Este código fue tomada a partir de ActiveRecord 2.3.14 clase joya ConnectionHandlerestablish_connection obras en ActiveRecord

def establish_connection(name, spec) 
    @connection_pools[name] = ConnectionAdapters::ConnectionPool.new(spec) 
end 

Parece cada vez rubí llama establish_connection en el modelo, es la creación de una nueva agrupación de conexiones.

Mi pregunta:

Si tengo 5 modelos que utilizan establish_connection a la misma base de datos, es lo suficientemente inteligente como rieles para recoger una piscina ya existente en lugar de crear uno nuevo con las mismas credenciales de conexión? ¿Esto también sucede si mis 5 modelos son subclases de alguna clase abstracta que usa establish_connection? ¿Siempre elegirá una conexión del @connection_pools si existe?

Actualización 1

Estoy hablando de un ejemplo concreto. Tienes 5 modelos con 5 conexiones diferentes, cada vez que Rails usa un modelo ejecuta establish_connection. Al observar el código en ActiveRecord, cuando se ejecuta establish_connection, crea un nuevo grupo con conexiones a esa conexión específica. Lo que me pregunto es si cada vez que Rails llama al modelo establish_connection, crea un nuevo grupo o toma el existente.

Ejemplo: accede a mi sitio y ve una lista de productos. Acaba de ejecutar una acción que llama al Product.all, que ejecuta establish_connection en alguna base de datos en Amazon. Luego, llego a la lista de productos, ¿qué sucede? ¿Cojo la conexión establecida o estoy creando un nuevo grupo con esa conexión?

Actualización 2

Mi conjetura es que los primeros carriles de tiempo cargas mis modelos se crean piscinas con diferentes conexiones. Después, cuando uso algunos Model.method, simplemente toma la conexión asociada con el modelo y ejecuta el método.

No estoy seguro de qué sucede cuando 2 modelos tienen dos conexiones iguales (no en la clase abstracta sino en la clase propia). ¿Esto producirá dos grupos de conexiones iguales, o ActiveRecord es lo suficientemente inteligente como para detectar este caso?

+3

BTW, muy buena pregunta. – bor1s

Respuesta

8

Realmente no tiene que llamar al establish_connection en cada modelo. Simplemente puede hacer lo siguiente:

ActiveRecord::Base.establish_connection(
{ :adapter => 'mysql2', 
    :database => 'some_database', 
    :host => 'localhost', 
    :username => 'root', 
    :password => "" } 
) 

y tendrá acceso a la conexión. (Este fragmento de código se ha extraído del código real (excepto el nombre de la base de datos :))).
Pero de acuerdo con la API, creo que Rails no toma la conexión existente de otro modelo (corrígeme si estoy equivocado).
También aquí hay un link to documentation. Puede leer más sobre la conexión allí.
Espero haberlo ayudado un poco.

+0

Ver mi pregunta editada – Filip

+0

Parece que Rails ya ha establecido la conexión – bor1s

+0

Captura, al llamar a los métodos de los modelos, pero en el estado de inicialización cuando solo carga los modelos y ejecuta la conexión de establecer, mirando el código simplemente crea un grupo, no importa si ya existe Las claves en @connection_pool hash son diferentes, pero los valores son los mismos. – Filip

2

Este comentario:

# Check-out a database connection from the pool, indicating that you want 
# to use it. You should call #checkin when you no longer need this. 
# 
# This is done by either returning an existing connection, or by creating 
# a new connection. If the maximum number of connections for this pool has 
# already been reached, but the pool is empty (i.e. they're all being used), 
# then this method will wait until a thread has checked in a connection. 
# The wait time is bounded however: if no connection can be checked out 
# within the timeout specified for this pool, then a ConnectionTimeoutError 
# exception will be raised. 

de: https://github.com/rails/rails/blob/dd944cbf5879e675fff541d1be7c7eb6c3382d01/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb#L242-251

debe explicar la situación

14

AR llama establish_connection sólo una vez, por ActiveRecord :: Base.Todas las subclases usan una conexión.

Puede establecer manualmente la conexión de establecer usted mismo en algunas subclases. Esto es muy conveniente para usar dos bases de datos a la vez, p.

class MyMainUser < ActiveRecord::Base; end 
class MyOtherDb < ActiveRecord::Base; end 
class MyOtherUser < MyOtherDb; end 

MyOtherDb.establish_connection ... 

MyMainUser.first # uses default db 
MyOtherUser.first # uses other db 

Sin embargo, no se pueden hacer consultas que crucen las bases de datos.

+0

Tuve que agregar 'self.abstract_class = true' en la clase MyOtherDb para ejecutar inserciones. De lo contrario, estaba intentando que la tabla 'my_other_dbs' no existiera. – iamprem

Cuestiones relacionadas