activerecord 3.2.22.5 → 4.2.11.3
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 +5 -5
- data/CHANGELOG.md +1632 -609
- data/MIT-LICENSE +1 -1
- data/README.rdoc +37 -41
- data/examples/performance.rb +31 -19
- data/examples/simple.rb +4 -4
- data/lib/active_record/aggregations.rb +56 -42
- data/lib/active_record/association_relation.rb +35 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -36
- data/lib/active_record/associations/association.rb +73 -55
- data/lib/active_record/associations/association_scope.rb +143 -82
- data/lib/active_record/associations/belongs_to_association.rb +65 -25
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -2
- data/lib/active_record/associations/builder/association.rb +125 -31
- data/lib/active_record/associations/builder/belongs_to.rb +89 -61
- data/lib/active_record/associations/builder/collection_association.rb +69 -49
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +113 -42
- data/lib/active_record/associations/builder/has_many.rb +8 -64
- data/lib/active_record/associations/builder/has_one.rb +12 -51
- data/lib/active_record/associations/builder/singular_association.rb +23 -17
- data/lib/active_record/associations/collection_association.rb +251 -177
- data/lib/active_record/associations/collection_proxy.rb +963 -63
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +113 -22
- data/lib/active_record/associations/has_many_through_association.rb +99 -39
- data/lib/active_record/associations/has_one_association.rb +43 -20
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +76 -107
- data/lib/active_record/associations/join_dependency/join_base.rb +7 -9
- data/lib/active_record/associations/join_dependency/join_part.rb +30 -37
- data/lib/active_record/associations/join_dependency.rb +230 -156
- data/lib/active_record/associations/preloader/association.rb +96 -55
- data/lib/active_record/associations/preloader/collection_association.rb +3 -3
- data/lib/active_record/associations/preloader/has_many_through.rb +7 -3
- data/lib/active_record/associations/preloader/has_one.rb +1 -1
- data/lib/active_record/associations/preloader/singular_association.rb +3 -3
- data/lib/active_record/associations/preloader/through_association.rb +62 -33
- data/lib/active_record/associations/preloader.rb +101 -79
- data/lib/active_record/associations/singular_association.rb +29 -13
- data/lib/active_record/associations/through_association.rb +30 -16
- data/lib/active_record/associations.rb +463 -345
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +142 -151
- data/lib/active_record/attribute_decorators.rb +66 -0
- data/lib/active_record/attribute_methods/before_type_cast.rb +52 -7
- data/lib/active_record/attribute_methods/dirty.rb +137 -57
- data/lib/active_record/attribute_methods/primary_key.rb +50 -36
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +73 -106
- data/lib/active_record/attribute_methods/serialization.rb +44 -94
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -45
- data/lib/active_record/attribute_methods/write.rb +57 -44
- data/lib/active_record/attribute_methods.rb +301 -141
- data/lib/active_record/attribute_set/builder.rb +106 -0
- data/lib/active_record/attribute_set.rb +81 -0
- data/lib/active_record/attributes.rb +147 -0
- data/lib/active_record/autosave_association.rb +246 -217
- data/lib/active_record/base.rb +70 -474
- data/lib/active_record/callbacks.rb +66 -28
- data/lib/active_record/coders/json.rb +13 -0
- data/lib/active_record/coders/yaml_column.rb +18 -21
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +396 -219
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -164
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +29 -24
- data/lib/active_record/connection_adapters/abstract/quoting.rb +74 -55
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +21 -0
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +125 -0
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +261 -169
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +707 -259
- data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +298 -89
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +466 -196
- data/lib/active_record/connection_adapters/column.rb +31 -245
- data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +45 -57
- data/lib/active_record/connection_adapters/mysql_adapter.rb +180 -123
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +93 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +20 -0
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +232 -0
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +100 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +52 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bit_varying.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +15 -0
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +46 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/oid/decimal.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +59 -0
- data/lib/active_record/connection_adapters/postgresql/oid/inet.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +13 -0
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +23 -0
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +43 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +79 -0
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +19 -0
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +11 -0
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +109 -0
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +21 -0
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +26 -0
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +28 -0
- data/lib/active_record/connection_adapters/postgresql/oid.rb +36 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +108 -0
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +30 -0
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +152 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +596 -0
- data/lib/active_record/connection_adapters/postgresql/utils.rb +77 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +430 -999
- data/lib/active_record/connection_adapters/schema_cache.rb +52 -27
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +579 -22
- data/lib/active_record/connection_handling.rb +132 -0
- data/lib/active_record/core.rb +579 -0
- data/lib/active_record/counter_cache.rb +157 -105
- data/lib/active_record/dynamic_matchers.rb +119 -63
- data/lib/active_record/enum.rb +197 -0
- data/lib/active_record/errors.rb +94 -36
- data/lib/active_record/explain.rb +15 -63
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +9 -5
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +302 -215
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +143 -70
- data/lib/active_record/integration.rb +65 -12
- data/lib/active_record/legacy_yaml_adapter.rb +30 -0
- data/lib/active_record/locale/en.yml +8 -1
- data/lib/active_record/locking/optimistic.rb +73 -52
- data/lib/active_record/locking/pessimistic.rb +5 -5
- data/lib/active_record/log_subscriber.rb +24 -21
- data/lib/active_record/migration/command_recorder.rb +124 -32
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +511 -213
- data/lib/active_record/model_schema.rb +91 -117
- data/lib/active_record/nested_attributes.rb +184 -130
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +81 -0
- data/lib/active_record/persistence.rb +276 -117
- data/lib/active_record/query_cache.rb +19 -37
- data/lib/active_record/querying.rb +28 -18
- data/lib/active_record/railtie.rb +73 -40
- 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 +141 -416
- data/lib/active_record/railties/jdbcmysql_error.rb +1 -1
- data/lib/active_record/readonly_attributes.rb +1 -4
- data/lib/active_record/reflection.rb +513 -154
- data/lib/active_record/relation/batches.rb +91 -43
- data/lib/active_record/relation/calculations.rb +199 -161
- data/lib/active_record/relation/delegation.rb +116 -25
- data/lib/active_record/relation/finder_methods.rb +362 -248
- data/lib/active_record/relation/merger.rb +193 -0
- data/lib/active_record/relation/predicate_builder/array_handler.rb +48 -0
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +13 -0
- data/lib/active_record/relation/predicate_builder.rb +135 -43
- data/lib/active_record/relation/query_methods.rb +928 -167
- data/lib/active_record/relation/spawn_methods.rb +48 -149
- data/lib/active_record/relation.rb +352 -207
- data/lib/active_record/result.rb +101 -10
- data/lib/active_record/runtime_registry.rb +22 -0
- data/lib/active_record/sanitization.rb +56 -59
- data/lib/active_record/schema.rb +19 -13
- data/lib/active_record/schema_dumper.rb +106 -63
- data/lib/active_record/schema_migration.rb +53 -0
- data/lib/active_record/scoping/default.rb +50 -57
- data/lib/active_record/scoping/named.rb +73 -109
- data/lib/active_record/scoping.rb +58 -123
- data/lib/active_record/serialization.rb +6 -2
- data/lib/active_record/serializers/xml_serializer.rb +12 -22
- data/lib/active_record/statement_cache.rb +111 -0
- data/lib/active_record/store.rb +168 -15
- data/lib/active_record/tasks/database_tasks.rb +299 -0
- data/lib/active_record/tasks/mysql_database_tasks.rb +159 -0
- data/lib/active_record/tasks/postgresql_database_tasks.rb +101 -0
- data/lib/active_record/tasks/sqlite_database_tasks.rb +55 -0
- data/lib/active_record/timestamp.rb +23 -16
- data/lib/active_record/transactions.rb +125 -79
- data/lib/active_record/type/big_integer.rb +13 -0
- data/lib/active_record/type/binary.rb +50 -0
- data/lib/active_record/type/boolean.rb +31 -0
- data/lib/active_record/type/date.rb +50 -0
- data/lib/active_record/type/date_time.rb +54 -0
- data/lib/active_record/type/decimal.rb +64 -0
- data/lib/active_record/type/decimal_without_scale.rb +11 -0
- data/lib/active_record/type/decorator.rb +14 -0
- data/lib/active_record/type/float.rb +19 -0
- data/lib/active_record/type/hash_lookup_type_map.rb +23 -0
- data/lib/active_record/type/integer.rb +59 -0
- data/lib/active_record/type/mutable.rb +16 -0
- data/lib/active_record/type/numeric.rb +36 -0
- data/lib/active_record/type/serialized.rb +62 -0
- data/lib/active_record/type/string.rb +40 -0
- data/lib/active_record/type/text.rb +11 -0
- data/lib/active_record/type/time.rb +26 -0
- data/lib/active_record/type/time_value.rb +38 -0
- data/lib/active_record/type/type_map.rb +64 -0
- data/lib/active_record/type/unsigned_integer.rb +15 -0
- data/lib/active_record/type/value.rb +110 -0
- data/lib/active_record/type.rb +23 -0
- data/lib/active_record/validations/associated.rb +24 -16
- data/lib/active_record/validations/presence.rb +67 -0
- data/lib/active_record/validations/uniqueness.rb +123 -64
- data/lib/active_record/validations.rb +36 -29
- data/lib/active_record/version.rb +5 -7
- data/lib/active_record.rb +66 -46
- data/lib/rails/generators/active_record/migration/migration_generator.rb +53 -8
- data/lib/rails/generators/active_record/{model/templates/migration.rb → migration/templates/create_table_migration.rb} +5 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb +20 -15
- data/lib/rails/generators/active_record/migration.rb +11 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +9 -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 -11
- metadata +101 -45
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -63
- data/lib/active_record/associations/join_helper.rb +0 -55
- data/lib/active_record/associations/preloader/has_and_belongs_to_many.rb +0 -60
- 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/active_record/test_case.rb +0 -73
- 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,67 @@ 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(:
|
18
|
+
class ColumnDefinition < Struct.new(:name, :type, :limit, :precision, :scale, :default, :null, :first, :after, :primary_key, :sql_type, :cast_type) #:nodoc:
|
17
19
|
|
18
|
-
def
|
19
|
-
|
20
|
+
def primary_key?
|
21
|
+
primary_key || type.to_sym == :primary_key
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
class ChangeColumnDefinition < Struct.new(:column, :type, :options) #:nodoc:
|
26
|
+
end
|
27
|
+
|
28
|
+
class ForeignKeyDefinition < Struct.new(:from_table, :to_table, :options) #:nodoc:
|
29
|
+
def name
|
30
|
+
options[:name]
|
31
|
+
end
|
32
|
+
|
33
|
+
def column
|
34
|
+
options[:column]
|
35
|
+
end
|
36
|
+
|
37
|
+
def primary_key
|
38
|
+
options[:primary_key] || default_primary_key
|
39
|
+
end
|
40
|
+
|
41
|
+
def on_delete
|
42
|
+
options[:on_delete]
|
20
43
|
end
|
21
44
|
|
22
|
-
def
|
23
|
-
|
45
|
+
def on_update
|
46
|
+
options[:on_update]
|
24
47
|
end
|
25
48
|
|
26
|
-
def
|
27
|
-
|
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
|
49
|
+
def custom_primary_key?
|
50
|
+
options[:primary_key] != default_primary_key
|
33
51
|
end
|
34
52
|
|
35
53
|
private
|
54
|
+
def default_primary_key
|
55
|
+
"id"
|
56
|
+
end
|
57
|
+
end
|
36
58
|
|
37
|
-
|
38
|
-
|
39
|
-
|
59
|
+
module TimestampDefaultDeprecation # :nodoc:
|
60
|
+
def emit_warning_if_null_unspecified(sym, options)
|
61
|
+
return if options.key?(:null)
|
62
|
+
|
63
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
64
|
+
`##{sym}` was called without specifying an option for `null`. In Rails 5,
|
65
|
+
this behavior will change to `null: false`. You should manually specify
|
66
|
+
`null: true` to prevent the behavior of your existing migrations from changing.
|
67
|
+
MSG
|
68
|
+
end
|
40
69
|
end
|
41
70
|
|
42
71
|
# Represents the schema of an SQL table in an abstract way. This class
|
@@ -60,29 +89,30 @@ module ActiveRecord
|
|
60
89
|
# The table definitions
|
61
90
|
# The Columns are stored as a ColumnDefinition in the +columns+ attribute.
|
62
91
|
class TableDefinition
|
92
|
+
include TimestampDefaultDeprecation
|
93
|
+
|
63
94
|
# An array of ColumnDefinition objects, representing the column changes
|
64
95
|
# that have been defined.
|
65
|
-
attr_accessor :
|
96
|
+
attr_accessor :indexes
|
97
|
+
attr_reader :name, :temporary, :options, :as, :foreign_keys
|
66
98
|
|
67
|
-
def initialize(
|
68
|
-
@columns = []
|
99
|
+
def initialize(types, name, temporary, options, as = nil)
|
69
100
|
@columns_hash = {}
|
70
|
-
@
|
101
|
+
@indexes = {}
|
102
|
+
@foreign_keys = []
|
103
|
+
@native = types
|
104
|
+
@temporary = temporary
|
105
|
+
@options = options
|
106
|
+
@as = as
|
107
|
+
@name = name
|
71
108
|
end
|
72
109
|
|
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
|
110
|
+
def columns; @columns_hash.values; end
|
81
111
|
|
82
112
|
# Appends a primary key definition to the table definition.
|
83
113
|
# Can be called multiple times, but this is probably not a good idea.
|
84
|
-
def primary_key(name)
|
85
|
-
column(name, :primary_key)
|
114
|
+
def primary_key(name, type = :primary_key, options = {})
|
115
|
+
column(name, type, options.merge(:primary_key => true))
|
86
116
|
end
|
87
117
|
|
88
118
|
# Returns a ColumnDefinition for the column with name +name+.
|
@@ -95,8 +125,8 @@ module ActiveRecord
|
|
95
125
|
# which is one of the following:
|
96
126
|
# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
|
97
127
|
# <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
|
98
|
-
# <tt>:datetime</tt>, <tt>:
|
99
|
-
# <tt>:
|
128
|
+
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
129
|
+
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
100
130
|
#
|
101
131
|
# You may use a type not in this list as long as it is supported by your
|
102
132
|
# database (for example, "polygon" in MySQL), but this will not be database
|
@@ -115,9 +145,11 @@ module ActiveRecord
|
|
115
145
|
# Specifies the precision for a <tt>:decimal</tt> column.
|
116
146
|
# * <tt>:scale</tt> -
|
117
147
|
# Specifies the scale for a <tt>:decimal</tt> column.
|
148
|
+
# * <tt>:index</tt> -
|
149
|
+
# Create an index for the column. Can be either <tt>true</tt> or an options hash.
|
118
150
|
#
|
119
|
-
#
|
120
|
-
#
|
151
|
+
# Note: The precision is the total number of significant digits
|
152
|
+
# and the scale is the number of digits that can be stored following
|
121
153
|
# the decimal point. For example, the number 123.45 has a precision of 5
|
122
154
|
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
123
155
|
# range from -999.99 to 999.99.
|
@@ -139,17 +171,8 @@ module ActiveRecord
|
|
139
171
|
# Default is (38,0).
|
140
172
|
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
141
173
|
# Default unknown.
|
142
|
-
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
143
|
-
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
144
|
-
# storage rules, decimal being better.
|
145
|
-
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
146
|
-
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
147
|
-
# NUMERIC is 19, and DECIMAL is 38.
|
148
174
|
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
149
175
|
# Default (38,0).
|
150
|
-
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
151
|
-
# Default (38,0).
|
152
|
-
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
153
176
|
#
|
154
177
|
# This method returns <tt>self</tt>.
|
155
178
|
#
|
@@ -158,21 +181,21 @@ module ActiveRecord
|
|
158
181
|
# td.column(:granted, :boolean)
|
159
182
|
# # granted BOOLEAN
|
160
183
|
#
|
161
|
-
# td.column(:picture, :binary, :
|
184
|
+
# td.column(:picture, :binary, limit: 2.megabytes)
|
162
185
|
# # => picture BLOB(2097152)
|
163
186
|
#
|
164
|
-
# td.column(:sales_stage, :string, :
|
187
|
+
# td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
|
165
188
|
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
166
189
|
#
|
167
|
-
# td.column(:bill_gates_money, :decimal, :
|
190
|
+
# td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
|
168
191
|
# # => bill_gates_money DECIMAL(15,2)
|
169
192
|
#
|
170
|
-
# td.column(:sensor_reading, :decimal, :
|
193
|
+
# td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
|
171
194
|
# # => sensor_reading DECIMAL(30,20)
|
172
195
|
#
|
173
196
|
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
174
197
|
# # probably wouldn't hurt to include it.
|
175
|
-
# td.column(:huge_integer, :decimal, :
|
198
|
+
# td.column(:huge_integer, :decimal, precision: 30)
|
176
199
|
# # => huge_integer DECIMAL(30)
|
177
200
|
#
|
178
201
|
# # Defines a column with a database-specific type.
|
@@ -187,21 +210,24 @@ module ActiveRecord
|
|
187
210
|
#
|
188
211
|
# What can be written like this with the regular calls to column:
|
189
212
|
#
|
190
|
-
# create_table
|
191
|
-
# t.column
|
192
|
-
# t.column
|
193
|
-
# t.column
|
194
|
-
# t.column
|
195
|
-
# t.column
|
196
|
-
# t.column
|
213
|
+
# create_table :products do |t|
|
214
|
+
# t.column :shop_id, :integer
|
215
|
+
# t.column :creator_id, :integer
|
216
|
+
# t.column :item_number, :string
|
217
|
+
# t.column :name, :string, default: "Untitled"
|
218
|
+
# t.column :value, :string, default: "Untitled"
|
219
|
+
# t.column :created_at, :datetime
|
220
|
+
# t.column :updated_at, :datetime
|
197
221
|
# end
|
222
|
+
# add_index :products, :item_number
|
198
223
|
#
|
199
|
-
#
|
224
|
+
# can also be written as follows using the short-hand:
|
200
225
|
#
|
201
226
|
# create_table :products do |t|
|
202
227
|
# t.integer :shop_id, :creator_id
|
203
|
-
# t.string :
|
204
|
-
# t.
|
228
|
+
# t.string :item_number, index: true
|
229
|
+
# t.string :name, :value, default: "Untitled"
|
230
|
+
# t.timestamps null: false
|
205
231
|
# end
|
206
232
|
#
|
207
233
|
# There's a short-hand method for each of the type values declared at the top. And then there's
|
@@ -209,85 +235,161 @@ module ActiveRecord
|
|
209
235
|
#
|
210
236
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
211
237
|
# 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.
|
238
|
+
# options, these will be used when creating the <tt>_type</tt> column. The <tt>:index</tt> option
|
239
|
+
# will also create an index, similar to calling <tt>add_index</tt>. So what can be written like this:
|
213
240
|
#
|
214
241
|
# create_table :taggings do |t|
|
215
242
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
216
243
|
# t.string :tagger_type
|
217
|
-
# t.string :taggable_type, :
|
244
|
+
# t.string :taggable_type, default: 'Photo'
|
218
245
|
# end
|
246
|
+
# add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
|
247
|
+
# add_index :taggings, [:tagger_id, :tagger_type]
|
219
248
|
#
|
220
249
|
# Can also be written as follows using references:
|
221
250
|
#
|
222
251
|
# create_table :taggings do |t|
|
223
|
-
# t.references :tag
|
224
|
-
# t.references :tagger, :
|
225
|
-
# t.references :taggable, :
|
252
|
+
# t.references :tag, index: { name: 'index_taggings_on_tag_id' }
|
253
|
+
# t.references :tagger, polymorphic: true, index: true
|
254
|
+
# t.references :taggable, polymorphic: { default: 'Photo' }
|
226
255
|
# end
|
227
256
|
def column(name, type, options = {})
|
228
257
|
name = name.to_s
|
229
258
|
type = type.to_sym
|
259
|
+
options = options.dup
|
230
260
|
|
231
|
-
|
232
|
-
|
233
|
-
limit = options.fetch(:limit) do
|
234
|
-
native[type][:limit] if native[type].is_a?(Hash)
|
261
|
+
if @columns_hash[name] && @columns_hash[name].primary_key?
|
262
|
+
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
|
235
263
|
end
|
236
264
|
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
column.default = options[:default]
|
241
|
-
column.null = options[:null]
|
265
|
+
index_options = options.delete(:index)
|
266
|
+
index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
|
267
|
+
@columns_hash[name] = new_column_definition(name, type, options)
|
242
268
|
self
|
243
269
|
end
|
244
270
|
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
|
251
|
-
|
252
|
-
|
253
|
-
|
271
|
+
def remove_column(name)
|
272
|
+
@columns_hash.delete name.to_s
|
273
|
+
end
|
274
|
+
|
275
|
+
[:string, :text, :integer, :bigint, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
276
|
+
define_method column_type do |*args|
|
277
|
+
options = args.extract_options!
|
278
|
+
column_names = args
|
279
|
+
column_names.each { |name| column(name, column_type, options) }
|
280
|
+
end
|
281
|
+
end
|
282
|
+
|
283
|
+
# Adds index options to the indexes hash, keyed by column name
|
284
|
+
# This is primarily used to track indexes that need to be created after the table
|
285
|
+
#
|
286
|
+
# index(:account_id, name: 'index_projects_on_account_id')
|
287
|
+
def index(column_name, options = {})
|
288
|
+
indexes[column_name] = options
|
289
|
+
end
|
290
|
+
|
291
|
+
def foreign_key(table_name, options = {}) # :nodoc:
|
292
|
+
foreign_keys.push([table_name, options])
|
254
293
|
end
|
255
294
|
|
256
295
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
257
|
-
# <tt>:updated_at</tt> to the table.
|
296
|
+
# <tt>:updated_at</tt> to the table. See SchemaStatements#add_timestamps
|
297
|
+
#
|
298
|
+
# t.timestamps null: false
|
258
299
|
def timestamps(*args)
|
259
|
-
options =
|
300
|
+
options = args.extract_options!
|
301
|
+
emit_warning_if_null_unspecified(:timestamps, options)
|
260
302
|
column(:created_at, :datetime, options)
|
261
303
|
column(:updated_at, :datetime, options)
|
262
304
|
end
|
263
305
|
|
306
|
+
# Adds a reference.
|
307
|
+
#
|
308
|
+
# t.references(:user)
|
309
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
310
|
+
#
|
311
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
264
312
|
def references(*args)
|
265
313
|
options = args.extract_options!
|
266
314
|
polymorphic = options.delete(:polymorphic)
|
315
|
+
index_options = options.delete(:index)
|
316
|
+
foreign_key_options = options.delete(:foreign_key)
|
317
|
+
type = options.delete(:type) || :integer
|
318
|
+
|
319
|
+
if polymorphic && foreign_key_options
|
320
|
+
raise ArgumentError, "Cannot add a foreign key on a polymorphic relation"
|
321
|
+
end
|
322
|
+
|
267
323
|
args.each do |col|
|
268
|
-
column("#{col}_id",
|
269
|
-
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options)
|
324
|
+
column("#{col}_id", type, options)
|
325
|
+
column("#{col}_type", :string, polymorphic.is_a?(Hash) ? polymorphic : options) if polymorphic
|
326
|
+
index(polymorphic ? %w(type id).map { |t| "#{col}_#{t}" } : "#{col}_id", index_options.is_a?(Hash) ? index_options : {}) if index_options
|
327
|
+
if foreign_key_options
|
328
|
+
to_table = Base.pluralize_table_names ? col.to_s.pluralize : col.to_s
|
329
|
+
foreign_key(to_table, foreign_key_options.is_a?(Hash) ? foreign_key_options : {})
|
330
|
+
end
|
270
331
|
end
|
271
332
|
end
|
272
333
|
alias :belongs_to :references
|
273
334
|
|
274
|
-
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
335
|
+
def new_column_definition(name, type, options) # :nodoc:
|
336
|
+
type = aliased_types(type.to_s, type)
|
337
|
+
column = create_column_definition name, type
|
338
|
+
limit = options.fetch(:limit) do
|
339
|
+
native[type][:limit] if native[type].is_a?(Hash)
|
340
|
+
end
|
341
|
+
|
342
|
+
column.limit = limit
|
343
|
+
column.precision = options[:precision]
|
344
|
+
column.scale = options[:scale]
|
345
|
+
column.default = options[:default]
|
346
|
+
column.null = options[:null]
|
347
|
+
column.first = options[:first]
|
348
|
+
column.after = options[:after]
|
349
|
+
column.primary_key = type == :primary_key || options[:primary_key]
|
350
|
+
column
|
279
351
|
end
|
280
352
|
|
281
353
|
private
|
282
|
-
def
|
283
|
-
|
284
|
-
@columns << definition
|
285
|
-
@columns_hash[name] = definition
|
286
|
-
definition
|
354
|
+
def create_column_definition(name, type)
|
355
|
+
ColumnDefinition.new name, type
|
287
356
|
end
|
288
357
|
|
289
358
|
def native
|
290
|
-
@
|
359
|
+
@native
|
360
|
+
end
|
361
|
+
|
362
|
+
def aliased_types(name, fallback)
|
363
|
+
'timestamp' == name ? :datetime : fallback
|
364
|
+
end
|
365
|
+
end
|
366
|
+
|
367
|
+
class AlterTable # :nodoc:
|
368
|
+
attr_reader :adds
|
369
|
+
attr_reader :foreign_key_adds
|
370
|
+
attr_reader :foreign_key_drops
|
371
|
+
|
372
|
+
def initialize(td)
|
373
|
+
@td = td
|
374
|
+
@adds = []
|
375
|
+
@foreign_key_adds = []
|
376
|
+
@foreign_key_drops = []
|
377
|
+
end
|
378
|
+
|
379
|
+
def name; @td.name; end
|
380
|
+
|
381
|
+
def add_foreign_key(to_table, options)
|
382
|
+
@foreign_key_adds << ForeignKeyDefinition.new(name, to_table, options)
|
383
|
+
end
|
384
|
+
|
385
|
+
def drop_foreign_key(name)
|
386
|
+
@foreign_key_drops << name
|
387
|
+
end
|
388
|
+
|
389
|
+
def add_column(name, type, options)
|
390
|
+
name = name.to_s
|
391
|
+
type = type.to_sym
|
392
|
+
@adds << @td.new_column_definition(name, type, options)
|
291
393
|
end
|
292
394
|
end
|
293
395
|
|
@@ -299,6 +401,7 @@ module ActiveRecord
|
|
299
401
|
# change_table :table do |t|
|
300
402
|
# t.column
|
301
403
|
# t.index
|
404
|
+
# t.rename_index
|
302
405
|
# t.timestamps
|
303
406
|
# t.change
|
304
407
|
# t.change_default
|
@@ -324,162 +427,152 @@ module ActiveRecord
|
|
324
427
|
# end
|
325
428
|
#
|
326
429
|
class Table
|
430
|
+
attr_reader :name
|
431
|
+
|
327
432
|
def initialize(table_name, base)
|
328
|
-
@
|
433
|
+
@name = table_name
|
329
434
|
@base = base
|
330
435
|
end
|
331
436
|
|
332
437
|
# Adds a new column to the named table.
|
333
438
|
# See TableDefinition#column for details of the options you can use.
|
334
|
-
#
|
439
|
+
#
|
335
440
|
# ====== Creating a simple column
|
336
441
|
# t.column(:name, :string)
|
337
442
|
def column(column_name, type, options = {})
|
338
|
-
@base.add_column(
|
443
|
+
@base.add_column(name, column_name, type, options)
|
339
444
|
end
|
340
445
|
|
341
446
|
# Checks to see if a column exists. See SchemaStatements#column_exists?
|
342
447
|
def column_exists?(column_name, type = nil, options = {})
|
343
|
-
@base.column_exists?(
|
448
|
+
@base.column_exists?(name, column_name, type, options)
|
344
449
|
end
|
345
450
|
|
346
451
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
347
452
|
# an Array of Symbols. See SchemaStatements#add_index
|
348
453
|
#
|
349
|
-
# ===== Examples
|
350
454
|
# ====== Creating a simple index
|
351
455
|
# t.index(:name)
|
352
456
|
# ====== Creating a unique index
|
353
|
-
# t.index([:branch_id, :party_id], :
|
457
|
+
# t.index([:branch_id, :party_id], unique: true)
|
354
458
|
# ====== Creating a named index
|
355
|
-
# t.index([:branch_id, :party_id], :
|
459
|
+
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
356
460
|
def index(column_name, options = {})
|
357
|
-
@base.add_index(
|
461
|
+
@base.add_index(name, column_name, options)
|
358
462
|
end
|
359
463
|
|
360
464
|
# Checks to see if an index exists. See SchemaStatements#index_exists?
|
361
465
|
def index_exists?(column_name, options = {})
|
362
|
-
@base.index_exists?(
|
466
|
+
@base.index_exists?(name, column_name, options)
|
467
|
+
end
|
468
|
+
|
469
|
+
# Renames the given index on the table.
|
470
|
+
#
|
471
|
+
# t.rename_index(:user_id, :account_id)
|
472
|
+
def rename_index(index_name, new_index_name)
|
473
|
+
@base.rename_index(name, index_name, new_index_name)
|
363
474
|
end
|
364
475
|
|
365
476
|
# Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
|
366
|
-
#
|
367
|
-
# t.timestamps
|
368
|
-
def timestamps
|
369
|
-
@base.add_timestamps(
|
477
|
+
#
|
478
|
+
# t.timestamps null: false
|
479
|
+
def timestamps(options = {})
|
480
|
+
@base.add_timestamps(name, options)
|
370
481
|
end
|
371
482
|
|
372
483
|
# Changes the column's definition according to the new options.
|
373
484
|
# See TableDefinition#column for details of the options you can use.
|
374
|
-
#
|
375
|
-
# t.change(:name, :string, :
|
485
|
+
#
|
486
|
+
# t.change(:name, :string, limit: 80)
|
376
487
|
# t.change(:description, :text)
|
377
488
|
def change(column_name, type, options = {})
|
378
|
-
@base.change_column(
|
489
|
+
@base.change_column(name, column_name, type, options)
|
379
490
|
end
|
380
491
|
|
381
492
|
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
382
|
-
#
|
493
|
+
#
|
383
494
|
# t.change_default(:qualification, 'new')
|
384
495
|
# t.change_default(:authorized, 1)
|
385
496
|
def change_default(column_name, default)
|
386
|
-
@base.change_column_default(
|
497
|
+
@base.change_column_default(name, column_name, default)
|
387
498
|
end
|
388
499
|
|
389
500
|
# Removes the column(s) from the table definition.
|
390
|
-
#
|
501
|
+
#
|
391
502
|
# t.remove(:qualification)
|
392
503
|
# t.remove(:qualification, :experience)
|
393
504
|
def remove(*column_names)
|
394
|
-
@base.
|
505
|
+
@base.remove_columns(name, *column_names)
|
395
506
|
end
|
396
507
|
|
397
508
|
# Removes the given index from the table.
|
398
509
|
#
|
399
|
-
# ===== Examples
|
400
510
|
# ====== Remove the index_table_name_on_column in the table_name table
|
401
511
|
# t.remove_index :column
|
402
512
|
# ====== Remove the index named index_table_name_on_branch_id in the table_name table
|
403
|
-
# t.remove_index :
|
513
|
+
# t.remove_index column: :branch_id
|
404
514
|
# ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
|
405
|
-
# t.remove_index :
|
515
|
+
# t.remove_index column: [:branch_id, :party_id]
|
406
516
|
# ====== Remove the index named by_branch_party in the table_name table
|
407
|
-
# t.remove_index :
|
517
|
+
# t.remove_index name: :by_branch_party
|
408
518
|
def remove_index(options = {})
|
409
|
-
@base.remove_index(
|
519
|
+
@base.remove_index(name, options)
|
410
520
|
end
|
411
521
|
|
412
522
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
413
|
-
#
|
523
|
+
#
|
414
524
|
# t.remove_timestamps
|
415
|
-
def remove_timestamps
|
416
|
-
@base.remove_timestamps(
|
525
|
+
def remove_timestamps(options = {})
|
526
|
+
@base.remove_timestamps(name, options)
|
417
527
|
end
|
418
528
|
|
419
529
|
# Renames a column.
|
420
|
-
#
|
530
|
+
#
|
421
531
|
# t.rename(:description, :name)
|
422
532
|
def rename(column_name, new_column_name)
|
423
|
-
@base.rename_column(
|
533
|
+
@base.rename_column(name, column_name, new_column_name)
|
424
534
|
end
|
425
535
|
|
426
|
-
# Adds a reference.
|
427
|
-
#
|
428
|
-
#
|
429
|
-
# t.
|
430
|
-
#
|
431
|
-
#
|
536
|
+
# Adds a reference.
|
537
|
+
#
|
538
|
+
# t.references(:user)
|
539
|
+
# t.belongs_to(:supplier, foreign_key: true)
|
540
|
+
#
|
541
|
+
# See SchemaStatements#add_reference for details of the options you can use.
|
432
542
|
def references(*args)
|
433
543
|
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?
|
544
|
+
args.each do |ref_name|
|
545
|
+
@base.add_reference(name, ref_name, options)
|
438
546
|
end
|
439
547
|
end
|
440
548
|
alias :belongs_to :references
|
441
549
|
|
442
550
|
# Removes a reference. Optionally removes a +type+ column.
|
443
551
|
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
444
|
-
#
|
445
|
-
# t.remove_references(:
|
446
|
-
# t.
|
447
|
-
#
|
552
|
+
#
|
553
|
+
# t.remove_references(:user)
|
554
|
+
# t.remove_belongs_to(:supplier, polymorphic: true)
|
555
|
+
#
|
556
|
+
# See SchemaStatements#remove_reference
|
448
557
|
def remove_references(*args)
|
449
558
|
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?
|
559
|
+
args.each do |ref_name|
|
560
|
+
@base.remove_reference(name, ref_name, options)
|
454
561
|
end
|
455
562
|
end
|
456
|
-
alias :remove_belongs_to
|
563
|
+
alias :remove_belongs_to :remove_references
|
457
564
|
|
458
565
|
# Adds a column or columns of a specified type
|
459
|
-
#
|
566
|
+
#
|
460
567
|
# t.string(:goat)
|
461
568
|
# 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
|
569
|
+
[:string, :text, :integer, :float, :decimal, :datetime, :timestamp, :time, :date, :binary, :boolean].each do |column_type|
|
570
|
+
define_method column_type do |*args|
|
571
|
+
options = args.extract_options!
|
572
|
+
args.each do |column_name|
|
573
|
+
@base.add_column(name, column_name, column_type, options)
|
574
|
+
end
|
575
|
+
end
|
483
576
|
end
|
484
577
|
|
485
578
|
private
|
@@ -487,6 +580,5 @@ module ActiveRecord
|
|
487
580
|
@base.native_database_types
|
488
581
|
end
|
489
582
|
end
|
490
|
-
|
491
583
|
end
|
492
584
|
end
|