Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/query_cache.rb,
lib/active_record/deprecated_finders.rb,
lib/active_record/connection_adapters/mysql_adapter.rb,
lib/active_record/connection_adapters/sqlite_adapter.rb,
lib/active_record/connection_adapters/openbase_adapter.rb,
lib/active_record/connection_adapters/frontbase_adapter.rb,
lib/active_record/connection_adapters/sqlserver_adapter.rb,
lib/active_record/connection_adapters/postgresql_adapter.rb,
lib/active_record/connection_adapters/abstract/connection_specification.rb

Defined Under Namespace

Classes: ConnectionSpecification

Constant Summary collapse

@@verification_timeout =
0
@@defined_connections =

The class -> [adapter_method, config] map

{}
@@active_connections =

The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency)

{}

Class Method Summary collapse

Instance Method Summary collapse

Class Method Details

.active_connection_nameObject

:nodoc:



54
55
56
57
58
59
60
61
62
63
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 54

def active_connection_name #:nodoc:
  @active_connection_name ||=
     if active_connections[name] || @@defined_connections[name]
       name
     elsif self == ActiveRecord::Base
       nil
     else
       superclass.active_connection_name
     end
end

.allow_concurrency=(threaded) ⇒ Object

set concurrency support flag (not thread safe, like most of the methods in this file)



41
42
43
44
45
46
47
48
49
50
51
52
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 41

def allow_concurrency=(threaded) #:nodoc:
  logger.debug "allow_concurrency=#{threaded}" if logger
  return if @@allow_concurrency == threaded
  clear_all_cached_connections!
  @@allow_concurrency = threaded
  method_prefix = threaded ? "thread_safe" : "single_threaded"
  sing = (class << self; self; end)
  [:active_connections, :scoped_methods].each do |method|
    sing.send(:alias_method, method, "#{method_prefix}_#{method}")
  end
  log_connections if logger
end

.clear_active_connection_nameObject

:nodoc:



65
66
67
68
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 65

def clear_active_connection_name #:nodoc:
  @active_connection_name = nil
  subclasses.each { |klass| klass.clear_active_connection_name }
end

.clear_active_connections!Object

Clears the cache which maps classes to connections.



84
85
86
87
88
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 84

def clear_active_connections!
  clear_cache!(@@active_connections) do |name, conn|
    conn.disconnect!
  end
end

.clear_reloadable_connections!Object

Clears the cache which maps classes



91
92
93
94
95
96
97
98
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 91

def clear_reloadable_connections!
  @@active_connections.each do |name, conn|
    if conn.requires_reloading?
      conn.disconnect!
      @@active_connections.delete(name)
    end
  end
end

.connected?Boolean

Returns true if a connection that’s accessible to this class have already been opened.

Returns:

  • (Boolean)


239
240
241
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 239

def self.connected?
  active_connections[active_connection_name] ? true : false
end

.connectionObject

Returns the connection currently associated with the class. This can also be used to “borrow” the connection to do database work unrelated to any of the specific Active Records.



73
74
75
76
77
78
79
80
81
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 73

def connection
  if @active_connection_name && (conn = active_connections[@active_connection_name])
    conn
  else
    # retrieve_connection sets the cache key.
    conn = retrieve_connection
    active_connections[@active_connection_name] = conn
  end
end

.connection=(spec) ⇒ Object

Set the connection for the class.



257
258
259
260
261
262
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 257

def connection=(spec)
  if spec.is_a?(ConnectionSpecification) and spec.config[:query_cache]
    spec = QueryCache.new(self.send(spec.adapter_method, spec.config))
  end
  self.connection_without_query_cache = spec
end

.connection_without_query_cache=Object



48
# File 'lib/active_record/query_cache.rb', line 48

alias_method :connection_without_query_cache=, :connection=

.establish_connection(spec = nil) ⇒ Object

Establishes the connection to the database. Accepts a hash as input where the :adapter key must be specified with the name of a database adapter (in lower-case) example for regular databases (MySQL, Postgresql, etc):

ActiveRecord::Base.establish_connection(
  :adapter  => "mysql",
  :host     => "localhost",
  :username => "myuser",
  :password => "mypass",
  :database => "somedatabase"
)

Example for SQLite database:

ActiveRecord::Base.establish_connection(
  :adapter => "sqlite",
  :database  => "path/to/dbfile"
)

Also accepts keys as strings (for parsing from yaml for example):

ActiveRecord::Base.establish_connection(
  "adapter" => "sqlite",
  "database"  => "path/to/dbfile"
)

The exceptions AdapterNotSpecified, AdapterNotFound and ArgumentError may be returned on an error.



191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 191

def self.establish_connection(spec = nil)
  case spec
    when nil
      raise AdapterNotSpecified unless defined? RAILS_ENV
      establish_connection(RAILS_ENV)
    when ConnectionSpecification
      clear_active_connection_name
      @active_connection_name = name
      @@defined_connections[name] = spec
    when Symbol, String
      if configuration = configurations[spec.to_s]
        establish_connection(configuration)
      else
        raise AdapterNotSpecified, "#{spec} database is not configured"
      end
    else
      spec = spec.symbolize_keys
      unless spec.key?(:adapter) then raise AdapterNotSpecified, "database configuration does not specify adapter" end
      adapter_method = "#{spec[:adapter]}_connection"
      unless respond_to?(adapter_method) then raise AdapterNotFound, "database configuration specifies nonexistent #{spec[:adapter]} adapter" end
      remove_connection
      establish_connection(ConnectionSpecification.new(spec, adapter_method))
  end
end

.find_all(conditions = nil, orderings = nil, limit = nil, joins = nil) ⇒ Object

DEPRECATION NOTICE: This method is deprecated in favor of find(:all, options).

Returns an array of all the objects that could be instantiated from the associated table in the database. The conditions can be used to narrow the selection of objects (WHERE-part), such as by “color = ‘red’”, and arrangement of the selection can be done through orderings (ORDER BY-part), such as by “last_name, first_name DESC”. A maximum of returned objects and their offset can be specified in limit with either just a single integer as the limit or as an array with the first element as the limit, the second as the offset. Examples:

Project.find_all "category = 'accounts'", "last_accessed DESC", 15
Project.find_all ["category = ?", category_name], "created ASC", [15, 20]


37
38
39
40
# File 'lib/active_record/deprecated_finders.rb', line 37

def find_all(conditions = nil, orderings = nil, limit = nil, joins = nil) # :nodoc:
  limit, offset = limit.is_a?(Array) ? limit : [ limit, nil ]
  find(:all, :conditions => conditions, :order => orderings, :joins => joins, :limit => limit, :offset => offset)
end

.find_first(conditions = nil, orderings = nil, joins = nil) ⇒ Object

DEPRECATION NOTICE: This method is deprecated in favor of find(:first, options).

Returns the object for the first record responding to the conditions in conditions, such as “group = ‘master’”. If more than one record is returned from the query, it’s the first that’ll be used to create the object. In such cases, it might be beneficial to also specify orderings, like “income DESC, name”, to control exactly which record is to be used. Example:

Employee.find_first "income > 50000", "income DESC, name"


22
23
24
# File 'lib/active_record/deprecated_finders.rb', line 22

def find_first(conditions = nil, orderings = nil, joins = nil) # :nodoc:
  find(:first, :conditions => conditions, :order => orderings, :joins => joins)
end

.find_on_conditions(ids, conditions) ⇒ Object

DEPRECATION NOTICE: This method is deprecated in favor of find with the :conditions option.

Works like find, but the record matching id must also meet the conditions. RecordNotFound is raised if no record can be found matching the id or meeting the condition. Example:

Person.find_on_conditions 5, "first_name LIKE '%dav%' AND last_name = 'heinemeier'"


10
11
12
# File 'lib/active_record/deprecated_finders.rb', line 10

def find_on_conditions(ids, conditions) # :nodoc:
  find(ids, :conditions => conditions)
end

.firebird_connection(config) ⇒ Object

:nodoc:



26
27
28
29
30
31
32
33
34
35
36
37
38
# File 'lib/active_record/connection_adapters/firebird_adapter.rb', line 26

def firebird_connection(config) # :nodoc:
  require_library_or_gem 'fireruby'
  unless defined? FireRuby::SQLType
    raise AdapterNotFound,
      'The Firebird adapter requires FireRuby version 0.4.0 or greater; you appear ' <<
      'to be running an older version -- please update FireRuby (gem install fireruby).'
  end
  config.symbolize_keys!
  db = FireRuby::Database.new_from_config(config)
  connection_params = config.values_at(:username, :password)
  connection = db.connect(*connection_params)
  ConnectionAdapters::FirebirdAdapter.new(connection, logger, connection_params)
end

.frontbase_connection(config) ⇒ Object

Establishes a connection to the database that’s used by all Active Record objects.



12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/active_record/connection_adapters/frontbase_adapter.rb', line 12

def frontbase_connection(config) # :nodoc:
  # FrontBase only supports one unnamed sequence per table
  define_attr_method(:set_sequence_name, :sequence_name, &Proc.new {|*args| nil})

  config = config.symbolize_keys
  database     = config[:database]
  port         = config[:port]
  host         = config[:host]
  username     = config[:username]
  password     = config[:password]
  dbpassword   = config[:dbpassword]
  session_name = config[:session_name]

  dbpassword = '' if dbpassword.nil?
  
  # Turn off colorization since it makes tail/less output difficult
  self.colorize_logging = false

  require_library_or_gem 'frontbase' unless self.class.const_defined? :FBSQL_Connect
  
  # Check bindings version
  version = "0.0.0"
  version = FBSQL_Connect::FB_BINDINGS_VERSION if defined? FBSQL_Connect::FB_BINDINGS_VERSION
  
  if ActiveRecord::ConnectionAdapters::FrontBaseAdapter.compare_versions(version,"1.0.0") == -1
    raise AdapterNotFound,
      'The FrontBase adapter requires ruby-frontbase version 1.0.0 or greater; you appear ' <<
      "to be running an older version (#{version}) -- please update ruby-frontbase (gem install ruby-frontbase)."
  end
  connection = FBSQL_Connect.connect(host, port, database, username, password, dbpassword, session_name)
  ConnectionAdapters::FrontBaseAdapter.new(connection, logger, [host, port, database, username, password, dbpassword, session_name], config)
end

.log_connectionsObject

connection state logging



271
272
273
274
275
276
277
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 271

def self.log_connections #:nodoc:
  if logger
    logger.info "Defined connections: #{@@defined_connections.inspect}"
    logger.info "Active connections: #{active_connections.inspect}"
    logger.info "Active connection name: #{@active_connection_name}"
  end
end

.mysql_connection(config) ⇒ Object

Establishes a connection to the database that’s used by all Active Record objects.



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 64

def self.mysql_connection(config) # :nodoc:
  config = config.symbolize_keys
  host     = config[:host]
  port     = config[:port]
  socket   = config[:socket]
  username = config[:username] ? config[:username].to_s : 'root'
  password = config[:password].to_s

  if config.has_key?(:database)
    database = config[:database]
  else
    raise ArgumentError, "No database specified. Missing argument: database."
  end

  require_mysql
  mysql = Mysql.init
  mysql.ssl_set(config[:sslkey], config[:sslcert], config[:sslca], config[:sslcapath], config[:sslcipher]) if config[:sslkey]

  ConnectionAdapters::MysqlAdapter.new(mysql, logger, [host, username, password, database, port, socket], config)
end

.openbase_connection(config) ⇒ Object

Establishes a connection to the database that’s used by all Active Record objects



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/active_record/connection_adapters/openbase_adapter.rb', line 6

def self.openbase_connection(config) # :nodoc:
  require_library_or_gem 'openbase' unless self.class.const_defined?(:OpenBase)

  config = config.symbolize_keys
  host     = config[:host]
  username = config[:username].to_s
  password = config[:password].to_s
  

  if config.has_key?(:database)
    database = config[:database]
  else
    raise ArgumentError, "No database specified. Missing argument: database."
  end

  oba = ConnectionAdapters::OpenBaseAdapter.new(
    OpenBase.new(database, host, username, password), logger
  )
  
  oba
end

.postgresql_connection(config) ⇒ Object

Establishes a connection to the database that’s used by all Active Record objects



6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
# File 'lib/active_record/connection_adapters/postgresql_adapter.rb', line 6

def self.postgresql_connection(config) # :nodoc:
  require_library_or_gem 'postgres' unless self.class.const_defined?(:PGconn)

  config = config.symbolize_keys
  host     = config[:host]
  port     = config[:port] || 5432
  username = config[:username].to_s
  password = config[:password].to_s

  min_messages = config[:min_messages]

  if config.has_key?(:database)
    database = config[:database]
  else
    raise ArgumentError, "No database specified. Missing argument: database."
  end

  pga = ConnectionAdapters::PostgreSQLAdapter.new(
    PGconn.connect(host, port, "", "", database, username, password), logger, config
  )

  PGconn.translate_results = false if PGconn.respond_to? :translate_results=

  pga.schema_search_path = config[:schema_search_path] || config[:schema_order]

  pga
end

.remove_connection(klass = self) ⇒ Object

Remove the connection for this class. This will close the active connection and the defined connection (if they exist). The result can be used as argument for establish_connection, for easy re-establishing of the connection.



247
248
249
250
251
252
253
254
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 247

def self.remove_connection(klass=self)
  spec = @@defined_connections[klass.name]
  konn = active_connections[klass.name]
  @@defined_connections.delete_if { |key, value| value == spec }
  active_connections.delete_if { |key, value| value == konn }
  konn.disconnect! if konn
  spec.config if spec
end

.require_mysqlObject



44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 44

def self.require_mysql
  # Include the MySQL driver if one hasn't already been loaded
  unless defined? Mysql
    begin
      require_library_or_gem 'mysql'
    rescue LoadError => cannot_require_mysql
      # Use the bundled Ruby/MySQL driver if no driver is already in place
      begin
        require 'active_record/vendor/mysql'
      rescue LoadError
        raise cannot_require_mysql
      end
    end
  end

  # Define Mysql::Result.all_hashes
  MysqlCompat.define_all_hashes_method!
end

.retrieve_connectionObject

Locate the connection of the nearest super class. This can be an active or defined connections: if it is the latter, it will be opened and set as the active connection for the class it was defined for (not necessarily the current class).



220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 220

def self.retrieve_connection #:nodoc:
  # Name is nil if establish_connection hasn't been called for
  # some class along the inheritance chain up to AR::Base yet.
  if name = active_connection_name
    if conn = active_connections[name]
      # Verify the connection.
      conn.verify!(@@verification_timeout)
    elsif spec = @@defined_connections[name]
      # Activate this connection specification.
      klass = name.constantize
      klass.connection = spec
      conn = active_connections[name]
    end
  end

  conn or raise ConnectionNotEstablished
end

.single_threaded_active_connectionsObject

:nodoc:



29
30
31
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 29

def single_threaded_active_connections #:nodoc:
  @@active_connections
end

.sqlite3_connection(config) ⇒ Object

sqlite3 adapter reuses sqlite_connection.



10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# File 'lib/active_record/connection_adapters/sqlite_adapter.rb', line 10

def sqlite3_connection(config) # :nodoc:
  parse_config!(config)

  unless self.class.const_defined?(:SQLite3)
    require_library_or_gem(config[:adapter])
  end

  db = SQLite3::Database.new(
    config[:database],
    :results_as_hash => true,
    :type_translation => false
  )

  db.busy_timeout(config[:timeout]) unless config[:timeout].nil?

  ConnectionAdapters::SQLite3Adapter.new(db, logger)
end

.sqlite_connection(config) ⇒ Object

Establishes a connection to the database that’s used by all Active Record objects



29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
# File 'lib/active_record/connection_adapters/sqlite_adapter.rb', line 29

def sqlite_connection(config) # :nodoc:
  parse_config!(config)

  unless self.class.const_defined?(:SQLite)
    require_library_or_gem(config[:adapter])

    db = SQLite::Database.new(config[:database], 0)
    db.show_datatypes   = "ON" if !defined? SQLite::Version
    db.results_as_hash  = true if defined? SQLite::Version
    db.type_translation = false

    # "Downgrade" deprecated sqlite API
    if SQLite.const_defined?(:Version)
      ConnectionAdapters::SQLite2Adapter.new(db, logger)
    else
      ConnectionAdapters::DeprecatedSQLiteAdapter.new(db, logger)
    end
  end
end

.sqlserver_connection(config) ⇒ Object

:nodoc:



27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 27

def self.sqlserver_connection(config) #:nodoc:
  require_library_or_gem 'dbi' unless self.class.const_defined?(:DBI)
  
  config = config.symbolize_keys

  mode        = config[:mode] ? config[:mode].to_s.upcase : 'ADO'
  username    = config[:username] ? config[:username].to_s : 'sa'
  password    = config[:password] ? config[:password].to_s : ''
  autocommit  = config.key?(:autocommit) ? config[:autocommit] : true
  if mode == "ODBC"
    raise ArgumentError, "Missing DSN. Argument ':dsn' must be set in order for this adapter to work." unless config.has_key?(:dsn)
    dsn       = config[:dsn]
    driver_url = "DBI:ODBC:#{dsn}"
  else
    raise ArgumentError, "Missing Database. Argument ':database' must be set in order for this adapter to work." unless config.has_key?(:database)
    database  = config[:database]
    host      = config[:host] ? config[:host].to_s : 'localhost'
    driver_url = "DBI:ADO:Provider=SQLOLEDB;Data Source=#{host};Initial Catalog=#{database};User Id=#{username};Password=#{password};"
  end
  conn      = DBI.connect(driver_url, username, password)
  conn["AutoCommit"] = autocommit
  ConnectionAdapters::SQLServerAdapter.new(conn, logger, [driver_url, username, password])
end

.thread_safe_active_connectionsObject

Retrieve the connection cache.



25
26
27
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 25

def thread_safe_active_connections #:nodoc:
  @@active_connections[Thread.current.object_id] ||= {}
end

.verify_active_connections!Object

Verify active connections.



101
102
103
104
105
106
107
108
109
110
111
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 101

def verify_active_connections! #:nodoc:
  if @@allow_concurrency
    remove_stale_cached_threads!(@@active_connections) do |name, conn|
      conn.disconnect!
    end
  end
  
  active_connections.each_value do |connection|
    connection.verify!(@@verification_timeout)
  end
end

Instance Method Details

#connectionObject

Returns the connection currently associated with the class. This can also be used to “borrow” the connection to do database work that isn’t easily done without going straight to SQL.



160
161
162
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 160

def connection
  self.class.connection
end