activerecord 4.2.11.3 → 5.0.0.beta1
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 +1029 -1349
- data/MIT-LICENSE +1 -1
- data/README.rdoc +6 -7
- data/examples/performance.rb +2 -2
- data/lib/active_record.rb +7 -3
- data/lib/active_record/aggregations.rb +35 -25
- data/lib/active_record/association_relation.rb +2 -2
- data/lib/active_record/associations.rb +305 -204
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +10 -8
- data/lib/active_record/associations/association_scope.rb +73 -102
- data/lib/active_record/associations/belongs_to_association.rb +20 -32
- data/lib/active_record/associations/builder/association.rb +28 -34
- data/lib/active_record/associations/builder/belongs_to.rb +41 -18
- data/lib/active_record/associations/builder/collection_association.rb +8 -24
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +11 -11
- data/lib/active_record/associations/builder/has_many.rb +4 -4
- data/lib/active_record/associations/builder/has_one.rb +10 -5
- data/lib/active_record/associations/builder/singular_association.rb +2 -9
- data/lib/active_record/associations/collection_association.rb +40 -43
- data/lib/active_record/associations/collection_proxy.rb +55 -29
- data/lib/active_record/associations/foreign_association.rb +1 -1
- data/lib/active_record/associations/has_many_association.rb +20 -71
- data/lib/active_record/associations/has_many_through_association.rb +8 -52
- data/lib/active_record/associations/has_one_association.rb +12 -5
- data/lib/active_record/associations/join_dependency.rb +28 -18
- data/lib/active_record/associations/join_dependency/join_association.rb +13 -12
- data/lib/active_record/associations/preloader.rb +13 -4
- data/lib/active_record/associations/preloader/association.rb +45 -51
- data/lib/active_record/associations/preloader/collection_association.rb +0 -6
- data/lib/active_record/associations/preloader/has_many_through.rb +1 -1
- data/lib/active_record/associations/preloader/has_one.rb +0 -8
- data/lib/active_record/associations/preloader/through_association.rb +5 -4
- data/lib/active_record/associations/singular_association.rb +6 -0
- data/lib/active_record/associations/through_association.rb +11 -3
- data/lib/active_record/attribute.rb +61 -17
- data/lib/active_record/attribute/user_provided_default.rb +23 -0
- data/lib/active_record/attribute_assignment.rb +27 -140
- data/lib/active_record/attribute_decorators.rb +6 -5
- data/lib/active_record/attribute_methods.rb +79 -26
- data/lib/active_record/attribute_methods/before_type_cast.rb +1 -1
- data/lib/active_record/attribute_methods/dirty.rb +46 -86
- data/lib/active_record/attribute_methods/primary_key.rb +2 -2
- data/lib/active_record/attribute_methods/query.rb +2 -2
- data/lib/active_record/attribute_methods/read.rb +26 -42
- data/lib/active_record/attribute_methods/serialization.rb +13 -16
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +42 -9
- data/lib/active_record/attribute_methods/write.rb +13 -24
- data/lib/active_record/attribute_mutation_tracker.rb +70 -0
- data/lib/active_record/attribute_set.rb +30 -3
- data/lib/active_record/attribute_set/builder.rb +6 -4
- data/lib/active_record/attributes.rb +194 -81
- data/lib/active_record/autosave_association.rb +33 -15
- data/lib/active_record/base.rb +30 -18
- data/lib/active_record/callbacks.rb +36 -40
- data/lib/active_record/coders/yaml_column.rb +20 -8
- data/lib/active_record/collection_cache_key.rb +31 -0
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +431 -122
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +40 -22
- data/lib/active_record/connection_adapters/abstract/quoting.rb +62 -8
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +46 -38
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +229 -185
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +52 -13
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +275 -115
- data/lib/active_record/connection_adapters/abstract/transaction.rb +32 -33
- data/lib/active_record/connection_adapters/abstract_adapter.rb +83 -32
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +384 -221
- data/lib/active_record/connection_adapters/column.rb +27 -41
- data/lib/active_record/connection_adapters/connection_specification.rb +2 -21
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +22 -0
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +57 -0
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +69 -0
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +59 -0
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +22 -101
- data/lib/active_record/connection_adapters/postgresql/column.rb +6 -10
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +1 -6
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +23 -57
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bytea.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +7 -22
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +3 -3
- data/lib/active_record/connection_adapters/postgresql/oid/json.rb +1 -26
- data/lib/active_record/connection_adapters/postgresql/oid/jsonb.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/money.rb +0 -2
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +4 -4
- data/lib/active_record/connection_adapters/postgresql/oid/rails_5_1_point.rb +50 -0
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +23 -16
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +0 -4
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/vector.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/xml.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +18 -11
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +29 -10
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -79
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +54 -0
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +174 -128
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +35 -0
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +184 -112
- data/lib/active_record/connection_adapters/schema_cache.rb +36 -23
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +32 -0
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +15 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +134 -110
- data/lib/active_record/connection_adapters/statement_pool.rb +28 -11
- data/lib/active_record/connection_handling.rb +5 -5
- data/lib/active_record/core.rb +72 -104
- data/lib/active_record/counter_cache.rb +9 -20
- data/lib/active_record/dynamic_matchers.rb +1 -20
- data/lib/active_record/enum.rb +110 -76
- data/lib/active_record/errors.rb +72 -47
- data/lib/active_record/explain_registry.rb +1 -1
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +19 -4
- data/lib/active_record/fixtures.rb +76 -40
- data/lib/active_record/gem_version.rb +4 -4
- data/lib/active_record/inheritance.rb +27 -40
- data/lib/active_record/integration.rb +4 -4
- data/lib/active_record/legacy_yaml_adapter.rb +18 -2
- data/lib/active_record/locale/en.yml +3 -2
- data/lib/active_record/locking/optimistic.rb +10 -14
- data/lib/active_record/locking/pessimistic.rb +1 -1
- data/lib/active_record/log_subscriber.rb +40 -22
- data/lib/active_record/migration.rb +304 -133
- data/lib/active_record/migration/command_recorder.rb +59 -18
- data/lib/active_record/migration/compatibility.rb +90 -0
- data/lib/active_record/model_schema.rb +92 -40
- data/lib/active_record/nested_attributes.rb +45 -34
- data/lib/active_record/null_relation.rb +15 -7
- data/lib/active_record/persistence.rb +112 -72
- data/lib/active_record/querying.rb +6 -5
- data/lib/active_record/railtie.rb +20 -13
- data/lib/active_record/railties/controller_runtime.rb +1 -1
- data/lib/active_record/railties/databases.rake +47 -38
- data/lib/active_record/readonly_attributes.rb +1 -1
- data/lib/active_record/reflection.rb +182 -57
- data/lib/active_record/relation.rb +152 -100
- data/lib/active_record/relation/batches.rb +133 -33
- data/lib/active_record/relation/batches/batch_enumerator.rb +67 -0
- data/lib/active_record/relation/calculations.rb +80 -101
- data/lib/active_record/relation/delegation.rb +6 -19
- data/lib/active_record/relation/finder_methods.rb +58 -46
- data/lib/active_record/relation/from_clause.rb +32 -0
- data/lib/active_record/relation/merger.rb +13 -42
- data/lib/active_record/relation/predicate_builder.rb +99 -105
- data/lib/active_record/relation/predicate_builder/array_handler.rb +11 -16
- data/lib/active_record/relation/predicate_builder/association_query_handler.rb +78 -0
- data/lib/active_record/relation/predicate_builder/base_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +17 -0
- data/lib/active_record/relation/predicate_builder/class_handler.rb +27 -0
- data/lib/active_record/relation/predicate_builder/range_handler.rb +17 -0
- data/lib/active_record/relation/query_attribute.rb +19 -0
- data/lib/active_record/relation/query_methods.rb +274 -238
- data/lib/active_record/relation/record_fetch_warning.rb +51 -0
- data/lib/active_record/relation/spawn_methods.rb +3 -6
- data/lib/active_record/relation/where_clause.rb +173 -0
- data/lib/active_record/relation/where_clause_factory.rb +37 -0
- data/lib/active_record/result.rb +4 -3
- data/lib/active_record/runtime_registry.rb +1 -1
- data/lib/active_record/sanitization.rb +94 -65
- data/lib/active_record/schema.rb +23 -22
- data/lib/active_record/schema_dumper.rb +33 -22
- data/lib/active_record/schema_migration.rb +10 -4
- data/lib/active_record/scoping.rb +17 -6
- data/lib/active_record/scoping/default.rb +19 -6
- data/lib/active_record/scoping/named.rb +39 -28
- data/lib/active_record/secure_token.rb +38 -0
- data/lib/active_record/serialization.rb +2 -4
- data/lib/active_record/statement_cache.rb +15 -13
- data/lib/active_record/store.rb +8 -3
- data/lib/active_record/suppressor.rb +54 -0
- data/lib/active_record/table_metadata.rb +64 -0
- data/lib/active_record/tasks/database_tasks.rb +30 -40
- data/lib/active_record/tasks/mysql_database_tasks.rb +7 -15
- data/lib/active_record/tasks/postgresql_database_tasks.rb +11 -2
- data/lib/active_record/tasks/sqlite_database_tasks.rb +5 -1
- data/lib/active_record/timestamp.rb +16 -9
- data/lib/active_record/touch_later.rb +58 -0
- data/lib/active_record/transactions.rb +138 -56
- data/lib/active_record/type.rb +66 -17
- data/lib/active_record/type/adapter_specific_registry.rb +130 -0
- data/lib/active_record/type/date.rb +2 -45
- data/lib/active_record/type/date_time.rb +2 -49
- data/lib/active_record/type/internal/abstract_json.rb +33 -0
- data/lib/active_record/type/internal/timezone.rb +15 -0
- data/lib/active_record/type/serialized.rb +9 -14
- data/lib/active_record/type/time.rb +3 -21
- data/lib/active_record/type/type_map.rb +4 -4
- data/lib/active_record/type_caster.rb +7 -0
- data/lib/active_record/type_caster/connection.rb +29 -0
- data/lib/active_record/type_caster/map.rb +19 -0
- data/lib/active_record/validations.rb +33 -32
- data/lib/active_record/validations/absence.rb +24 -0
- data/lib/active_record/validations/associated.rb +10 -3
- data/lib/active_record/validations/length.rb +36 -0
- data/lib/active_record/validations/presence.rb +12 -12
- data/lib/active_record/validations/uniqueness.rb +24 -21
- data/lib/rails/generators/active_record/migration.rb +7 -0
- data/lib/rails/generators/active_record/migration/migration_generator.rb +7 -4
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb +8 -3
- data/lib/rails/generators/active_record/migration/templates/migration.rb +4 -1
- data/lib/rails/generators/active_record/model/model_generator.rb +21 -15
- data/lib/rails/generators/active_record/model/templates/model.rb +3 -0
- metadata +50 -35
- data/lib/active_record/connection_adapters/mysql_adapter.rb +0 -498
- data/lib/active_record/connection_adapters/postgresql/array_parser.rb +0 -93
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/float.rb +0 -21
- data/lib/active_record/connection_adapters/postgresql/oid/infinity.rb +0 -13
- data/lib/active_record/connection_adapters/postgresql/oid/integer.rb +0 -11
- data/lib/active_record/connection_adapters/postgresql/oid/time.rb +0 -11
- data/lib/active_record/serializers/xml_serializer.rb +0 -193
- data/lib/active_record/type/big_integer.rb +0 -13
- data/lib/active_record/type/binary.rb +0 -50
- data/lib/active_record/type/boolean.rb +0 -31
- data/lib/active_record/type/decimal.rb +0 -64
- data/lib/active_record/type/decimal_without_scale.rb +0 -11
- data/lib/active_record/type/decorator.rb +0 -14
- data/lib/active_record/type/float.rb +0 -19
- data/lib/active_record/type/integer.rb +0 -59
- data/lib/active_record/type/mutable.rb +0 -16
- data/lib/active_record/type/numeric.rb +0 -36
- data/lib/active_record/type/string.rb +0 -40
- data/lib/active_record/type/text.rb +0 -11
- data/lib/active_record/type/time_value.rb +0 -38
- data/lib/active_record/type/unsigned_integer.rb +0 -15
- data/lib/active_record/type/value.rb +0 -110
@@ -0,0 +1,38 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
module SecureToken
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
module ClassMethods
|
6
|
+
# Example using #has_secure_token
|
7
|
+
#
|
8
|
+
# # Schema: User(token:string, auth_token:string)
|
9
|
+
# class User < ActiveRecord::Base
|
10
|
+
# has_secure_token
|
11
|
+
# has_secure_token :auth_token
|
12
|
+
# end
|
13
|
+
#
|
14
|
+
# user = User.new
|
15
|
+
# user.save
|
16
|
+
# user.token # => "pX27zsMN2ViQKta1bGfLmVJE"
|
17
|
+
# user.auth_token # => "77TMHrHJFvFDwodq8w7Ev2m7"
|
18
|
+
# user.regenerate_token # => true
|
19
|
+
# user.regenerate_auth_token # => true
|
20
|
+
#
|
21
|
+
# <tt>SecureRandom::base58</tt> is used to generate the 24-character unique token, so collisions are highly unlikely.
|
22
|
+
#
|
23
|
+
# Note that it's still possible to generate a race condition in the database in the same way that
|
24
|
+
# {validates_uniqueness_of}[rdoc-ref:Validations::ClassMethods#validates_uniqueness_of] can.
|
25
|
+
# You're encouraged to add a unique index in the database to deal with this even more unlikely scenario.
|
26
|
+
def has_secure_token(attribute = :token)
|
27
|
+
# Load securerandom only when has_secure_token is used.
|
28
|
+
require 'active_support/core_ext/securerandom'
|
29
|
+
define_method("regenerate_#{attribute}") { update! attribute => self.class.generate_unique_secure_token }
|
30
|
+
before_create { self.send("#{attribute}=", self.class.generate_unique_secure_token) unless self.send("#{attribute}?")}
|
31
|
+
end
|
32
|
+
|
33
|
+
def generate_unique_secure_token
|
34
|
+
SecureRandom.base58(24)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module ActiveRecord #:nodoc:
|
2
|
-
# = Active Record Serialization
|
2
|
+
# = Active Record \Serialization
|
3
3
|
module Serialization
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
include ActiveModel::Serializers::JSON
|
@@ -11,12 +11,10 @@ module ActiveRecord #:nodoc:
|
|
11
11
|
def serializable_hash(options = nil)
|
12
12
|
options = options.try(:clone) || {}
|
13
13
|
|
14
|
-
options[:except] = Array(options[:except]).map
|
14
|
+
options[:except] = Array(options[:except]).map(&:to_s)
|
15
15
|
options[:except] |= Array(self.class.inheritance_column)
|
16
16
|
|
17
17
|
super(options)
|
18
18
|
end
|
19
19
|
end
|
20
20
|
end
|
21
|
-
|
22
|
-
require 'active_record/serializers/xml_serializer'
|
@@ -7,12 +7,14 @@ module ActiveRecord
|
|
7
7
|
# Book.where(name: "my book").where("author_id > 3")
|
8
8
|
# end
|
9
9
|
#
|
10
|
-
# The cached statement is executed by using the
|
10
|
+
# The cached statement is executed by using the
|
11
|
+
# [connection.execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute} method:
|
11
12
|
#
|
12
13
|
# cache.execute([], Book, Book.connection)
|
13
14
|
#
|
14
|
-
# The relation returned by the block is cached, and for each
|
15
|
-
#
|
15
|
+
# The relation returned by the block is cached, and for each
|
16
|
+
# [execute]{rdoc-ref:ConnectionAdapters::DatabaseStatements#execute}
|
17
|
+
# call the cached relation gets duped. Database is queried when +to_a+ is called on the relation.
|
16
18
|
#
|
17
19
|
# If you want to cache the statement without the values you can use the +bind+ method of the
|
18
20
|
# block parameter.
|
@@ -47,8 +49,8 @@ module ActiveRecord
|
|
47
49
|
|
48
50
|
def sql_for(binds, connection)
|
49
51
|
val = @values.dup
|
50
|
-
binds = binds
|
51
|
-
@indexes.each { |i| val[i] = connection.quote(
|
52
|
+
binds = connection.prepare_binds_for_database(binds)
|
53
|
+
@indexes.each { |i| val[i] = connection.quote(binds.shift) }
|
52
54
|
val.join
|
53
55
|
end
|
54
56
|
end
|
@@ -67,21 +69,21 @@ module ActiveRecord
|
|
67
69
|
end
|
68
70
|
|
69
71
|
class BindMap # :nodoc:
|
70
|
-
def initialize(
|
72
|
+
def initialize(bound_attributes)
|
71
73
|
@indexes = []
|
72
|
-
@
|
74
|
+
@bound_attributes = bound_attributes
|
73
75
|
|
74
|
-
|
75
|
-
if Substitute === value
|
76
|
+
bound_attributes.each_with_index do |attr, i|
|
77
|
+
if Substitute === attr.value
|
76
78
|
@indexes << i
|
77
79
|
end
|
78
80
|
end
|
79
81
|
end
|
80
82
|
|
81
83
|
def bind(values)
|
82
|
-
|
83
|
-
@indexes.each_with_index { |offset,i|
|
84
|
-
|
84
|
+
bas = @bound_attributes.dup
|
85
|
+
@indexes.each_with_index { |offset,i| bas[offset] = bas[offset].with_cast_value(values[i]) }
|
86
|
+
bas
|
85
87
|
end
|
86
88
|
end
|
87
89
|
|
@@ -89,7 +91,7 @@ module ActiveRecord
|
|
89
91
|
|
90
92
|
def self.create(connection, block = Proc.new)
|
91
93
|
relation = block.call Params.new
|
92
|
-
bind_map = BindMap.new relation.
|
94
|
+
bind_map = BindMap.new relation.bound_attributes
|
93
95
|
query_builder = connection.cacheable_query relation.arel
|
94
96
|
new query_builder, bind_map
|
95
97
|
end
|
data/lib/active_record/store.rb
CHANGED
@@ -15,11 +15,16 @@ module ActiveRecord
|
|
15
15
|
# You can set custom coder to encode/decode your serialized attributes to/from different formats.
|
16
16
|
# JSON, YAML, Marshal are supported out of the box. Generally it can be any wrapper that provides +load+ and +dump+.
|
17
17
|
#
|
18
|
-
# NOTE
|
19
|
-
# the serialization provided by
|
18
|
+
# NOTE: If you are using PostgreSQL specific columns like +hstore+ or +json+ there is no need for
|
19
|
+
# the serialization provided by {.store}[rdoc-ref:rdoc-ref:ClassMethods#store].
|
20
|
+
# Simply use {.store_accessor}[rdoc-ref:ClassMethods#store_accessor] instead to generate
|
20
21
|
# the accessor methods. Be aware that these columns use a string keyed hash and do not allow access
|
21
22
|
# using a symbol.
|
22
23
|
#
|
24
|
+
# NOTE: The default validations with the exception of +uniqueness+ will work.
|
25
|
+
# For example, if you want to check for +uniqueness+ with +hstore+ you will
|
26
|
+
# need to use a custom validation to handle it.
|
27
|
+
#
|
23
28
|
# Examples:
|
24
29
|
#
|
25
30
|
# class User < ActiveRecord::Base
|
@@ -39,7 +44,7 @@ module ActiveRecord
|
|
39
44
|
# store_accessor :settings, :privileges, :servants
|
40
45
|
# end
|
41
46
|
#
|
42
|
-
# The stored attribute names can be retrieved using
|
47
|
+
# The stored attribute names can be retrieved using {.stored_attributes}[rdoc-ref:rdoc-ref:ClassMethods#stored_attributes].
|
43
48
|
#
|
44
49
|
# User.stored_attributes[:settings] # [:color, :homepage]
|
45
50
|
#
|
@@ -0,0 +1,54 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
# ActiveRecord::Suppressor prevents the receiver from being saved during
|
3
|
+
# a given block.
|
4
|
+
#
|
5
|
+
# For example, here's a pattern of creating notifications when new comments
|
6
|
+
# are posted. (The notification may in turn trigger an email, a push
|
7
|
+
# notification, or just appear in the UI somewhere):
|
8
|
+
#
|
9
|
+
# class Comment < ActiveRecord::Base
|
10
|
+
# belongs_to :commentable, polymorphic: true
|
11
|
+
# after_create -> { Notification.create! comment: self,
|
12
|
+
# recipients: commentable.recipients }
|
13
|
+
# end
|
14
|
+
#
|
15
|
+
# That's what you want the bulk of the time. New comment creates a new
|
16
|
+
# Notification. But there may well be off cases, like copying a commentable
|
17
|
+
# and its comments, where you don't want that. So you'd have a concern
|
18
|
+
# something like this:
|
19
|
+
#
|
20
|
+
# module Copyable
|
21
|
+
# def copy_to(destination)
|
22
|
+
# Notification.suppress do
|
23
|
+
# # Copy logic that creates new comments that we do not want
|
24
|
+
# # triggering notifications.
|
25
|
+
# end
|
26
|
+
# end
|
27
|
+
# end
|
28
|
+
module Suppressor
|
29
|
+
extend ActiveSupport::Concern
|
30
|
+
|
31
|
+
module ClassMethods
|
32
|
+
def suppress(&block)
|
33
|
+
SuppressorRegistry.suppressed[name] = true
|
34
|
+
yield
|
35
|
+
ensure
|
36
|
+
SuppressorRegistry.suppressed[name] = false
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def create_or_update(*args) # :nodoc:
|
41
|
+
SuppressorRegistry.suppressed[self.class.name] ? true : super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
class SuppressorRegistry # :nodoc:
|
46
|
+
extend ActiveSupport::PerThreadRegistry
|
47
|
+
|
48
|
+
attr_reader :suppressed
|
49
|
+
|
50
|
+
def initialize
|
51
|
+
@suppressed = {}
|
52
|
+
end
|
53
|
+
end
|
54
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class TableMetadata # :nodoc:
|
3
|
+
delegate :foreign_type, :foreign_key, to: :association, prefix: true
|
4
|
+
delegate :association_primary_key, to: :association
|
5
|
+
|
6
|
+
def initialize(klass, arel_table, association = nil)
|
7
|
+
@klass = klass
|
8
|
+
@arel_table = arel_table
|
9
|
+
@association = association
|
10
|
+
end
|
11
|
+
|
12
|
+
def resolve_column_aliases(hash)
|
13
|
+
# This method is a hot spot, so for now, use Hash[] to dup the hash.
|
14
|
+
# https://bugs.ruby-lang.org/issues/7166
|
15
|
+
new_hash = Hash[hash]
|
16
|
+
hash.each do |key, _|
|
17
|
+
if (key.is_a?(Symbol)) && klass.attribute_alias?(key)
|
18
|
+
new_hash[klass.attribute_alias(key)] = new_hash.delete(key)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
new_hash
|
22
|
+
end
|
23
|
+
|
24
|
+
def arel_attribute(column_name)
|
25
|
+
arel_table[column_name]
|
26
|
+
end
|
27
|
+
|
28
|
+
def type(column_name)
|
29
|
+
if klass
|
30
|
+
klass.type_for_attribute(column_name.to_s)
|
31
|
+
else
|
32
|
+
Type::Value.new
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def associated_with?(association_name)
|
37
|
+
klass && klass._reflect_on_association(association_name)
|
38
|
+
end
|
39
|
+
|
40
|
+
def associated_table(table_name)
|
41
|
+
return self if table_name == arel_table.name
|
42
|
+
|
43
|
+
association = klass._reflect_on_association(table_name)
|
44
|
+
if association && !association.polymorphic?
|
45
|
+
association_klass = association.klass
|
46
|
+
arel_table = association_klass.arel_table.alias(table_name)
|
47
|
+
else
|
48
|
+
type_caster = TypeCaster::Connection.new(klass, table_name)
|
49
|
+
association_klass = nil
|
50
|
+
arel_table = Arel::Table.new(table_name, type_caster: type_caster)
|
51
|
+
end
|
52
|
+
|
53
|
+
TableMetadata.new(association_klass, arel_table, association)
|
54
|
+
end
|
55
|
+
|
56
|
+
def polymorphic_association?
|
57
|
+
association && association.polymorphic?
|
58
|
+
end
|
59
|
+
|
60
|
+
protected
|
61
|
+
|
62
|
+
attr_reader :klass, :arel_table, :association
|
63
|
+
end
|
64
|
+
end
|
@@ -5,7 +5,7 @@ module ActiveRecord
|
|
5
5
|
class DatabaseAlreadyExists < StandardError; end # :nodoc:
|
6
6
|
class DatabaseNotSupported < StandardError; end # :nodoc:
|
7
7
|
|
8
|
-
#
|
8
|
+
# ActiveRecord::Tasks::DatabaseTasks is a utility class, which encapsulates
|
9
9
|
# logic behind common tasks used to manage database and migrations.
|
10
10
|
#
|
11
11
|
# The tasks defined here are used with Rake tasks provided by Active Record.
|
@@ -18,15 +18,15 @@ module ActiveRecord
|
|
18
18
|
#
|
19
19
|
# The possible config values are:
|
20
20
|
#
|
21
|
-
#
|
22
|
-
#
|
23
|
-
#
|
24
|
-
#
|
25
|
-
#
|
26
|
-
#
|
27
|
-
#
|
21
|
+
# * +env+: current environment (like Rails.env).
|
22
|
+
# * +database_configuration+: configuration of your databases (as in +config/database.yml+).
|
23
|
+
# * +db_dir+: your +db+ directory.
|
24
|
+
# * +fixtures_path+: a path to fixtures directory.
|
25
|
+
# * +migrations_paths+: a list of paths to directories with migrations.
|
26
|
+
# * +seed_loader+: an object which will load seeds, it needs to respond to the +load_seed+ method.
|
27
|
+
# * +root+: a path to the root of the application.
|
28
28
|
#
|
29
|
-
# Example usage of
|
29
|
+
# Example usage of DatabaseTasks outside Rails could look as such:
|
30
30
|
#
|
31
31
|
# include ActiveRecord::Tasks
|
32
32
|
# DatabaseTasks.database_configuration = YAML.load_file('my_database_config.yml')
|
@@ -94,8 +94,9 @@ module ActiveRecord
|
|
94
94
|
rescue DatabaseAlreadyExists
|
95
95
|
$stderr.puts "#{configuration['database']} already exists"
|
96
96
|
rescue Exception => error
|
97
|
-
$stderr.puts error
|
97
|
+
$stderr.puts error
|
98
98
|
$stderr.puts "Couldn't create database for #{configuration.inspect}"
|
99
|
+
raise
|
99
100
|
end
|
100
101
|
|
101
102
|
def create_all
|
@@ -115,8 +116,9 @@ module ActiveRecord
|
|
115
116
|
rescue ActiveRecord::NoDatabaseError
|
116
117
|
$stderr.puts "Database '#{configuration['database']}' does not exist"
|
117
118
|
rescue Exception => error
|
118
|
-
$stderr.puts error
|
119
|
+
$stderr.puts error
|
119
120
|
$stderr.puts "Couldn't drop #{configuration['database']}"
|
121
|
+
raise
|
120
122
|
end
|
121
123
|
|
122
124
|
def drop_all
|
@@ -130,8 +132,6 @@ module ActiveRecord
|
|
130
132
|
end
|
131
133
|
|
132
134
|
def migrate
|
133
|
-
raise "Empty VERSION provided" if ENV["VERSION"] && ENV["VERSION"].empty?
|
134
|
-
|
135
135
|
verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true
|
136
136
|
version = ENV["VERSION"] ? ENV["VERSION"].to_i : nil
|
137
137
|
scope = ENV['SCOPE']
|
@@ -139,7 +139,6 @@ module ActiveRecord
|
|
139
139
|
Migrator.migrate(migrations_paths, version) do |migration|
|
140
140
|
scope.blank? || scope == migration.scope
|
141
141
|
end
|
142
|
-
ActiveRecord::Base.clear_cache!
|
143
142
|
ensure
|
144
143
|
Migration.verbose = verbose_was
|
145
144
|
end
|
@@ -191,27 +190,7 @@ module ActiveRecord
|
|
191
190
|
class_for_adapter(configuration['adapter']).new(*arguments).structure_load(filename)
|
192
191
|
end
|
193
192
|
|
194
|
-
def load_schema(format = ActiveRecord::Base.schema_format, file = nil)
|
195
|
-
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
196
|
-
This method will act on a specific connection in the future.
|
197
|
-
To act on the current connection, use `load_schema_current` instead.
|
198
|
-
MSG
|
199
|
-
|
200
|
-
load_schema_current(format, file)
|
201
|
-
end
|
202
|
-
|
203
|
-
def schema_file(format = ActiveRecord::Base.schema_format)
|
204
|
-
case format
|
205
|
-
when :ruby
|
206
|
-
File.join(db_dir, "schema.rb")
|
207
|
-
when :sql
|
208
|
-
File.join(db_dir, "structure.sql")
|
209
|
-
end
|
210
|
-
end
|
211
|
-
|
212
|
-
# This method is the successor of +load_schema+. We should rename it
|
213
|
-
# after +load_schema+ went through a deprecation cycle. (Rails > 4.2)
|
214
|
-
def load_schema_for(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
193
|
+
def load_schema(configuration, format = ActiveRecord::Base.schema_format, file = nil) # :nodoc:
|
215
194
|
file ||= schema_file(format)
|
216
195
|
|
217
196
|
case format
|
@@ -227,22 +206,33 @@ module ActiveRecord
|
|
227
206
|
end
|
228
207
|
end
|
229
208
|
|
230
|
-
def
|
231
|
-
|
232
|
-
|
209
|
+
def load_schema_for(*args)
|
210
|
+
ActiveSupport::Deprecation.warn(<<-MSG.squish)
|
211
|
+
This method was renamed to `#load_schema` and will be removed in the future.
|
212
|
+
Use `#load_schema` instead.
|
213
|
+
MSG
|
214
|
+
load_schema(*args)
|
215
|
+
end
|
216
|
+
|
217
|
+
def schema_file(format = ActiveRecord::Base.schema_format)
|
218
|
+
case format
|
219
|
+
when :ruby
|
220
|
+
File.join(db_dir, "schema.rb")
|
221
|
+
when :sql
|
222
|
+
File.join(db_dir, "structure.sql")
|
233
223
|
end
|
234
224
|
end
|
235
225
|
|
236
226
|
def load_schema_current(format = ActiveRecord::Base.schema_format, file = nil, environment = env)
|
237
227
|
each_current_configuration(environment) { |configuration|
|
238
|
-
|
228
|
+
load_schema configuration, format, file
|
239
229
|
}
|
240
230
|
ActiveRecord::Base.establish_connection(environment.to_sym)
|
241
231
|
end
|
242
232
|
|
243
233
|
def check_schema_file(filename)
|
244
234
|
unless File.exist?(filename)
|
245
|
-
message = %{#{filename} doesn't exist yet. Run `
|
235
|
+
message = %{#{filename} doesn't exist yet. Run `rails db:migrate` to create it, then try again.}
|
246
236
|
message << %{ If you do not intend to use a database, you should instead alter #{Rails.root}/config/application.rb to limit the frameworks that will be loaded.} if defined?(::Rails)
|
247
237
|
Kernel.abort message
|
248
238
|
end
|
@@ -1,8 +1,6 @@
|
|
1
1
|
module ActiveRecord
|
2
2
|
module Tasks # :nodoc:
|
3
3
|
class MySQLDatabaseTasks # :nodoc:
|
4
|
-
DEFAULT_CHARSET = ENV['CHARSET'] || 'utf8'
|
5
|
-
DEFAULT_COLLATION = ENV['COLLATION'] || 'utf8_unicode_ci'
|
6
4
|
ACCESS_DENIED_ERROR = 1045
|
7
5
|
|
8
6
|
delegate :connection, :establish_connection, to: ActiveRecord::Base
|
@@ -23,7 +21,7 @@ module ActiveRecord
|
|
23
21
|
end
|
24
22
|
rescue error_class => error
|
25
23
|
if error.respond_to?(:errno) && error.errno == ACCESS_DENIED_ERROR
|
26
|
-
$stdout.print error.
|
24
|
+
$stdout.print error.message
|
27
25
|
establish_connection root_configuration_without_database
|
28
26
|
connection.create_database configuration['database'], creation_options
|
29
27
|
if configuration['username'] != 'root'
|
@@ -59,6 +57,7 @@ module ActiveRecord
|
|
59
57
|
args = prepare_command_options
|
60
58
|
args.concat(["--result-file", "#{filename}"])
|
61
59
|
args.concat(["--no-data"])
|
60
|
+
args.concat(["--routines"])
|
62
61
|
args.concat(["#{configuration['database']}"])
|
63
62
|
|
64
63
|
run_cmd('mysqldump', args, 'dumping')
|
@@ -86,12 +85,6 @@ module ActiveRecord
|
|
86
85
|
Hash.new.tap do |options|
|
87
86
|
options[:charset] = configuration['encoding'] if configuration.include? 'encoding'
|
88
87
|
options[:collation] = configuration['collation'] if configuration.include? 'collation'
|
89
|
-
|
90
|
-
# Set default charset only when collation isn't set.
|
91
|
-
options[:charset] ||= DEFAULT_CHARSET unless options[:collation]
|
92
|
-
|
93
|
-
# Set default collation only when charset is also default.
|
94
|
-
options[:collation] ||= DEFAULT_COLLATION if options[:charset] == DEFAULT_CHARSET
|
95
88
|
end
|
96
89
|
end
|
97
90
|
|
@@ -101,8 +94,6 @@ module ActiveRecord
|
|
101
94
|
ArJdbcMySQL::Error
|
102
95
|
elsif defined?(Mysql2)
|
103
96
|
Mysql2::Error
|
104
|
-
elsif defined?(Mysql)
|
105
|
-
Mysql::Error
|
106
97
|
else
|
107
98
|
StandardError
|
108
99
|
end
|
@@ -129,7 +120,7 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
129
120
|
end
|
130
121
|
|
131
122
|
def prepare_command_options
|
132
|
-
{
|
123
|
+
args = {
|
133
124
|
'host' => '--host',
|
134
125
|
'port' => '--port',
|
135
126
|
'socket' => '--socket',
|
@@ -139,9 +130,11 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
139
130
|
'sslca' => '--ssl-ca',
|
140
131
|
'sslcert' => '--ssl-cert',
|
141
132
|
'sslcapath' => '--ssl-capath',
|
142
|
-
'sslcipher' => '--
|
133
|
+
'sslcipher' => '--ssh-cipher',
|
143
134
|
'sslkey' => '--ssl-key'
|
144
135
|
}.map { |opt, arg| "#{arg}=#{configuration[opt]}" if configuration[opt] }.compact
|
136
|
+
|
137
|
+
args
|
145
138
|
end
|
146
139
|
|
147
140
|
def run_cmd(cmd, args, action)
|
@@ -149,8 +142,7 @@ IDENTIFIED BY '#{configuration['password']}' WITH GRANT OPTION;
|
|
149
142
|
end
|
150
143
|
|
151
144
|
def run_cmd_error(cmd, args, action)
|
152
|
-
msg = "failed to execute
|
153
|
-
msg << "#{cmd}"
|
145
|
+
msg = "failed to execute: `#{cmd}`\n"
|
154
146
|
msg << "Please check the output above for any errors and make sure that `#{cmd}` is installed in your PATH and has proper permissions.\n\n"
|
155
147
|
msg
|
156
148
|
end
|