activerecord 3.2.22.4 → 4.0.13
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +2799 -617
- data/MIT-LICENSE +1 -1
- data/README.rdoc +23 -32
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +40 -34
- data/lib/active_record/association_relation.rb +22 -0
- data/lib/active_record/associations/alias_tracker.rb +4 -2
- data/lib/active_record/associations/association.rb +60 -46
- data/lib/active_record/associations/association_scope.rb +46 -40
- data/lib/active_record/associations/belongs_to_association.rb +17 -4
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +1 -1
- data/lib/active_record/associations/builder/association.rb +81 -28
- data/lib/active_record/associations/builder/belongs_to.rb +73 -56
- data/lib/active_record/associations/builder/collection_association.rb +54 -40
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +23 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +13 -50
- data/lib/active_record/associations/builder/singular_association.rb +13 -13
- data/lib/active_record/associations/collection_association.rb +130 -96
- data/lib/active_record/associations/collection_proxy.rb +916 -63
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +15 -13
- data/lib/active_record/associations/has_many_association.rb +35 -8
- data/lib/active_record/associations/has_many_through_association.rb +37 -17
- data/lib/active_record/associations/has_one_association.rb +42 -19
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +39 -22
- data/lib/active_record/associations/join_dependency/join_base.rb +2 -2
- data/lib/active_record/associations/join_dependency/join_part.rb +21 -8
- data/lib/active_record/associations/join_dependency.rb +30 -9
- data/lib/active_record/associations/join_helper.rb +1 -11
- data/lib/active_record/associations/preloader/association.rb +29 -33
- data/lib/active_record/associations/preloader/collection_association.rb +1 -1
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +2 -2
- data/lib/active_record/associations/preloader/has_many_through.rb +6 -2
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/through_association.rb +13 -17
- data/lib/active_record/associations/preloader.rb +20 -43
- data/lib/active_record/associations/singular_association.rb +11 -11
- data/lib/active_record/associations/through_association.rb +3 -3
- data/lib/active_record/associations.rb +223 -282
- data/lib/active_record/attribute_assignment.rb +134 -154
- data/lib/active_record/attribute_methods/before_type_cast.rb +44 -5
- data/lib/active_record/attribute_methods/dirty.rb +36 -29
- data/lib/active_record/attribute_methods/primary_key.rb +45 -31
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +67 -90
- data/lib/active_record/attribute_methods/serialization.rb +133 -70
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +51 -45
- data/lib/active_record/attribute_methods/write.rb +34 -39
- data/lib/active_record/attribute_methods.rb +268 -108
- data/lib/active_record/autosave_association.rb +80 -73
- data/lib/active_record/base.rb +54 -451
- data/lib/active_record/callbacks.rb +60 -22
- data/lib/active_record/coders/yaml_column.rb +18 -21
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +347 -197
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +146 -138
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +25 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +19 -3
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +151 -142
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +70 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +499 -217
- data/lib/active_record/connection_adapters/abstract/transaction.rb +208 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +209 -44
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +169 -61
- data/lib/active_record/connection_adapters/column.rb +67 -36
- data/lib/active_record/connection_adapters/connection_specification.rb +96 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +28 -29
- data/lib/active_record/connection_adapters/mysql_adapter.rb +200 -73
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +98 -0
- data/lib/active_record/connection_adapters/postgresql/cast.rb +160 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +240 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +374 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +183 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +508 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +544 -899
- data/lib/active_record/connection_adapters/schema_cache.rb +76 -16
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +595 -16
- data/lib/active_record/connection_handling.rb +98 -0
- data/lib/active_record/core.rb +472 -0
- data/lib/active_record/counter_cache.rb +107 -108
- data/lib/active_record/dynamic_matchers.rb +115 -63
- data/lib/active_record/errors.rb +36 -18
- data/lib/active_record/explain.rb +15 -63
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +8 -4
- data/lib/active_record/fixture_set/file.rb +55 -0
- data/lib/active_record/fixtures.rb +159 -155
- data/lib/active_record/inheritance.rb +93 -59
- data/lib/active_record/integration.rb +8 -8
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +39 -43
- data/lib/active_record/locking/pessimistic.rb +4 -4
- data/lib/active_record/log_subscriber.rb +19 -9
- data/lib/active_record/migration/command_recorder.rb +102 -33
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +411 -173
- data/lib/active_record/model_schema.rb +81 -94
- data/lib/active_record/nested_attributes.rb +173 -131
- data/lib/active_record/null_relation.rb +67 -0
- data/lib/active_record/persistence.rb +254 -106
- data/lib/active_record/query_cache.rb +18 -36
- data/lib/active_record/querying.rb +19 -15
- data/lib/active_record/railtie.rb +113 -38
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +4 -3
- data/lib/active_record/railties/databases.rake +115 -368
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +7 -3
- data/lib/active_record/reflection.rb +110 -61
- data/lib/active_record/relation/batches.rb +29 -29
- data/lib/active_record/relation/calculations.rb +155 -125
- data/lib/active_record/relation/delegation.rb +94 -18
- data/lib/active_record/relation/finder_methods.rb +151 -203
- data/lib/active_record/relation/merger.rb +188 -0
- data/lib/active_record/relation/predicate_builder.rb +85 -42
- data/lib/active_record/relation/query_methods.rb +793 -146
- data/lib/active_record/relation/spawn_methods.rb +43 -150
- data/lib/active_record/relation.rb +293 -173
- data/lib/active_record/result.rb +48 -7
- data/lib/active_record/runtime_registry.rb +17 -0
- data/lib/active_record/sanitization.rb +41 -54
- data/lib/active_record/schema.rb +19 -12
- data/lib/active_record/schema_dumper.rb +41 -41
- data/lib/active_record/schema_migration.rb +46 -0
- data/lib/active_record/scoping/default.rb +56 -52
- data/lib/active_record/scoping/named.rb +78 -103
- data/lib/active_record/scoping.rb +54 -124
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +9 -15
- data/lib/active_record/statement_cache.rb +26 -0
- data/lib/active_record/store.rb +131 -15
- data/lib/active_record/tasks/database_tasks.rb +204 -0
- data/lib/active_record/tasks/firebird_database_tasks.rb +56 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +144 -0
- data/lib/active_record/tasks/oracle_database_tasks.rb +45 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +90 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +51 -0
- data/lib/active_record/tasks/sqlserver_database_tasks.rb +48 -0
- data/lib/active_record/test_case.rb +67 -38
- data/lib/active_record/timestamp.rb +16 -11
- data/lib/active_record/transactions.rb +73 -51
- data/lib/active_record/validations/associated.rb +19 -13
- data/lib/active_record/validations/presence.rb +65 -0
- data/lib/active_record/validations/uniqueness.rb +110 -57
- data/lib/active_record/validations.rb +18 -17
- data/lib/active_record/version.rb +7 -6
- data/lib/active_record.rb +63 -45
- data/lib/rails/generators/active_record/migration/migration_generator.rb +45 -8
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +4 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/model/model_generator.rb +5 -4
- data/lib/rails/generators/active_record/model/templates/model.rb +4 -6
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -5
- metadata +43 -29
- data/examples/associations.png +0 -0
- data/lib/active_record/attribute_methods/deprecated_underscore_read.rb +0 -32
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +0 -191
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -583
- data/lib/active_record/dynamic_finder_match.rb +0 -68
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/fixtures/file.rb +0 -65
- data/lib/active_record/identity_map.rb +0 -162
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -360
- data/lib/rails/generators/active_record/migration.rb +0 -15
- data/lib/rails/generators/active_record/observer/observer_generator.rb +0 -15
- data/lib/rails/generators/active_record/observer/templates/observer.rb +0 -4
- data/lib/rails/generators/active_record/session_migration/session_migration_generator.rb +0 -25
- data/lib/rails/generators/active_record/session_migration/templates/migration.rb +0 -12
@@ -1,4 +1,3 @@
|
|
1
|
-
require 'active_support/core_ext/object/blank'
|
2
1
|
require 'date'
|
3
2
|
require 'set'
|
4
3
|
require 'bigdecimal'
|
@@ -6,37 +5,24 @@ require 'bigdecimal/util'
|
|
6
5
|
|
7
6
|
module ActiveRecord
|
8
7
|
module ConnectionAdapters #:nodoc:
|
9
|
-
|
8
|
+
# Abstract representation of an index definition on a table. Instances of
|
9
|
+
# this type are typically created and returned by methods in database
|
10
|
+
# adapters. e.g. ActiveRecord::ConnectionAdapters::AbstractMysqlAdapter#indexes
|
11
|
+
class IndexDefinition < Struct.new(:table, :name, :unique, :columns, :lengths, :orders, :where, :type, :using) #:nodoc:
|
10
12
|
end
|
11
13
|
|
12
14
|
# Abstract representation of a column definition. Instances of this type
|
13
15
|
# are typically created by methods in TableDefinition, and added to the
|
14
16
|
# +columns+ attribute of said TableDefinition object, in order to be used
|
15
17
|
# for generating a number of table creation or table changing SQL statements.
|
16
|
-
class ColumnDefinition < Struct.new(:
|
17
|
-
|
18
|
+
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type) #:nodoc:
|
18
19
|
def string_to_binary(value)
|
19
20
|
value
|
20
21
|
end
|
21
22
|
|
22
|
-
def
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
def to_sql
|
27
|
-
column_sql = "#{base.quote_column_name(name)} #{sql_type}"
|
28
|
-
column_options = {}
|
29
|
-
column_options[:null] = null unless null.nil?
|
30
|
-
column_options[:default] = default unless default.nil?
|
31
|
-
add_column_options!(column_sql, column_options) unless type.to_sym == :primary_key
|
32
|
-
column_sql
|
23
|
+
def primary_key?
|
24
|
+
primary_key || type.to_sym == :primary_key
|
33
25
|
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def add_column_options!(sql, options)
|
38
|
-
base.add_column_options!(sql, options.merge(:column => self))
|
39
|
-
end
|
40
26
|
end
|
41
27
|
|
42
28
|
# Represents the schema of an SQL table in an abstract way. This class
|
@@ -62,27 +48,24 @@ module ActiveRecord
|
|
62
48
|
class TableDefinition
|
63
49
|
# An array of ColumnDefinition objects, representing the column changes
|
64
50
|
# that have been defined.
|
65
|
-
attr_accessor :
|
51
|
+
attr_accessor :indexes
|
52
|
+
attr_reader :name, :temporary, :options
|
66
53
|
|
67
|
-
def initialize(
|
68
|
-
@columns = []
|
54
|
+
def initialize(types, name, temporary, options)
|
69
55
|
@columns_hash = {}
|
70
|
-
@
|
56
|
+
@indexes = {}
|
57
|
+
@native = types
|
58
|
+
@temporary = temporary
|
59
|
+
@options = options
|
60
|
+
@name = name
|
71
61
|
end
|
72
62
|
|
73
|
-
def
|
74
|
-
raise NotImplementedError unless %w{
|
75
|
-
sqlite mysql mysql2
|
76
|
-
}.include? @base.adapter_name.downcase
|
77
|
-
|
78
|
-
options = args.extract_options!
|
79
|
-
column(args[0], :text, options)
|
80
|
-
end
|
63
|
+
def columns; @columns_hash.values; end
|
81
64
|
|
82
65
|
# Appends a primary key definition to the table definition.
|
83
66
|
# Can be called multiple times, but this is probably not a good idea.
|
84
|
-
def primary_key(name)
|
85
|
-
column(name, :primary_key)
|
67
|
+
def primary_key(name, type = :primary_key, options = {})
|
68
|
+
column(name, type, options.merge(:primary_key => true))
|
86
69
|
end
|
87
70
|
|
88
71
|
# Returns a ColumnDefinition for the column with name +name+.
|
@@ -158,21 +141,21 @@ module ActiveRecord
|
|
158
141
|
# td.column(:granted, :boolean)
|
159
142
|
# # granted BOOLEAN
|
160
143
|
#
|
161
|
-
# td.column(:picture, :binary, :
|
144
|
+
# td.column(:picture, :binary, limit: 2.megabytes)
|
162
145
|
# # => picture BLOB(2097152)
|
163
146
|
#
|
164
|
-
# td.column(:sales_stage, :string, :
|
147
|
+
# td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
|
165
148
|
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
166
149
|
#
|
167
|
-
# td.column(:bill_gates_money, :decimal, :
|
150
|
+
# td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
|
168
151
|
# # => bill_gates_money DECIMAL(15,2)
|
169
152
|
#
|
170
|
-
# td.column(:sensor_reading, :decimal, :
|
153
|
+
# td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
|
171
154
|
# # => sensor_reading DECIMAL(30,20)
|
172
155
|
#
|
173
156
|
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
174
157
|
# # probably wouldn't hurt to include it.
|
175
|
-
# td.column(:huge_integer, :decimal, :
|
158
|
+
# td.column(:huge_integer, :decimal, precision: 30)
|
176
159
|
# # => huge_integer DECIMAL(30)
|
177
160
|
#
|
178
161
|
# # Defines a column with a database-specific type.
|
@@ -187,20 +170,20 @@ module ActiveRecord
|
|
187
170
|
#
|
188
171
|
# What can be written like this with the regular calls to column:
|
189
172
|
#
|
190
|
-
# create_table
|
191
|
-
# t.column
|
192
|
-
# t.column
|
193
|
-
# t.column
|
194
|
-
# t.column
|
195
|
-
# t.column
|
196
|
-
# t.column
|
173
|
+
# create_table :products do |t|
|
174
|
+
# t.column :shop_id, :integer
|
175
|
+
# t.column :creator_id, :integer
|
176
|
+
# t.column :name, :string, default: "Untitled"
|
177
|
+
# t.column :value, :string, default: "Untitled"
|
178
|
+
# t.column :created_at, :datetime
|
179
|
+
# t.column :updated_at, :datetime
|
197
180
|
# end
|
198
181
|
#
|
199
|
-
#
|
182
|
+
# can also be written as follows using the short-hand:
|
200
183
|
#
|
201
184
|
# create_table :products do |t|
|
202
185
|
# t.integer :shop_id, :creator_id
|
203
|
-
# t.string :name, :value, :
|
186
|
+
# t.string :name, :value, default: "Untitled"
|
204
187
|
# t.timestamps
|
205
188
|
# end
|
206
189
|
#
|
@@ -209,54 +192,60 @@ module ActiveRecord
|
|
209
192
|
#
|
210
193
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
211
194
|
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
|
212
|
-
# options, these will be used when creating the <tt>_type</tt> column.
|
195
|
+
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
|
196
|
+
# will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
|
213
197
|
#
|
214
198
|
# create_table :taggings do |t|
|
215
199
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
216
200
|
# t.string :tagger_type
|
217
|
-
# t.string :taggable_type, :
|
201
|
+
# t.string :taggable_type, default: 'Photo'
|
218
202
|
# end
|
203
|
+
# add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
|
204
|
+
# add_index :taggings, [:tagger_id, :tagger_type]
|
219
205
|
#
|
220
206
|
# Can also be written as follows using references:
|
221
207
|
#
|
222
208
|
# create_table :taggings do |t|
|
223
|
-
# t.references :tag
|
224
|
-
# t.references :tagger, :
|
225
|
-
# t.references :taggable, :
|
209
|
+
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
210
|
+
# t.references :tagger, polymorphic: true, index: true
|
211
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }
|
226
212
|
# end
|
227
213
|
def column(name, type, options = {})
|
228
214
|
name = name.to_s
|
229
215
|
type = type.to_sym
|
230
216
|
|
231
|
-
|
232
|
-
|
233
|
-
limit = options.fetch(:limit) do
|
234
|
-
native[type][:limit] if native[type].is_a?(Hash)
|
217
|
+
if primary_key_column_name == name
|
218
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
235
219
|
end
|
236
220
|
|
237
|
-
|
238
|
-
column.precision = options[:precision]
|
239
|
-
column.scale = options[:scale]
|
240
|
-
column.default = options[:default]
|
241
|
-
column.null = options[:null]
|
221
|
+
@columns_hash[name] = new_column_definition(name, type, options)
|
242
222
|
self
|
243
223
|
end
|
244
224
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
225
|
+
def remove_column(name)
|
226
|
+
@columns_hash.delete name.to_s
|
227
|
+
end
|
228
|
+
|
229
|
+
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
230
|
+
define_method column_type do |*args|
|
231
|
+
options = args.extract_options!
|
232
|
+
column_names = args
|
233
|
+
column_names.each { |name| column(name, column_type, options) }
|
234
|
+
end
|
235
|
+
end
|
236
|
+
|
237
|
+
# Adds index options to the indexes hash, keyed by column name
|
238
|
+
# This is primarily used to track indexes that need to be created after the table
|
239
|
+
#
|
240
|
+
# index(:account_id, name: 'index_projects_on_account_id')
|
241
|
+
def index(column_name, options = {})
|
242
|
+
indexes[column_name] = options
|
254
243
|
end
|
255
244
|
|
256
245
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
257
246
|
# <tt>:updated_at</tt> to the table.
|
258
247
|
def timestamps(*args)
|
259
|
-
options =
|
248
|
+
options = args.extract_options!
|
260
249
|
column(:created_at, :datetime, options)
|
261
250
|
column(:updated_at, :datetime, options)
|
262
251
|
end
|
@@ -264,30 +253,62 @@ module ActiveRecord
|
|
264
253
|
def references(*args)
|
265
254
|
options = args.extract_options!
|
266
255
|
polymorphic = options.delete(:polymorphic)
|
256
|
+
index_options = options.delete(:index)
|
267
257
|
args.each do |col|
|
268
258
|
column("#{col}_id", :integer, options)
|
269
|
-
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options)
|
259
|
+
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
260
|
+
index(polymorphic ? %w(id type).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
270
261
|
end
|
271
262
|
end
|
272
263
|
alias :belongs_to :references
|
273
264
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
265
|
+
def new_column_definition(name, type, options) # :nodoc:
|
266
|
+
column = create_column_definition name, type
|
267
|
+
limit = options.fetch(:limit) do
|
268
|
+
native[type][:limit] if native[type].is_a?(Hash)
|
269
|
+
end
|
270
|
+
|
271
|
+
column.limit = limit
|
272
|
+
column.array = options[:array] if column.respond_to?(:array)
|
273
|
+
column.precision = options[:precision]
|
274
|
+
column.scale = options[:scale]
|
275
|
+
column.default = options[:default]
|
276
|
+
column.null = options[:null]
|
277
|
+
column.first = options[:first]
|
278
|
+
column.after = options[:after]
|
279
|
+
column.primary_key = type == :primary_key || options[:primary_key]
|
280
|
+
column
|
279
281
|
end
|
280
282
|
|
281
283
|
private
|
282
|
-
def
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
284
|
+
def create_column_definition(name, type)
|
285
|
+
ColumnDefinition.new name, type
|
286
|
+
end
|
287
|
+
|
288
|
+
def primary_key_column_name
|
289
|
+
primary_key_column = columns.detect { |c| c.primary_key? }
|
290
|
+
primary_key_column && primary_key_column.name
|
287
291
|
end
|
288
292
|
|
289
293
|
def native
|
290
|
-
@
|
294
|
+
@native
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
class AlterTable # :nodoc:
|
299
|
+
attr_reader :adds
|
300
|
+
|
301
|
+
def initialize(td)
|
302
|
+
@td = td
|
303
|
+
@adds = []
|
304
|
+
end
|
305
|
+
|
306
|
+
def name; @td.name; end
|
307
|
+
|
308
|
+
def add_column(name, type, options)
|
309
|
+
name = name.to_s
|
310
|
+
type = type.to_sym
|
311
|
+
@adds << @td.new_column_definition(name, type, options)
|
291
312
|
end
|
292
313
|
end
|
293
314
|
|
@@ -299,6 +320,7 @@ module ActiveRecord
|
|
299
320
|
# change_table :table do |t|
|
300
321
|
# t.column
|
301
322
|
# t.index
|
323
|
+
# t.rename_index
|
302
324
|
# t.timestamps
|
303
325
|
# t.change
|
304
326
|
# t.change_default
|
@@ -331,7 +353,7 @@ module ActiveRecord
|
|
331
353
|
|
332
354
|
# Adds a new column to the named table.
|
333
355
|
# See TableDefinition#column for details of the options you can use.
|
334
|
-
#
|
356
|
+
#
|
335
357
|
# ====== Creating a simple column
|
336
358
|
# t.column(:name, :string)
|
337
359
|
def column(column_name, type, options = {})
|
@@ -346,13 +368,12 @@ module ActiveRecord
|
|
346
368
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
347
369
|
# an Array of Symbols. See SchemaStatements#add_index
|
348
370
|
#
|
349
|
-
# ===== Examples
|
350
371
|
# ====== Creating a simple index
|
351
372
|
# t.index(:name)
|
352
373
|
# ====== Creating a unique index
|
353
|
-
# t.index([:branch_id, :party_id], :
|
374
|
+
# t.index([:branch_id, :party_id], unique: true)
|
354
375
|
# ====== Creating a named index
|
355
|
-
# t.index([:branch_id, :party_id], :
|
376
|
+
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
356
377
|
def index(column_name, options = {})
|
357
378
|
@base.add_index(@table_name, column_name, options)
|
358
379
|
end
|
@@ -362,24 +383,31 @@ module ActiveRecord
|
|
362
383
|
@base.index_exists?(@table_name, column_name, options)
|
363
384
|
end
|
364
385
|
|
386
|
+
# Renames the given index on the table.
|
387
|
+
#
|
388
|
+
# t.rename_index(:user_id, :account_id)
|
389
|
+
def rename_index(index_name, new_index_name)
|
390
|
+
@base.rename_index(@table_name, index_name, new_index_name)
|
391
|
+
end
|
392
|
+
|
365
393
|
# Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
|
366
|
-
#
|
394
|
+
#
|
367
395
|
# t.timestamps
|
368
|
-
def timestamps
|
369
|
-
@base.add_timestamps(@table_name)
|
396
|
+
def timestamps(options = {})
|
397
|
+
@base.add_timestamps(@table_name, options)
|
370
398
|
end
|
371
399
|
|
372
400
|
# Changes the column's definition according to the new options.
|
373
401
|
# See TableDefinition#column for details of the options you can use.
|
374
|
-
#
|
375
|
-
# t.change(:name, :string, :
|
402
|
+
#
|
403
|
+
# t.change(:name, :string, limit: 80)
|
376
404
|
# t.change(:description, :text)
|
377
405
|
def change(column_name, type, options = {})
|
378
406
|
@base.change_column(@table_name, column_name, type, options)
|
379
407
|
end
|
380
408
|
|
381
409
|
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
382
|
-
#
|
410
|
+
#
|
383
411
|
# t.change_default(:qualification, 'new')
|
384
412
|
# t.change_default(:authorized, 1)
|
385
413
|
def change_default(column_name, default)
|
@@ -387,37 +415,36 @@ module ActiveRecord
|
|
387
415
|
end
|
388
416
|
|
389
417
|
# Removes the column(s) from the table definition.
|
390
|
-
#
|
418
|
+
#
|
391
419
|
# t.remove(:qualification)
|
392
420
|
# t.remove(:qualification, :experience)
|
393
421
|
def remove(*column_names)
|
394
|
-
@base.
|
422
|
+
@base.remove_columns(@table_name, *column_names)
|
395
423
|
end
|
396
424
|
|
397
425
|
# Removes the given index from the table.
|
398
426
|
#
|
399
|
-
# ===== Examples
|
400
427
|
# ====== Remove the index_table_name_on_column in the table_name table
|
401
428
|
# t.remove_index :column
|
402
429
|
# ====== Remove the index named index_table_name_on_branch_id in the table_name table
|
403
|
-
# t.remove_index :
|
430
|
+
# t.remove_index column: :branch_id
|
404
431
|
# ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
|
405
|
-
# t.remove_index :
|
432
|
+
# t.remove_index column: [:branch_id, :party_id]
|
406
433
|
# ====== Remove the index named by_branch_party in the table_name table
|
407
|
-
# t.remove_index :
|
434
|
+
# t.remove_index name: :by_branch_party
|
408
435
|
def remove_index(options = {})
|
409
436
|
@base.remove_index(@table_name, options)
|
410
437
|
end
|
411
438
|
|
412
439
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
413
|
-
#
|
440
|
+
#
|
414
441
|
# t.remove_timestamps
|
415
442
|
def remove_timestamps
|
416
443
|
@base.remove_timestamps(@table_name)
|
417
444
|
end
|
418
445
|
|
419
446
|
# Renames a column.
|
420
|
-
#
|
447
|
+
#
|
421
448
|
# t.rename(:description, :name)
|
422
449
|
def rename(column_name, new_column_name)
|
423
450
|
@base.rename_column(@table_name, column_name, new_column_name)
|
@@ -425,61 +452,43 @@ module ActiveRecord
|
|
425
452
|
|
426
453
|
# Adds a reference. Optionally adds a +type+ column, if <tt>:polymorphic</tt> option is provided.
|
427
454
|
# <tt>references</tt> and <tt>belongs_to</tt> are acceptable.
|
428
|
-
#
|
429
|
-
# t.references(:
|
430
|
-
# t.
|
431
|
-
#
|
455
|
+
#
|
456
|
+
# t.references(:user)
|
457
|
+
# t.belongs_to(:supplier, polymorphic: true)
|
458
|
+
#
|
432
459
|
def references(*args)
|
433
460
|
options = args.extract_options!
|
434
|
-
|
435
|
-
|
436
|
-
@base.add_column(@table_name, "#{col}_id", :integer, options)
|
437
|
-
@base.add_column(@table_name, "#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) unless polymorphic.nil?
|
461
|
+
args.each do |ref_name|
|
462
|
+
@base.add_reference(@table_name, ref_name, options)
|
438
463
|
end
|
439
464
|
end
|
440
465
|
alias :belongs_to :references
|
441
466
|
|
442
467
|
# Removes a reference. Optionally removes a +type+ column.
|
443
468
|
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
444
|
-
#
|
445
|
-
# t.remove_references(:
|
446
|
-
# t.
|
447
|
-
#
|
469
|
+
#
|
470
|
+
# t.remove_references(:user)
|
471
|
+
# t.remove_belongs_to(:supplier, polymorphic: true)
|
472
|
+
#
|
448
473
|
def remove_references(*args)
|
449
474
|
options = args.extract_options!
|
450
|
-
|
451
|
-
|
452
|
-
@base.remove_column(@table_name, "#{col}_id")
|
453
|
-
@base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
|
475
|
+
args.each do |ref_name|
|
476
|
+
@base.remove_reference(@table_name, ref_name, options)
|
454
477
|
end
|
455
478
|
end
|
456
|
-
alias :remove_belongs_to
|
479
|
+
alias :remove_belongs_to :remove_references
|
457
480
|
|
458
481
|
# Adds a column or columns of a specified type
|
459
|
-
#
|
482
|
+
#
|
460
483
|
# t.string(:goat)
|
461
484
|
# t.string(:goat, :sheep)
|
462
|
-
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
column = ColumnDefinition.new(@base, name.to_s, type) # column = ColumnDefinition.new(@base, name, type)
|
470
|
-
if options[:limit] # if options[:limit]
|
471
|
-
column.limit = options[:limit] # column.limit = options[:limit]
|
472
|
-
elsif native[type].is_a?(Hash) # elsif native[type].is_a?(Hash)
|
473
|
-
column.limit = native[type][:limit] # column.limit = native[type][:limit]
|
474
|
-
end # end
|
475
|
-
column.precision = options[:precision] # column.precision = options[:precision]
|
476
|
-
column.scale = options[:scale] # column.scale = options[:scale]
|
477
|
-
column.default = options[:default] # column.default = options[:default]
|
478
|
-
column.null = options[:null] # column.null = options[:null]
|
479
|
-
@base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
|
480
|
-
end # end
|
481
|
-
end # end
|
482
|
-
EOV
|
485
|
+
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
486
|
+
define_method column_type do |*args|
|
487
|
+
options = args.extract_options!
|
488
|
+
args.each do |name|
|
489
|
+
@base.add_column(@table_name, name, column_type, options)
|
490
|
+
end
|
491
|
+
end
|
483
492
|
end
|
484
493
|
|
485
494
|
private
|
@@ -0,0 +1,70 @@
|
|
1
|
+
require 'ipaddr'
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
module ConnectionAdapters # :nodoc:
|
5
|
+
# The goal of this module is to move Adapter specific column
|
6
|
+
# definitions to the Adapter instead of having it in the schema
|
7
|
+
# dumper itself. This code represents the normal case.
|
8
|
+
# We can then redefine how certain data types may be handled in the schema dumper on the
|
9
|
+
# Adapter level by over-writing this code inside the database specific adapters
|
10
|
+
module ColumnDumper
|
11
|
+
def column_spec(column, types)
|
12
|
+
spec = prepare_column_options(column, types)
|
13
|
+
(spec.keys - [:name, :type]).each{ |k| spec[k].insert(0, "#{k.to_s}: ")}
|
14
|
+
spec
|
15
|
+
end
|
16
|
+
|
17
|
+
# This can be overridden on a Adapter level basis to support other
|
18
|
+
# extended datatypes (Example: Adding an array option in the
|
19
|
+
# PostgreSQLAdapter)
|
20
|
+
def prepare_column_options(column, types)
|
21
|
+
spec = {}
|
22
|
+
spec[:name] = column.name.inspect
|
23
|
+
|
24
|
+
# AR has an optimization which handles zero-scale decimals as integers. This
|
25
|
+
# code ensures that the dumper still dumps the column as a decimal.
|
26
|
+
spec[:type] = if column.type == :integer && /^(numeric|decimal)/ =~ column.sql_type
|
27
|
+
'decimal'
|
28
|
+
else
|
29
|
+
column.type.to_s
|
30
|
+
end
|
31
|
+
spec[:limit] = column.limit.inspect if column.limit != types[column.type][:limit] && spec[:type] != 'decimal'
|
32
|
+
spec[:precision] = column.precision.inspect if column.precision
|
33
|
+
spec[:scale] = column.scale.inspect if column.scale
|
34
|
+
spec[:null] = 'false' unless column.null
|
35
|
+
spec[:default] = default_string(column.default) if column.has_default?
|
36
|
+
spec
|
37
|
+
end
|
38
|
+
|
39
|
+
# Lists the valid migration options
|
40
|
+
def migration_keys
|
41
|
+
[:name, :limit, :precision, :scale, :default, :null]
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def default_string(value)
|
47
|
+
case value
|
48
|
+
when BigDecimal
|
49
|
+
value.to_s
|
50
|
+
when Date, DateTime, Time
|
51
|
+
"'#{value.to_s(:db)}'"
|
52
|
+
when Range
|
53
|
+
# infinity dumps as Infinity, which causes uninitialized constant error
|
54
|
+
value.inspect.gsub('Infinity', '::Float::INFINITY')
|
55
|
+
when IPAddr
|
56
|
+
subnet_mask = value.instance_variable_get(:@mask_addr)
|
57
|
+
|
58
|
+
# If the subnet mask is equal to /32, don't output it
|
59
|
+
if subnet_mask == (2**32 - 1)
|
60
|
+
"\"#{value.to_s}\""
|
61
|
+
else
|
62
|
+
"\"#{value.to_s}/#{subnet_mask.to_s(2).count('1')}\""
|
63
|
+
end
|
64
|
+
else
|
65
|
+
value.inspect
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|