activerecord 3.1.10 → 4.2.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +6 -6
- data/CHANGELOG.md +1837 -338
- data/MIT-LICENSE +1 -1
- data/README.rdoc +39 -43
- data/examples/performance.rb +51 -20
- data/examples/simple.rb +4 -4
- data/lib/active_record/aggregations.rb +57 -43
- data/lib/active_record/association_relation.rb +35 -0
- data/lib/active_record/associations/alias_tracker.rb +47 -39
- data/lib/active_record/associations/association.rb +71 -85
- data/lib/active_record/associations/association_scope.rb +138 -89
- data/lib/active_record/associations/belongs_to_association.rb +65 -25
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +9 -3
- data/lib/active_record/associations/builder/association.rb +125 -29
- data/lib/active_record/associations/builder/belongs_to.rb +91 -60
- 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 -52
- data/lib/active_record/associations/builder/singular_association.rb +22 -29
- data/lib/active_record/associations/collection_association.rb +294 -187
- data/lib/active_record/associations/collection_proxy.rb +961 -94
- data/lib/active_record/associations/foreign_association.rb +11 -0
- data/lib/active_record/associations/has_many_association.rb +118 -23
- data/lib/active_record/associations/has_many_through_association.rb +115 -45
- data/lib/active_record/associations/has_one_association.rb +57 -24
- data/lib/active_record/associations/has_one_through_association.rb +1 -1
- data/lib/active_record/associations/join_dependency/join_association.rb +76 -102
- 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 +61 -32
- data/lib/active_record/associations/preloader.rb +113 -87
- data/lib/active_record/associations/singular_association.rb +29 -13
- data/lib/active_record/associations/through_association.rb +37 -19
- data/lib/active_record/associations.rb +505 -371
- data/lib/active_record/attribute.rb +163 -0
- data/lib/active_record/attribute_assignment.rb +212 -0
- 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 +141 -51
- data/lib/active_record/attribute_methods/primary_key.rb +87 -36
- data/lib/active_record/attribute_methods/query.rb +5 -4
- data/lib/active_record/attribute_methods/read.rb +74 -117
- data/lib/active_record/attribute_methods/serialization.rb +70 -0
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +49 -47
- data/lib/active_record/attribute_methods/write.rb +60 -21
- data/lib/active_record/attribute_methods.rb +409 -48
- 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 +279 -232
- data/lib/active_record/base.rb +84 -1969
- 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 +422 -243
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +9 -0
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +170 -194
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +32 -19
- data/lib/active_record/connection_adapters/abstract/quoting.rb +79 -57
- 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 +273 -170
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +50 -0
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +731 -254
- data/lib/active_record/connection_adapters/abstract/transaction.rb +215 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +339 -95
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +946 -0
- data/lib/active_record/connection_adapters/column.rb +33 -221
- data/lib/active_record/connection_adapters/connection_specification.rb +275 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +140 -602
- data/lib/active_record/connection_adapters/mysql_adapter.rb +254 -756
- 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 +445 -902
- data/lib/active_record/connection_adapters/schema_cache.rb +94 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +578 -25
- data/lib/active_record/connection_handling.rb +132 -0
- data/lib/active_record/core.rb +579 -0
- data/lib/active_record/counter_cache.rb +159 -102
- data/lib/active_record/dynamic_matchers.rb +140 -0
- data/lib/active_record/enum.rb +197 -0
- data/lib/active_record/errors.rb +102 -34
- data/lib/active_record/explain.rb +38 -0
- data/lib/active_record/explain_registry.rb +30 -0
- data/lib/active_record/explain_subscriber.rb +29 -0
- data/lib/active_record/fixture_set/file.rb +56 -0
- data/lib/active_record/fixtures.rb +318 -260
- data/lib/active_record/gem_version.rb +15 -0
- data/lib/active_record/inheritance.rb +247 -0
- data/lib/active_record/integration.rb +113 -0
- 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 +80 -52
- data/lib/active_record/locking/pessimistic.rb +27 -5
- data/lib/active_record/log_subscriber.rb +25 -18
- data/lib/active_record/migration/command_recorder.rb +130 -38
- data/lib/active_record/migration/join_table.rb +15 -0
- data/lib/active_record/migration.rb +532 -201
- data/lib/active_record/model_schema.rb +342 -0
- data/lib/active_record/nested_attributes.rb +229 -139
- data/lib/active_record/no_touching.rb +52 -0
- data/lib/active_record/null_relation.rb +81 -0
- data/lib/active_record/persistence.rb +304 -99
- data/lib/active_record/query_cache.rb +25 -43
- data/lib/active_record/querying.rb +68 -0
- data/lib/active_record/railtie.rb +86 -45
- data/lib/active_record/railties/console_sandbox.rb +3 -4
- data/lib/active_record/railties/controller_runtime.rb +7 -4
- data/lib/active_record/railties/databases.rake +198 -377
- data/lib/active_record/railties/jdbcmysql_error.rb +2 -2
- data/lib/active_record/readonly_attributes.rb +23 -0
- data/lib/active_record/reflection.rb +516 -165
- data/lib/active_record/relation/batches.rb +96 -45
- data/lib/active_record/relation/calculations.rb +221 -144
- data/lib/active_record/relation/delegation.rb +140 -0
- data/lib/active_record/relation/finder_methods.rb +362 -243
- 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 -41
- data/lib/active_record/relation/query_methods.rb +982 -155
- data/lib/active_record/relation/spawn_methods.rb +50 -110
- data/lib/active_record/relation.rb +371 -180
- data/lib/active_record/result.rb +109 -12
- data/lib/active_record/runtime_registry.rb +22 -0
- data/lib/active_record/sanitization.rb +191 -0
- data/lib/active_record/schema.rb +19 -13
- data/lib/active_record/schema_dumper.rb +111 -61
- data/lib/active_record/schema_migration.rb +53 -0
- data/lib/active_record/scoping/default.rb +135 -0
- data/lib/active_record/scoping/named.rb +164 -0
- data/lib/active_record/scoping.rb +87 -0
- data/lib/active_record/serialization.rb +7 -45
- data/lib/active_record/serializers/xml_serializer.rb +14 -65
- data/lib/active_record/statement_cache.rb +111 -0
- data/lib/active_record/store.rb +205 -0
- 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 +35 -14
- data/lib/active_record/transactions.rb +141 -74
- data/lib/active_record/translation.rb +22 -0
- 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 +27 -18
- data/lib/active_record/validations/presence.rb +67 -0
- data/lib/active_record/validations/uniqueness.rb +125 -66
- data/lib/active_record/validations.rb +37 -30
- data/lib/active_record/version.rb +5 -7
- data/lib/active_record.rb +80 -25
- data/lib/rails/generators/active_record/migration/migration_generator.rb +54 -9
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +19 -0
- data/lib/rails/generators/active_record/migration/templates/migration.rb +25 -11
- data/lib/rails/generators/active_record/migration.rb +11 -8
- data/lib/rails/generators/active_record/model/model_generator.rb +17 -4
- data/lib/rails/generators/active_record/model/templates/model.rb +5 -2
- data/lib/rails/generators/active_record/model/templates/module.rb +1 -1
- data/lib/rails/generators/active_record.rb +3 -11
- metadata +132 -53
- data/examples/associations.png +0 -0
- data/lib/active_record/associations/has_and_belongs_to_many_association.rb +0 -62
- 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/connection_adapters/abstract/connection_specification.rb +0 -135
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +0 -556
- data/lib/active_record/dynamic_finder_match.rb +0 -56
- data/lib/active_record/dynamic_scope_match.rb +0 -23
- data/lib/active_record/identity_map.rb +0 -163
- data/lib/active_record/named_scope.rb +0 -200
- data/lib/active_record/observer.rb +0 -121
- data/lib/active_record/session_store.rb +0 -358
- data/lib/active_record/test_case.rb +0 -69
- data/lib/rails/generators/active_record/model/templates/migration.rb +0 -17
- 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 -16
@@ -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,44 +5,74 @@ 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
|
43
72
|
# provides methods for manipulating the schema representation.
|
44
73
|
#
|
45
|
-
# Inside migration files, the +t+ object in +create_table+
|
46
|
-
#
|
74
|
+
# Inside migration files, the +t+ object in +create_table+
|
75
|
+
# is actually of this type:
|
47
76
|
#
|
48
77
|
# class SomeMigration < ActiveRecord::Migration
|
49
78
|
# def up
|
@@ -60,33 +89,35 @@ 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 :
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
@
|
96
|
+
attr_accessor :indexes
|
97
|
+
attr_reader :name, :temporary, :options, :as, :foreign_keys
|
98
|
+
|
99
|
+
def initialize(types, name, temporary, options, as = nil)
|
100
|
+
@columns_hash = {}
|
101
|
+
@indexes = {}
|
102
|
+
@foreign_keys = []
|
103
|
+
@native = types
|
104
|
+
@temporary = temporary
|
105
|
+
@options = options
|
106
|
+
@as = as
|
107
|
+
@name = name
|
70
108
|
end
|
71
109
|
|
72
|
-
def
|
73
|
-
raise NotImplementedError unless %w{
|
74
|
-
sqlite mysql mysql2
|
75
|
-
}.include? @base.adapter_name.downcase
|
76
|
-
|
77
|
-
options = args.extract_options!
|
78
|
-
column(args[0], :text, options)
|
79
|
-
end
|
110
|
+
def columns; @columns_hash.values; end
|
80
111
|
|
81
112
|
# Appends a primary key definition to the table definition.
|
82
113
|
# Can be called multiple times, but this is probably not a good idea.
|
83
|
-
def primary_key(name)
|
84
|
-
column(name, :primary_key)
|
114
|
+
def primary_key(name, type = :primary_key, options = {})
|
115
|
+
column(name, type, options.merge(:primary_key => true))
|
85
116
|
end
|
86
117
|
|
87
118
|
# Returns a ColumnDefinition for the column with name +name+.
|
88
119
|
def [](name)
|
89
|
-
@
|
120
|
+
@columns_hash[name.to_s]
|
90
121
|
end
|
91
122
|
|
92
123
|
# Instantiates a new column for the table.
|
@@ -94,8 +125,8 @@ module ActiveRecord
|
|
94
125
|
# which is one of the following:
|
95
126
|
# <tt>:primary_key</tt>, <tt>:string</tt>, <tt>:text</tt>,
|
96
127
|
# <tt>:integer</tt>, <tt>:float</tt>, <tt>:decimal</tt>,
|
97
|
-
# <tt>:datetime</tt>, <tt>:
|
98
|
-
# <tt>:
|
128
|
+
# <tt>:datetime</tt>, <tt>:time</tt>, <tt>:date</tt>,
|
129
|
+
# <tt>:binary</tt>, <tt>:boolean</tt>.
|
99
130
|
#
|
100
131
|
# You may use a type not in this list as long as it is supported by your
|
101
132
|
# database (for example, "polygon" in MySQL), but this will not be database
|
@@ -114,9 +145,11 @@ module ActiveRecord
|
|
114
145
|
# Specifies the precision for a <tt>:decimal</tt> column.
|
115
146
|
# * <tt>:scale</tt> -
|
116
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.
|
117
150
|
#
|
118
|
-
#
|
119
|
-
#
|
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
|
120
153
|
# the decimal point. For example, the number 123.45 has a precision of 5
|
121
154
|
# and a scale of 2. A decimal with a precision of 5 and a scale of 2 can
|
122
155
|
# range from -999.99 to 999.99.
|
@@ -138,17 +171,8 @@ module ActiveRecord
|
|
138
171
|
# Default is (38,0).
|
139
172
|
# * DB2: <tt>:precision</tt> [1..63], <tt>:scale</tt> [0..62].
|
140
173
|
# Default unknown.
|
141
|
-
# * Firebird: <tt>:precision</tt> [1..18], <tt>:scale</tt> [0..18].
|
142
|
-
# Default (9,0). Internal types NUMERIC and DECIMAL have different
|
143
|
-
# storage rules, decimal being better.
|
144
|
-
# * FrontBase?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
145
|
-
# Default (38,0). WARNING Max <tt>:precision</tt>/<tt>:scale</tt> for
|
146
|
-
# NUMERIC is 19, and DECIMAL is 38.
|
147
174
|
# * SqlServer?: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
148
175
|
# Default (38,0).
|
149
|
-
# * Sybase: <tt>:precision</tt> [1..38], <tt>:scale</tt> [0..38].
|
150
|
-
# Default (38,0).
|
151
|
-
# * OpenBase?: Documentation unclear. Claims storage in <tt>double</tt>.
|
152
176
|
#
|
153
177
|
# This method returns <tt>self</tt>.
|
154
178
|
#
|
@@ -157,21 +181,21 @@ module ActiveRecord
|
|
157
181
|
# td.column(:granted, :boolean)
|
158
182
|
# # granted BOOLEAN
|
159
183
|
#
|
160
|
-
# td.column(:picture, :binary, :
|
184
|
+
# td.column(:picture, :binary, limit: 2.megabytes)
|
161
185
|
# # => picture BLOB(2097152)
|
162
186
|
#
|
163
|
-
# td.column(:sales_stage, :string, :
|
187
|
+
# td.column(:sales_stage, :string, limit: 20, default: 'new', null: false)
|
164
188
|
# # => sales_stage VARCHAR(20) DEFAULT 'new' NOT NULL
|
165
189
|
#
|
166
|
-
# td.column(:bill_gates_money, :decimal, :
|
190
|
+
# td.column(:bill_gates_money, :decimal, precision: 15, scale: 2)
|
167
191
|
# # => bill_gates_money DECIMAL(15,2)
|
168
192
|
#
|
169
|
-
# td.column(:sensor_reading, :decimal, :
|
193
|
+
# td.column(:sensor_reading, :decimal, precision: 30, scale: 20)
|
170
194
|
# # => sensor_reading DECIMAL(30,20)
|
171
195
|
#
|
172
196
|
# # While <tt>:scale</tt> defaults to zero on most databases, it
|
173
197
|
# # probably wouldn't hurt to include it.
|
174
|
-
# td.column(:huge_integer, :decimal, :
|
198
|
+
# td.column(:huge_integer, :decimal, precision: 30)
|
175
199
|
# # => huge_integer DECIMAL(30)
|
176
200
|
#
|
177
201
|
# # Defines a column with a database-specific type.
|
@@ -186,21 +210,24 @@ module ActiveRecord
|
|
186
210
|
#
|
187
211
|
# What can be written like this with the regular calls to column:
|
188
212
|
#
|
189
|
-
# create_table
|
190
|
-
# t.column
|
191
|
-
# t.column
|
192
|
-
# t.column
|
193
|
-
# t.column
|
194
|
-
# t.column
|
195
|
-
# 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
|
196
221
|
# end
|
222
|
+
# add_index :products, :item_number
|
197
223
|
#
|
198
|
-
#
|
224
|
+
# can also be written as follows using the short-hand:
|
199
225
|
#
|
200
226
|
# create_table :products do |t|
|
201
227
|
# t.integer :shop_id, :creator_id
|
202
|
-
# t.string :
|
203
|
-
# t.
|
228
|
+
# t.string :item_number, index: true
|
229
|
+
# t.string :name, :value, default: "Untitled"
|
230
|
+
# t.timestamps null: false
|
204
231
|
# end
|
205
232
|
#
|
206
233
|
# There's a short-hand method for each of the type values declared at the top. And then there's
|
@@ -208,76 +235,162 @@ module ActiveRecord
|
|
208
235
|
#
|
209
236
|
# TableDefinition#references will add an appropriately-named _id column, plus a corresponding _type
|
210
237
|
# column if the <tt>:polymorphic</tt> option is supplied. If <tt>:polymorphic</tt> is a hash of
|
211
|
-
# 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:
|
212
240
|
#
|
213
241
|
# create_table :taggings do |t|
|
214
242
|
# t.integer :tag_id, :tagger_id, :taggable_id
|
215
243
|
# t.string :tagger_type
|
216
|
-
# t.string :taggable_type, :
|
244
|
+
# t.string :taggable_type, default: 'Photo'
|
217
245
|
# end
|
246
|
+
# add_index :taggings, :tag_id, name: 'index_taggings_on_tag_id'
|
247
|
+
# add_index :taggings, [:tagger_id, :tagger_type]
|
218
248
|
#
|
219
249
|
# Can also be written as follows using references:
|
220
250
|
#
|
221
251
|
# create_table :taggings do |t|
|
222
|
-
# t.references :tag
|
223
|
-
# t.references :tagger, :
|
224
|
-
# 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' }
|
225
255
|
# end
|
226
256
|
def column(name, type, options = {})
|
227
|
-
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
257
|
+
name = name.to_s
|
258
|
+
type = type.to_sym
|
259
|
+
options = options.dup
|
260
|
+
|
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."
|
232
263
|
end
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
@columns << column unless @columns.include? column
|
264
|
+
|
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)
|
238
268
|
self
|
239
269
|
end
|
240
270
|
|
241
|
-
|
242
|
-
|
243
|
-
|
244
|
-
|
245
|
-
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
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])
|
250
293
|
end
|
251
294
|
|
252
295
|
# Appends <tt>:datetime</tt> columns <tt>:created_at</tt> and
|
253
|
-
# <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
|
254
299
|
def timestamps(*args)
|
255
300
|
options = args.extract_options!
|
301
|
+
emit_warning_if_null_unspecified(:timestamps, options)
|
256
302
|
column(:created_at, :datetime, options)
|
257
303
|
column(:updated_at, :datetime, options)
|
258
304
|
end
|
259
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.
|
260
312
|
def references(*args)
|
261
313
|
options = args.extract_options!
|
262
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
|
+
|
263
323
|
args.each do |col|
|
264
|
-
column("#{col}_id",
|
265
|
-
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
|
266
331
|
end
|
267
332
|
end
|
268
333
|
alias :belongs_to :references
|
269
334
|
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
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
|
275
351
|
end
|
276
352
|
|
277
353
|
private
|
278
|
-
|
279
|
-
|
280
|
-
|
354
|
+
def create_column_definition(name, type)
|
355
|
+
ColumnDefinition.new name, type
|
356
|
+
end
|
357
|
+
|
358
|
+
def native
|
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)
|
393
|
+
end
|
281
394
|
end
|
282
395
|
|
283
396
|
# Represents an SQL table in an abstract way for updating a table.
|
@@ -288,6 +401,7 @@ module ActiveRecord
|
|
288
401
|
# change_table :table do |t|
|
289
402
|
# t.column
|
290
403
|
# t.index
|
404
|
+
# t.rename_index
|
291
405
|
# t.timestamps
|
292
406
|
# t.change
|
293
407
|
# t.change_default
|
@@ -313,162 +427,152 @@ module ActiveRecord
|
|
313
427
|
# end
|
314
428
|
#
|
315
429
|
class Table
|
430
|
+
attr_reader :name
|
431
|
+
|
316
432
|
def initialize(table_name, base)
|
317
|
-
@
|
433
|
+
@name = table_name
|
318
434
|
@base = base
|
319
435
|
end
|
320
436
|
|
321
437
|
# Adds a new column to the named table.
|
322
438
|
# See TableDefinition#column for details of the options you can use.
|
323
|
-
#
|
439
|
+
#
|
324
440
|
# ====== Creating a simple column
|
325
441
|
# t.column(:name, :string)
|
326
442
|
def column(column_name, type, options = {})
|
327
|
-
@base.add_column(
|
443
|
+
@base.add_column(name, column_name, type, options)
|
328
444
|
end
|
329
445
|
|
330
446
|
# Checks to see if a column exists. See SchemaStatements#column_exists?
|
331
447
|
def column_exists?(column_name, type = nil, options = {})
|
332
|
-
@base.column_exists?(
|
448
|
+
@base.column_exists?(name, column_name, type, options)
|
333
449
|
end
|
334
450
|
|
335
451
|
# Adds a new index to the table. +column_name+ can be a single Symbol, or
|
336
452
|
# an Array of Symbols. See SchemaStatements#add_index
|
337
453
|
#
|
338
|
-
# ===== Examples
|
339
454
|
# ====== Creating a simple index
|
340
455
|
# t.index(:name)
|
341
456
|
# ====== Creating a unique index
|
342
|
-
# t.index([:branch_id, :party_id], :
|
457
|
+
# t.index([:branch_id, :party_id], unique: true)
|
343
458
|
# ====== Creating a named index
|
344
|
-
# t.index([:branch_id, :party_id], :
|
459
|
+
# t.index([:branch_id, :party_id], unique: true, name: 'by_branch_party')
|
345
460
|
def index(column_name, options = {})
|
346
|
-
@base.add_index(
|
461
|
+
@base.add_index(name, column_name, options)
|
347
462
|
end
|
348
463
|
|
349
464
|
# Checks to see if an index exists. See SchemaStatements#index_exists?
|
350
465
|
def index_exists?(column_name, options = {})
|
351
|
-
@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)
|
352
474
|
end
|
353
475
|
|
354
476
|
# Adds timestamps (+created_at+ and +updated_at+) columns to the table. See SchemaStatements#add_timestamps
|
355
|
-
#
|
356
|
-
# t.timestamps
|
357
|
-
def timestamps
|
358
|
-
@base.add_timestamps(
|
477
|
+
#
|
478
|
+
# t.timestamps null: false
|
479
|
+
def timestamps(options = {})
|
480
|
+
@base.add_timestamps(name, options)
|
359
481
|
end
|
360
482
|
|
361
483
|
# Changes the column's definition according to the new options.
|
362
484
|
# See TableDefinition#column for details of the options you can use.
|
363
|
-
#
|
364
|
-
# t.change(:name, :string, :
|
485
|
+
#
|
486
|
+
# t.change(:name, :string, limit: 80)
|
365
487
|
# t.change(:description, :text)
|
366
488
|
def change(column_name, type, options = {})
|
367
|
-
@base.change_column(
|
489
|
+
@base.change_column(name, column_name, type, options)
|
368
490
|
end
|
369
491
|
|
370
492
|
# Sets a new default value for a column. See SchemaStatements#change_column_default
|
371
|
-
#
|
493
|
+
#
|
372
494
|
# t.change_default(:qualification, 'new')
|
373
495
|
# t.change_default(:authorized, 1)
|
374
496
|
def change_default(column_name, default)
|
375
|
-
@base.change_column_default(
|
497
|
+
@base.change_column_default(name, column_name, default)
|
376
498
|
end
|
377
499
|
|
378
500
|
# Removes the column(s) from the table definition.
|
379
|
-
#
|
501
|
+
#
|
380
502
|
# t.remove(:qualification)
|
381
503
|
# t.remove(:qualification, :experience)
|
382
504
|
def remove(*column_names)
|
383
|
-
@base.
|
505
|
+
@base.remove_columns(name, *column_names)
|
384
506
|
end
|
385
507
|
|
386
508
|
# Removes the given index from the table.
|
387
509
|
#
|
388
|
-
# ===== Examples
|
389
510
|
# ====== Remove the index_table_name_on_column in the table_name table
|
390
511
|
# t.remove_index :column
|
391
512
|
# ====== Remove the index named index_table_name_on_branch_id in the table_name table
|
392
|
-
# t.remove_index :
|
513
|
+
# t.remove_index column: :branch_id
|
393
514
|
# ====== Remove the index named index_table_name_on_branch_id_and_party_id in the table_name table
|
394
|
-
# t.remove_index :
|
515
|
+
# t.remove_index column: [:branch_id, :party_id]
|
395
516
|
# ====== Remove the index named by_branch_party in the table_name table
|
396
|
-
# t.remove_index :
|
517
|
+
# t.remove_index name: :by_branch_party
|
397
518
|
def remove_index(options = {})
|
398
|
-
@base.remove_index(
|
519
|
+
@base.remove_index(name, options)
|
399
520
|
end
|
400
521
|
|
401
522
|
# Removes the timestamp columns (+created_at+ and +updated_at+) from the table.
|
402
|
-
#
|
523
|
+
#
|
403
524
|
# t.remove_timestamps
|
404
|
-
def remove_timestamps
|
405
|
-
@base.remove_timestamps(
|
525
|
+
def remove_timestamps(options = {})
|
526
|
+
@base.remove_timestamps(name, options)
|
406
527
|
end
|
407
528
|
|
408
529
|
# Renames a column.
|
409
|
-
#
|
530
|
+
#
|
410
531
|
# t.rename(:description, :name)
|
411
532
|
def rename(column_name, new_column_name)
|
412
|
-
@base.rename_column(
|
533
|
+
@base.rename_column(name, column_name, new_column_name)
|
413
534
|
end
|
414
535
|
|
415
|
-
# Adds a reference.
|
416
|
-
#
|
417
|
-
#
|
418
|
-
# t.
|
419
|
-
#
|
420
|
-
#
|
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.
|
421
542
|
def references(*args)
|
422
543
|
options = args.extract_options!
|
423
|
-
|
424
|
-
|
425
|
-
@base.add_column(@table_name, "#{col}_id", :integer, options)
|
426
|
-
@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)
|
427
546
|
end
|
428
547
|
end
|
429
548
|
alias :belongs_to :references
|
430
549
|
|
431
550
|
# Removes a reference. Optionally removes a +type+ column.
|
432
551
|
# <tt>remove_references</tt> and <tt>remove_belongs_to</tt> are acceptable.
|
433
|
-
#
|
434
|
-
# t.remove_references(:
|
435
|
-
# t.
|
436
|
-
#
|
552
|
+
#
|
553
|
+
# t.remove_references(:user)
|
554
|
+
# t.remove_belongs_to(:supplier, polymorphic: true)
|
555
|
+
#
|
556
|
+
# See SchemaStatements#remove_reference
|
437
557
|
def remove_references(*args)
|
438
558
|
options = args.extract_options!
|
439
|
-
|
440
|
-
|
441
|
-
@base.remove_column(@table_name, "#{col}_id")
|
442
|
-
@base.remove_column(@table_name, "#{col}_type") unless polymorphic.nil?
|
559
|
+
args.each do |ref_name|
|
560
|
+
@base.remove_reference(name, ref_name, options)
|
443
561
|
end
|
444
562
|
end
|
445
|
-
alias :remove_belongs_to
|
563
|
+
alias :remove_belongs_to :remove_references
|
446
564
|
|
447
565
|
# Adds a column or columns of a specified type
|
448
|
-
#
|
566
|
+
#
|
449
567
|
# t.string(:goat)
|
450
568
|
# t.string(:goat, :sheep)
|
451
|
-
|
452
|
-
|
453
|
-
|
454
|
-
|
455
|
-
|
456
|
-
|
457
|
-
|
458
|
-
column = ColumnDefinition.new(@base, name, '#{column_type}') # column = ColumnDefinition.new(@base, name, 'string')
|
459
|
-
if options[:limit] # if options[:limit]
|
460
|
-
column.limit = options[:limit] # column.limit = options[:limit]
|
461
|
-
elsif native['#{column_type}'.to_sym].is_a?(Hash) # elsif native['string'.to_sym].is_a?(Hash)
|
462
|
-
column.limit = native['#{column_type}'.to_sym][:limit] # column.limit = native['string'.to_sym][:limit]
|
463
|
-
end # end
|
464
|
-
column.precision = options[:precision] # column.precision = options[:precision]
|
465
|
-
column.scale = options[:scale] # column.scale = options[:scale]
|
466
|
-
column.default = options[:default] # column.default = options[:default]
|
467
|
-
column.null = options[:null] # column.null = options[:null]
|
468
|
-
@base.add_column(@table_name, name, column.sql_type, options) # @base.add_column(@table_name, name, column.sql_type, options)
|
469
|
-
end # end
|
470
|
-
end # end
|
471
|
-
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
|
472
576
|
end
|
473
577
|
|
474
578
|
private
|
@@ -476,6 +580,5 @@ module ActiveRecord
|
|
476
580
|
@base.native_database_types
|
477
581
|
end
|
478
582
|
end
|
479
|
-
|
480
583
|
end
|
481
584
|
end
|