Class: ActiveRecord::Base

Inherits:
Object
  • Object
show all
Defined in:
lib/active_record/locking.rb,
lib/active_record/timestamp.rb,
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/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

@@lock_optimistically =
true
@@record_timestamps =

Records the creation date and possibly time in created_on (date only) or created_at (date and time) and the update date and possibly time in updated_on and updated_at. This only happens if the object responds to either of these messages, which they will do automatically if the table has columns of either of these names. This feature is turned on by default.

true
@@timestamps_gmt =

deprecated: use ActiveRecord::Base.default_timezone instead.

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

.connected?Boolean

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

Returns:

  • (Boolean)


229
230
231
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 229

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.



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

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.



181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 181

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

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]


35
36
37
38
# File 'lib/active_record/deprecated_finders.rb', line 35

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

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"


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

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

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:



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

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 = config.symbolize_keys
  unless config.has_key?(:database)
    raise ArgumentError, "No database specified. Missing argument: database."
  end
  options = config[:charset] ? { CHARACTER_SET => config[:charset] } : {}
  connection_params = [config[:username], config[:password], options]
  db = FireRuby::Database.new_from_params(*config.values_at(:database, :host, :port, :service))
  connection = db.connect(*connection_params)
  ConnectionAdapters::FirebirdAdapter.new(connection, logger, connection_params)
end

.locking_columnObject

:nodoc:



67
68
69
# File 'lib/active_record/locking.rb', line 67

def locking_column #:nodoc:
  reset_locking_column
end

.log_connectionsObject

connection state logging



260
261
262
263
264
265
266
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 260

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.



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
33
34
35
36
37
38
# File 'lib/active_record/connection_adapters/mysql_adapter.rb', line 6

def self.mysql_connection(config) # :nodoc:
  # Only 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
      # Only use the supplied backup 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


  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

  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 unless host.nil?
  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.



237
238
239
240
241
242
243
244
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 237

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

.reset_locking_columnObject

:nodoc:



71
72
73
74
75
# File 'lib/active_record/locking.rb', line 71

def reset_locking_column #:nodoc:
  default = 'lock_version'
  set_locking_column(default)
  default
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).



210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 210

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

.set_locking_column(value = nil, &block) ⇒ Object



63
64
65
# File 'lib/active_record/locking.rb', line 63

def set_locking_column(value = nil, &block)
  define_attr_method :locking_column, value, &block
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
# 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
  )
  ConnectionAdapters::SQLiteAdapter.new(db, logger)
end

.sqlite_connection(config) ⇒ Object

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



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

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:



22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
# File 'lib/active_record/connection_adapters/sqlserver_adapter.rb', line 22

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

.timestamps_gmtObject

:nodoc:



57
58
59
60
# File 'lib/active_record/timestamp.rb', line 57

def self.timestamps_gmt #:nodoc:
  warn "timestamps_gmt is deprecated. use default_timezone instead"
  self.default_timezone == :utc
end

.timestamps_gmt=(gmt) ⇒ Object

:nodoc:



52
53
54
55
# File 'lib/active_record/timestamp.rb', line 52

def self.timestamps_gmt=( gmt ) #:nodoc:
  warn "timestamps_gmt= is deprecated. use default_timezone= instead"
  self.default_timezone = ( gmt ? :utc : :local )
end

.verify_active_connections!Object

Verify active connections.



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

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.



150
151
152
# File 'lib/active_record/connection_adapters/abstract/connection_specification.rb', line 150

def connection
  self.class.connection
end

#locking_enabled?Boolean

:nodoc:

Returns:

  • (Boolean)


58
59
60
# File 'lib/active_record/locking.rb', line 58

def locking_enabled? #:nodoc:
  lock_optimistically && respond_to?(self.class.locking_column)
end