activerecord 2.1.2 → 2.2.2
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +32 -6
- data/README +0 -0
- data/Rakefile +4 -5
- data/lib/active_record.rb +11 -10
- data/lib/active_record/aggregations.rb +110 -38
- data/lib/active_record/association_preload.rb +104 -15
- data/lib/active_record/associations.rb +427 -212
- data/lib/active_record/associations/association_collection.rb +101 -16
- data/lib/active_record/associations/association_proxy.rb +65 -13
- data/lib/active_record/associations/belongs_to_association.rb +2 -2
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +13 -3
- data/lib/active_record/associations/has_many_association.rb +28 -28
- data/lib/active_record/associations/has_many_through_association.rb +21 -19
- data/lib/active_record/associations/has_one_association.rb +24 -7
- data/lib/active_record/associations/has_one_through_association.rb +3 -4
- data/lib/active_record/attribute_methods.rb +13 -5
- data/lib/active_record/base.rb +435 -212
- data/lib/active_record/calculations.rb +12 -5
- data/lib/active_record/callbacks.rb +28 -9
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +355 -0
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +42 -215
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +30 -5
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +2 -1
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +48 -7
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +10 -4
- data/lib/active_record/connection_adapters/abstract_adapter.rb +67 -26
- data/lib/active_record/connection_adapters/mysql_adapter.rb +71 -45
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +155 -84
- data/lib/active_record/dirty.rb +25 -7
- data/lib/active_record/dynamic_finder_match.rb +41 -0
- data/lib/active_record/fixtures.rb +10 -9
- data/lib/active_record/i18n_interpolation_deprecation.rb +26 -0
- data/lib/active_record/locale/en.yml +54 -0
- data/lib/active_record/migration.rb +47 -10
- data/lib/active_record/named_scope.rb +29 -16
- data/lib/active_record/reflection.rb +118 -54
- data/lib/active_record/schema_dumper.rb +13 -7
- data/lib/active_record/test_case.rb +18 -5
- data/lib/active_record/transactions.rb +89 -34
- data/lib/active_record/validations.rb +270 -180
- data/lib/active_record/version.rb +1 -1
- data/test/cases/active_schema_test_mysql.rb +5 -0
- data/test/cases/adapter_test.rb +6 -0
- data/test/cases/aggregations_test.rb +39 -0
- data/test/cases/associations/belongs_to_associations_test.rb +10 -0
- data/test/cases/associations/eager_load_nested_include_test.rb +30 -12
- data/test/cases/associations/eager_test.rb +54 -5
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +77 -10
- data/test/cases/associations/has_many_associations_test.rb +74 -7
- data/test/cases/associations/has_many_through_associations_test.rb +50 -3
- data/test/cases/associations/has_one_associations_test.rb +17 -0
- data/test/cases/associations/has_one_through_associations_test.rb +49 -1
- data/test/cases/associations_test.rb +0 -0
- data/test/cases/attribute_methods_test.rb +59 -4
- data/test/cases/base_test.rb +93 -21
- data/test/cases/binary_test.rb +1 -5
- data/test/cases/calculations_test.rb +5 -0
- data/test/cases/callbacks_observers_test.rb +38 -0
- data/test/cases/connection_test_mysql.rb +1 -1
- data/test/cases/defaults_test.rb +32 -1
- data/test/cases/deprecated_finder_test.rb +0 -0
- data/test/cases/dirty_test.rb +13 -0
- data/test/cases/finder_test.rb +162 -12
- data/test/cases/fixtures_test.rb +32 -3
- data/test/cases/helper.rb +15 -0
- data/test/cases/i18n_test.rb +41 -0
- data/test/cases/inheritance_test.rb +2 -2
- data/test/cases/lifecycle_test.rb +0 -0
- data/test/cases/locking_test.rb +4 -9
- data/test/cases/method_scoping_test.rb +109 -2
- data/test/cases/migration_test.rb +43 -8
- data/test/cases/multiple_db_test.rb +25 -0
- data/test/cases/named_scope_test.rb +74 -0
- data/test/cases/pooled_connections_test.rb +103 -0
- data/test/cases/readonly_test.rb +0 -0
- data/test/cases/reflection_test.rb +11 -3
- data/test/cases/reload_models_test.rb +20 -0
- data/test/cases/sanitize_test.rb +25 -0
- data/test/cases/schema_authorization_test_postgresql.rb +2 -2
- data/test/cases/transactions_test.rb +62 -12
- data/test/cases/unconnected_test.rb +0 -0
- data/test/cases/validations_i18n_test.rb +921 -0
- data/test/cases/validations_test.rb +44 -33
- data/test/connections/native_mysql/connection.rb +1 -3
- data/test/fixtures/companies.yml +1 -0
- data/test/fixtures/customers.yml +10 -1
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/organizations.yml +5 -0
- data/test/migrations/broken/100_migration_that_raises_exception.rb +10 -0
- data/test/models/author.rb +3 -0
- data/test/models/category.rb +3 -0
- data/test/models/club.rb +6 -0
- data/test/models/company.rb +25 -1
- data/test/models/customer.rb +19 -1
- data/test/models/member.rb +2 -0
- data/test/models/member_detail.rb +4 -0
- data/test/models/organization.rb +4 -0
- data/test/models/parrot.rb +1 -0
- data/test/models/post.rb +3 -0
- data/test/models/reply.rb +0 -0
- data/test/models/topic.rb +3 -0
- data/test/schema/schema.rb +12 -1
- metadata +22 -10
- data/lib/active_record/vendor/mysql.rb +0 -1214
- data/test/cases/adapter_test_sqlserver.rb +0 -95
- data/test/cases/table_name_test_sqlserver.rb +0 -23
- data/test/cases/threaded_connections_test.rb +0 -48
- data/test/schema/sqlserver_specific_schema.rb +0 -5
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'set'
|
2
|
-
|
3
1
|
module ActiveRecord
|
4
2
|
class Base
|
5
3
|
class ConnectionSpecification #:nodoc:
|
@@ -9,163 +7,9 @@ module ActiveRecord
|
|
9
7
|
end
|
10
8
|
end
|
11
9
|
|
12
|
-
#
|
13
|
-
|
14
|
-
|
15
|
-
@@verification_timeout = 0
|
16
|
-
|
17
|
-
# The class -> [adapter_method, config] map
|
18
|
-
@@defined_connections = {}
|
19
|
-
|
20
|
-
# The class -> thread id -> adapter cache. (class -> adapter if not allow_concurrency)
|
21
|
-
@@active_connections = {}
|
22
|
-
|
23
|
-
class << self
|
24
|
-
# Retrieve the connection cache.
|
25
|
-
def thread_safe_active_connections #:nodoc:
|
26
|
-
@@active_connections[Thread.current.object_id] ||= {}
|
27
|
-
end
|
28
|
-
|
29
|
-
def single_threaded_active_connections #:nodoc:
|
30
|
-
@@active_connections
|
31
|
-
end
|
32
|
-
|
33
|
-
# pick up the right active_connection method from @@allow_concurrency
|
34
|
-
if @@allow_concurrency
|
35
|
-
alias_method :active_connections, :thread_safe_active_connections
|
36
|
-
else
|
37
|
-
alias_method :active_connections, :single_threaded_active_connections
|
38
|
-
end
|
39
|
-
|
40
|
-
# set concurrency support flag (not thread safe, like most of the methods in this file)
|
41
|
-
def allow_concurrency=(threaded) #:nodoc:
|
42
|
-
logger.debug "allow_concurrency=#{threaded}" if logger
|
43
|
-
return if @@allow_concurrency == threaded
|
44
|
-
clear_all_cached_connections!
|
45
|
-
@@allow_concurrency = threaded
|
46
|
-
method_prefix = threaded ? "thread_safe" : "single_threaded"
|
47
|
-
sing = (class << self; self; end)
|
48
|
-
[:active_connections, :scoped_methods].each do |method|
|
49
|
-
sing.send(:alias_method, method, "#{method_prefix}_#{method}")
|
50
|
-
end
|
51
|
-
log_connections if logger
|
52
|
-
end
|
53
|
-
|
54
|
-
def active_connection_name #:nodoc:
|
55
|
-
@active_connection_name ||=
|
56
|
-
if active_connections[name] || @@defined_connections[name]
|
57
|
-
name
|
58
|
-
elsif self == ActiveRecord::Base
|
59
|
-
nil
|
60
|
-
else
|
61
|
-
superclass.active_connection_name
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def clear_active_connection_name #:nodoc:
|
66
|
-
@active_connection_name = nil
|
67
|
-
subclasses.each { |klass| klass.clear_active_connection_name }
|
68
|
-
end
|
69
|
-
|
70
|
-
# Returns the connection currently associated with the class. This can
|
71
|
-
# also be used to "borrow" the connection to do database work unrelated
|
72
|
-
# to any of the specific Active Records.
|
73
|
-
def connection
|
74
|
-
if defined?(@active_connection_name) && (conn = active_connections[@active_connection_name])
|
75
|
-
conn
|
76
|
-
else
|
77
|
-
# retrieve_connection sets the cache key.
|
78
|
-
conn = retrieve_connection
|
79
|
-
active_connections[@active_connection_name] = conn
|
80
|
-
end
|
81
|
-
end
|
82
|
-
|
83
|
-
# Clears the cache which maps classes to connections.
|
84
|
-
def clear_active_connections!
|
85
|
-
clear_cache!(@@active_connections) do |name, conn|
|
86
|
-
conn.disconnect!
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
# Clears the cache which maps classes
|
91
|
-
def clear_reloadable_connections!
|
92
|
-
if @@allow_concurrency
|
93
|
-
# With concurrent connections @@active_connections is
|
94
|
-
# a hash keyed by thread id.
|
95
|
-
@@active_connections.each do |thread_id, conns|
|
96
|
-
conns.each do |name, conn|
|
97
|
-
if conn.requires_reloading?
|
98
|
-
conn.disconnect!
|
99
|
-
@@active_connections[thread_id].delete(name)
|
100
|
-
end
|
101
|
-
end
|
102
|
-
end
|
103
|
-
else
|
104
|
-
@@active_connections.each do |name, conn|
|
105
|
-
if conn.requires_reloading?
|
106
|
-
conn.disconnect!
|
107
|
-
@@active_connections.delete(name)
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
|
113
|
-
# Verify active connections.
|
114
|
-
def verify_active_connections! #:nodoc:
|
115
|
-
if @@allow_concurrency
|
116
|
-
remove_stale_cached_threads!(@@active_connections) do |name, conn|
|
117
|
-
conn.disconnect!
|
118
|
-
end
|
119
|
-
end
|
120
|
-
|
121
|
-
active_connections.each_value do |connection|
|
122
|
-
connection.verify!(@@verification_timeout)
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
private
|
127
|
-
def clear_cache!(cache, thread_id = nil, &block)
|
128
|
-
if cache
|
129
|
-
if @@allow_concurrency
|
130
|
-
thread_id ||= Thread.current.object_id
|
131
|
-
thread_cache, cache = cache, cache[thread_id]
|
132
|
-
return unless cache
|
133
|
-
end
|
134
|
-
|
135
|
-
cache.each(&block) if block_given?
|
136
|
-
cache.clear
|
137
|
-
end
|
138
|
-
ensure
|
139
|
-
if thread_cache && @@allow_concurrency
|
140
|
-
thread_cache.delete(thread_id)
|
141
|
-
end
|
142
|
-
end
|
143
|
-
|
144
|
-
# Remove stale threads from the cache.
|
145
|
-
def remove_stale_cached_threads!(cache, &block)
|
146
|
-
stale = Set.new(cache.keys)
|
147
|
-
|
148
|
-
Thread.list.each do |thread|
|
149
|
-
stale.delete(thread.object_id) if thread.alive?
|
150
|
-
end
|
151
|
-
|
152
|
-
stale.each do |thread_id|
|
153
|
-
clear_cache!(cache, thread_id, &block)
|
154
|
-
end
|
155
|
-
end
|
156
|
-
|
157
|
-
def clear_all_cached_connections!
|
158
|
-
if @@allow_concurrency
|
159
|
-
@@active_connections.each_value do |connection_hash_for_thread|
|
160
|
-
connection_hash_for_thread.each_value {|conn| conn.disconnect! }
|
161
|
-
connection_hash_for_thread.clear
|
162
|
-
end
|
163
|
-
else
|
164
|
-
@@active_connections.each_value {|conn| conn.disconnect! }
|
165
|
-
end
|
166
|
-
@@active_connections.clear
|
167
|
-
end
|
168
|
-
end
|
10
|
+
# The connection handler
|
11
|
+
cattr_accessor :connection_handler, :instance_writer => false
|
12
|
+
@@connection_handler = ConnectionAdapters::ConnectionHandler.new
|
169
13
|
|
170
14
|
# Returns the connection currently associated with the class. This can
|
171
15
|
# also be used to "borrow" the connection to do database work that isn't
|
@@ -208,9 +52,7 @@ module ActiveRecord
|
|
208
52
|
raise AdapterNotSpecified unless defined? RAILS_ENV
|
209
53
|
establish_connection(RAILS_ENV)
|
210
54
|
when ConnectionSpecification
|
211
|
-
|
212
|
-
@active_connection_name = name
|
213
|
-
@@defined_connections[name] = spec
|
55
|
+
@@connection_handler.establish_connection(name, spec)
|
214
56
|
when Symbol, String
|
215
57
|
if configuration = configurations[spec.to_s]
|
216
58
|
establish_connection(configuration)
|
@@ -243,67 +85,52 @@ module ActiveRecord
|
|
243
85
|
end
|
244
86
|
end
|
245
87
|
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
def self.retrieve_connection #:nodoc:
|
251
|
-
# Name is nil if establish_connection hasn't been called for
|
252
|
-
# some class along the inheritance chain up to AR::Base yet.
|
253
|
-
if name = active_connection_name
|
254
|
-
if conn = active_connections[name]
|
255
|
-
# Verify the connection.
|
256
|
-
conn.verify!(@@verification_timeout)
|
257
|
-
elsif spec = @@defined_connections[name]
|
258
|
-
# Activate this connection specification.
|
259
|
-
klass = name.constantize
|
260
|
-
klass.connection = spec
|
261
|
-
conn = active_connections[name]
|
262
|
-
end
|
88
|
+
class << self
|
89
|
+
# Deprecated and no longer has any effect.
|
90
|
+
def allow_concurrency
|
91
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_concurrency has been deprecated and no longer has any effect. Please remove all references to allow_concurrency.")
|
263
92
|
end
|
264
93
|
|
265
|
-
|
266
|
-
|
94
|
+
# Deprecated and no longer has any effect.
|
95
|
+
def allow_concurrency=(flag)
|
96
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.allow_concurrency= has been deprecated and no longer has any effect. Please remove all references to allow_concurrency=.")
|
97
|
+
end
|
267
98
|
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
99
|
+
# Deprecated and no longer has any effect.
|
100
|
+
def verification_timeout
|
101
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout has been deprecated and no longer has any effect. Please remove all references to verification_timeout.")
|
102
|
+
end
|
272
103
|
|
273
|
-
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
def self.remove_connection(klass=self)
|
278
|
-
spec = @@defined_connections[klass.name]
|
279
|
-
konn = active_connections[klass.name]
|
280
|
-
@@defined_connections.delete_if { |key, value| value == spec }
|
281
|
-
active_connections.delete_if { |key, value| value == konn }
|
282
|
-
konn.disconnect! if konn
|
283
|
-
spec.config if spec
|
284
|
-
end
|
104
|
+
# Deprecated and no longer has any effect.
|
105
|
+
def verification_timeout=(flag)
|
106
|
+
ActiveSupport::Deprecation.warn("ActiveRecord::Base.verification_timeout= has been deprecated and no longer has any effect. Please remove all references to verification_timeout=.")
|
107
|
+
end
|
285
108
|
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
config = spec.config.reverse_merge(:allow_concurrency => @@allow_concurrency)
|
292
|
-
self.connection = self.send(spec.adapter_method, config)
|
293
|
-
elsif spec.nil?
|
294
|
-
raise ConnectionNotEstablished
|
295
|
-
else
|
296
|
-
establish_connection spec
|
109
|
+
# Returns the connection currently associated with the class. This can
|
110
|
+
# also be used to "borrow" the connection to do database work unrelated
|
111
|
+
# to any of the specific Active Records.
|
112
|
+
def connection
|
113
|
+
retrieve_connection
|
297
114
|
end
|
298
|
-
end
|
299
115
|
|
300
|
-
|
301
|
-
|
302
|
-
if logger
|
303
|
-
logger.info "Defined connections: #{@@defined_connections.inspect}"
|
304
|
-
logger.info "Active connections: #{active_connections.inspect}"
|
305
|
-
logger.info "Active connection name: #{@active_connection_name}"
|
116
|
+
def connection_pool
|
117
|
+
connection_handler.retrieve_connection_pool(self)
|
306
118
|
end
|
119
|
+
|
120
|
+
def retrieve_connection
|
121
|
+
connection_handler.retrieve_connection(self)
|
122
|
+
end
|
123
|
+
|
124
|
+
def connected?
|
125
|
+
connection_handler.connected?(self)
|
126
|
+
end
|
127
|
+
|
128
|
+
def remove_connection(klass = self)
|
129
|
+
connection_handler.remove_connection(klass)
|
130
|
+
end
|
131
|
+
|
132
|
+
delegate :clear_active_connections!, :clear_reloadable_connections!,
|
133
|
+
:clear_all_connections!,:verify_active_connections!, :to => :connection_handler
|
307
134
|
end
|
308
135
|
end
|
309
136
|
end
|
@@ -98,8 +98,14 @@ module ActiveRecord
|
|
98
98
|
add_limit_offset!(sql, options) if options
|
99
99
|
end
|
100
100
|
|
101
|
-
# Appends +LIMIT+ and +OFFSET+ options to an SQL statement
|
101
|
+
# Appends +LIMIT+ and +OFFSET+ options to an SQL statement, or some SQL
|
102
|
+
# fragment that has the same semantics as LIMIT and OFFSET.
|
103
|
+
#
|
104
|
+
# +options+ must be a Hash which contains a +:limit+ option (required)
|
105
|
+
# and an +:offset+ option (optional).
|
106
|
+
#
|
102
107
|
# This method *modifies* the +sql+ parameter.
|
108
|
+
#
|
103
109
|
# ===== Examples
|
104
110
|
# add_limit_offset!('SELECT * FROM suppliers', {:limit => 10, :offset => 50})
|
105
111
|
# generates
|
@@ -114,10 +120,6 @@ module ActiveRecord
|
|
114
120
|
sql
|
115
121
|
end
|
116
122
|
|
117
|
-
def sanitize_limit(limit)
|
118
|
-
limit.to_s[/,/] ? limit.split(',').map{ |i| i.to_i }.join(',') : limit.to_i
|
119
|
-
end
|
120
|
-
|
121
123
|
# Appends a locking clause to an SQL statement.
|
122
124
|
# This method *modifies* the +sql+ parameter.
|
123
125
|
# # SELECT * FROM suppliers FOR UPDATE
|
@@ -149,6 +151,14 @@ module ActiveRecord
|
|
149
151
|
"INSERT INTO #{quote_table_name(table_name)} VALUES(DEFAULT)"
|
150
152
|
end
|
151
153
|
|
154
|
+
def case_sensitive_equality_operator
|
155
|
+
"="
|
156
|
+
end
|
157
|
+
|
158
|
+
def limited_update_conditions(where_sql, quoted_table_name, quoted_primary_key)
|
159
|
+
"WHERE #{quoted_primary_key} IN (SELECT #{quoted_primary_key} FROM #{quoted_table_name} #{where_sql})"
|
160
|
+
end
|
161
|
+
|
152
162
|
protected
|
153
163
|
# Returns an array of record hashes with the column names as keys and
|
154
164
|
# column values as values.
|
@@ -171,6 +181,21 @@ module ActiveRecord
|
|
171
181
|
def delete_sql(sql, name = nil)
|
172
182
|
update_sql(sql, name)
|
173
183
|
end
|
184
|
+
|
185
|
+
# Sanitizes the given LIMIT parameter in order to prevent SQL injection.
|
186
|
+
#
|
187
|
+
# +limit+ may be anything that can evaluate to a string via #to_s. It
|
188
|
+
# should look like an integer, or a comma-delimited list of integers.
|
189
|
+
#
|
190
|
+
# Returns the sanitized limit parameter, either as an integer, or as a
|
191
|
+
# string which contains a comma-delimited list of integers.
|
192
|
+
def sanitize_limit(limit)
|
193
|
+
if limit.to_s =~ /,/
|
194
|
+
limit.to_s.split(',').map{ |i| i.to_i }.join(',')
|
195
|
+
else
|
196
|
+
limit.to_i
|
197
|
+
end
|
198
|
+
end
|
174
199
|
end
|
175
200
|
end
|
176
201
|
end
|
@@ -4,7 +4,6 @@ module ActiveRecord
|
|
4
4
|
class << self
|
5
5
|
def included(base)
|
6
6
|
base.class_eval do
|
7
|
-
attr_accessor :query_cache_enabled
|
8
7
|
alias_method_chain :columns, :query_cache
|
9
8
|
alias_method_chain :select_all, :query_cache
|
10
9
|
end
|
@@ -26,6 +25,8 @@ module ActiveRecord
|
|
26
25
|
end
|
27
26
|
end
|
28
27
|
|
28
|
+
attr_reader :query_cache, :query_cache_enabled
|
29
|
+
|
29
30
|
# Enable the query cache within the block.
|
30
31
|
def cache
|
31
32
|
old, @query_cache_enabled = @query_cache_enabled, true
|
@@ -1,4 +1,5 @@
|
|
1
1
|
require 'date'
|
2
|
+
require 'set'
|
2
3
|
require 'bigdecimal'
|
3
4
|
require 'bigdecimal/util'
|
4
5
|
|
@@ -6,6 +7,8 @@ module ActiveRecord
|
|
6
7
|
module ConnectionAdapters #:nodoc:
|
7
8
|
# An abstract definition of a column in a table.
|
8
9
|
class Column
|
10
|
+
TRUE_VALUES = [true, 1, '1', 't', 'T', 'true', 'TRUE'].to_set
|
11
|
+
|
9
12
|
module Format
|
10
13
|
ISO_DATE = /\A(\d{4})-(\d\d)-(\d\d)\z/
|
11
14
|
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
|
@@ -30,11 +33,15 @@ module ActiveRecord
|
|
30
33
|
end
|
31
34
|
|
32
35
|
def text?
|
33
|
-
|
36
|
+
type == :string || type == :text
|
34
37
|
end
|
35
38
|
|
36
39
|
def number?
|
37
|
-
|
40
|
+
type == :integer || type == :float || type == :decimal
|
41
|
+
end
|
42
|
+
|
43
|
+
def has_default?
|
44
|
+
!default.nil?
|
38
45
|
end
|
39
46
|
|
40
47
|
# Returns the Ruby class that corresponds to the abstract data type.
|
@@ -135,10 +142,10 @@ module ActiveRecord
|
|
135
142
|
|
136
143
|
# convert something to a boolean
|
137
144
|
def value_to_boolean(value)
|
138
|
-
if value
|
139
|
-
|
145
|
+
if value.is_a?(String) && value.blank?
|
146
|
+
nil
|
140
147
|
else
|
141
|
-
|
148
|
+
TRUE_VALUES.include?(value)
|
142
149
|
end
|
143
150
|
end
|
144
151
|
|
@@ -249,6 +256,10 @@ module ActiveRecord
|
|
249
256
|
class IndexDefinition < Struct.new(:table, :name, :unique, :columns) #:nodoc:
|
250
257
|
end
|
251
258
|
|
259
|
+
# Abstract representation of a column definition. Instances of this type
|
260
|
+
# are typically created by methods in TableDefinition, and added to the
|
261
|
+
# +columns+ attribute of said TableDefinition object, in order to be used
|
262
|
+
# for generating a number of table creation or table changing SQL statements.
|
252
263
|
class ColumnDefinition < Struct.new(:base, :name, :type, :limit, :precision, :scale, :default, :null) #:nodoc:
|
253
264
|
|
254
265
|
def sql_type
|
@@ -272,9 +283,29 @@ module ActiveRecord
|
|
272
283
|
end
|
273
284
|
end
|
274
285
|
|
275
|
-
# Represents
|
276
|
-
#
|
286
|
+
# Represents the schema of an SQL table in an abstract way. This class
|
287
|
+
# provides methods for manipulating the schema representation.
|
288
|
+
#
|
289
|
+
# Inside migration files, the +t+ object in +create_table+ and
|
290
|
+
# +change_table+ is actually of this type:
|
291
|
+
#
|
292
|
+
# class SomeMigration < ActiveRecord::Migration
|
293
|
+
# def self.up
|
294
|
+
# create_table :foo do |t|
|
295
|
+
# puts t.class # => "ActiveRecord::ConnectionAdapters::TableDefinition"
|
296
|
+
# end
|
297
|
+
# end
|
298
|
+
#
|
299
|
+
# def self.down
|
300
|
+
# ...
|
301
|
+
# end
|
302
|
+
# end
|
303
|
+
#
|
304
|
+
# The table definitions
|
305
|
+
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
277
306
|
class TableDefinition
|
307
|
+
# An array of ColumnDefinition objects, representing the column changes
|
308
|
+
# that have been defined.
|
278
309
|
attr_accessor :columns
|
279
310
|
|
280
311
|
def initialize(base)
|
@@ -318,6 +349,12 @@ module ActiveRecord
|
|
318
349
|
# * <tt>:scale</tt> -
|
319
350
|
# Specifies the scale for a <tt>:decimal</tt> column.
|
320
351
|
#
|
352
|
+
# For clarity's sake: the precision is the number of significant digits,
|
353
|
+
# while the scale is the number of digits that can be stored following
|
354
|
+
# the decimal point. For example, the number 123.45 has a precision of 5
|
355
|
+
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
356
|
+
# range from -999.99 to 999.99.
|
357
|
+
#
|
321
358
|
# Please be aware of different RDBMS implementations behavior with
|
322
359
|
# <tt>:decimal</tt> columns:
|
323
360
|
# * The SQL standard says the default scale should be 0, <tt>:scale</tt> <=
|
@@ -371,6 +408,10 @@ module ActiveRecord
|
|
371
408
|
# td.column(:huge_integer, :decimal, :precision => 30)
|
372
409
|
# # => huge_integer DECIMAL(30)
|
373
410
|
#
|
411
|
+
# # Defines a column with a database-specific type.
|
412
|
+
# td.column(:foo, 'polygon')
|
413
|
+
# # => foo polygon
|
414
|
+
#
|
374
415
|
# == Short-hand examples
|
375
416
|
#
|
376
417
|
# Instead of calling +column+ directly, you can also work with the short-hand definitions for the default types.
|