activerecord 5.2.8.1 → 6.1.6.1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1255 -596
- data/MIT-LICENSE +3 -1
- data/README.rdoc +7 -5
- data/examples/performance.rb +1 -1
- data/lib/active_record/aggregations.rb +9 -8
- data/lib/active_record/association_relation.rb +30 -10
- data/lib/active_record/associations/alias_tracker.rb +19 -16
- data/lib/active_record/associations/association.rb +100 -41
- data/lib/active_record/associations/association_scope.rb +23 -21
- data/lib/active_record/associations/belongs_to_association.rb +55 -48
- data/lib/active_record/associations/belongs_to_polymorphic_association.rb +7 -6
- data/lib/active_record/associations/builder/association.rb +45 -22
- data/lib/active_record/associations/builder/belongs_to.rb +29 -59
- data/lib/active_record/associations/builder/collection_association.rb +8 -17
- data/lib/active_record/associations/builder/has_and_belongs_to_many.rb +17 -41
- data/lib/active_record/associations/builder/has_many.rb +8 -2
- data/lib/active_record/associations/builder/has_one.rb +33 -2
- data/lib/active_record/associations/builder/singular_association.rb +3 -1
- data/lib/active_record/associations/collection_association.rb +44 -34
- data/lib/active_record/associations/collection_proxy.rb +25 -21
- data/lib/active_record/associations/foreign_association.rb +20 -0
- data/lib/active_record/associations/has_many_association.rb +26 -13
- data/lib/active_record/associations/has_many_through_association.rb +24 -18
- data/lib/active_record/associations/has_one_association.rb +43 -31
- data/lib/active_record/associations/has_one_through_association.rb +5 -5
- data/lib/active_record/associations/join_dependency/join_association.rb +44 -22
- data/lib/active_record/associations/join_dependency/join_part.rb +5 -5
- data/lib/active_record/associations/join_dependency.rb +91 -60
- data/lib/active_record/associations/preloader/association.rb +69 -43
- data/lib/active_record/associations/preloader/through_association.rb +49 -40
- data/lib/active_record/associations/preloader.rb +47 -34
- data/lib/active_record/associations/singular_association.rb +3 -17
- data/lib/active_record/associations/through_association.rb +1 -1
- data/lib/active_record/associations.rb +137 -25
- data/lib/active_record/attribute_assignment.rb +17 -19
- data/lib/active_record/attribute_methods/before_type_cast.rb +13 -7
- data/lib/active_record/attribute_methods/dirty.rb +101 -40
- data/lib/active_record/attribute_methods/primary_key.rb +20 -25
- data/lib/active_record/attribute_methods/query.rb +4 -8
- data/lib/active_record/attribute_methods/read.rb +14 -56
- data/lib/active_record/attribute_methods/serialization.rb +12 -7
- data/lib/active_record/attribute_methods/time_zone_conversion.rb +12 -15
- data/lib/active_record/attribute_methods/write.rb +18 -34
- data/lib/active_record/attribute_methods.rb +81 -143
- data/lib/active_record/attributes.rb +46 -9
- data/lib/active_record/autosave_association.rb +57 -42
- data/lib/active_record/base.rb +4 -17
- data/lib/active_record/callbacks.rb +158 -43
- data/lib/active_record/coders/yaml_column.rb +1 -2
- data/lib/active_record/connection_adapters/abstract/connection_pool.rb +272 -130
- data/lib/active_record/connection_adapters/abstract/database_limits.rb +7 -36
- data/lib/active_record/connection_adapters/abstract/database_statements.rb +167 -146
- data/lib/active_record/connection_adapters/abstract/query_cache.rb +18 -14
- data/lib/active_record/connection_adapters/abstract/quoting.rb +98 -47
- data/lib/active_record/connection_adapters/abstract/savepoints.rb +3 -3
- data/lib/active_record/connection_adapters/abstract/schema_creation.rb +153 -110
- data/lib/active_record/connection_adapters/abstract/schema_definitions.rb +211 -90
- data/lib/active_record/connection_adapters/abstract/schema_dumper.rb +2 -4
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +385 -144
- data/lib/active_record/connection_adapters/abstract/transaction.rb +167 -69
- data/lib/active_record/connection_adapters/abstract_adapter.rb +229 -99
- data/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +243 -275
- data/lib/active_record/connection_adapters/column.rb +30 -12
- data/lib/active_record/connection_adapters/deduplicable.rb +29 -0
- data/lib/active_record/connection_adapters/legacy_pool_manager.rb +35 -0
- data/lib/active_record/connection_adapters/mysql/column.rb +1 -1
- data/lib/active_record/connection_adapters/mysql/database_statements.rb +88 -32
- data/lib/active_record/connection_adapters/mysql/explain_pretty_printer.rb +1 -2
- data/lib/active_record/connection_adapters/mysql/quoting.rb +59 -7
- data/lib/active_record/connection_adapters/mysql/schema_creation.rb +34 -10
- data/lib/active_record/connection_adapters/mysql/schema_definitions.rb +48 -32
- data/lib/active_record/connection_adapters/mysql/schema_dumper.rb +18 -7
- data/lib/active_record/connection_adapters/mysql/schema_statements.rb +142 -19
- data/lib/active_record/connection_adapters/mysql/type_metadata.rb +14 -9
- data/lib/active_record/connection_adapters/mysql2_adapter.rb +53 -18
- data/lib/active_record/connection_adapters/pool_config.rb +73 -0
- data/lib/active_record/connection_adapters/pool_manager.rb +47 -0
- data/lib/active_record/connection_adapters/postgresql/column.rb +37 -28
- data/lib/active_record/connection_adapters/postgresql/database_statements.rb +40 -54
- data/lib/active_record/connection_adapters/postgresql/oid/array.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/bit.rb +1 -4
- data/lib/active_record/connection_adapters/postgresql/oid/cidr.rb +3 -5
- data/lib/active_record/connection_adapters/postgresql/oid/date.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/oid/date_time.rb +10 -2
- data/lib/active_record/connection_adapters/postgresql/oid/enum.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/oid/hstore.rb +1 -2
- data/lib/active_record/connection_adapters/postgresql/oid/interval.rb +49 -0
- data/lib/active_record/connection_adapters/postgresql/oid/legacy_point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/macaddr.rb +25 -0
- data/lib/active_record/connection_adapters/postgresql/oid/oid.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/point.rb +3 -4
- data/lib/active_record/connection_adapters/postgresql/oid/range.rb +25 -7
- data/lib/active_record/connection_adapters/postgresql/oid/specialized_string.rb +1 -1
- data/lib/active_record/connection_adapters/postgresql/oid/type_map_initializer.rb +9 -7
- data/lib/active_record/connection_adapters/postgresql/oid/uuid.rb +15 -3
- data/lib/active_record/connection_adapters/postgresql/oid.rb +2 -0
- data/lib/active_record/connection_adapters/postgresql/quoting.rb +47 -10
- data/lib/active_record/connection_adapters/postgresql/referential_integrity.rb +2 -2
- data/lib/active_record/connection_adapters/postgresql/schema_creation.rb +19 -4
- data/lib/active_record/connection_adapters/postgresql/schema_definitions.rb +107 -91
- data/lib/active_record/connection_adapters/postgresql/schema_dumper.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql/schema_statements.rb +120 -100
- data/lib/active_record/connection_adapters/postgresql/type_metadata.rb +31 -26
- data/lib/active_record/connection_adapters/postgresql/utils.rb +0 -1
- data/lib/active_record/connection_adapters/postgresql_adapter.rb +224 -120
- data/lib/active_record/connection_adapters/schema_cache.rb +159 -21
- data/lib/active_record/connection_adapters/sql_type_metadata.rb +17 -6
- data/lib/active_record/connection_adapters/sqlite3/database_statements.rb +146 -0
- data/lib/active_record/connection_adapters/sqlite3/quoting.rb +42 -7
- data/lib/active_record/connection_adapters/sqlite3/schema_creation.rb +5 -1
- data/lib/active_record/connection_adapters/sqlite3/schema_statements.rb +77 -13
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +174 -186
- data/lib/active_record/connection_adapters/statement_pool.rb +0 -1
- data/lib/active_record/connection_adapters.rb +52 -0
- data/lib/active_record/connection_handling.rb +293 -33
- data/lib/active_record/core.rb +333 -98
- data/lib/active_record/counter_cache.rb +8 -30
- data/lib/active_record/database_configurations/connection_url_resolver.rb +99 -0
- data/lib/active_record/database_configurations/database_config.rb +80 -0
- data/lib/active_record/database_configurations/hash_config.rb +96 -0
- data/lib/active_record/database_configurations/url_config.rb +53 -0
- data/lib/active_record/database_configurations.rb +273 -0
- data/lib/active_record/delegated_type.rb +209 -0
- data/lib/active_record/destroy_association_async_job.rb +36 -0
- data/lib/active_record/dynamic_matchers.rb +3 -4
- data/lib/active_record/enum.rb +108 -36
- data/lib/active_record/errors.rb +62 -19
- data/lib/active_record/explain.rb +10 -6
- data/lib/active_record/explain_subscriber.rb +1 -1
- data/lib/active_record/fixture_set/file.rb +10 -17
- data/lib/active_record/fixture_set/model_metadata.rb +32 -0
- data/lib/active_record/fixture_set/render_context.rb +17 -0
- data/lib/active_record/fixture_set/table_row.rb +152 -0
- data/lib/active_record/fixture_set/table_rows.rb +46 -0
- data/lib/active_record/fixtures.rb +200 -481
- data/lib/active_record/gem_version.rb +3 -3
- data/lib/active_record/inheritance.rb +53 -24
- data/lib/active_record/insert_all.rb +212 -0
- data/lib/active_record/integration.rb +67 -17
- data/lib/active_record/internal_metadata.rb +28 -9
- data/lib/active_record/legacy_yaml_adapter.rb +7 -3
- data/lib/active_record/locking/optimistic.rb +37 -23
- data/lib/active_record/locking/pessimistic.rb +9 -5
- data/lib/active_record/log_subscriber.rb +35 -35
- data/lib/active_record/middleware/database_selector/resolver/session.rb +48 -0
- data/lib/active_record/middleware/database_selector/resolver.rb +92 -0
- data/lib/active_record/middleware/database_selector.rb +77 -0
- data/lib/active_record/migration/command_recorder.rb +96 -44
- data/lib/active_record/migration/compatibility.rb +145 -64
- data/lib/active_record/migration/join_table.rb +0 -1
- data/lib/active_record/migration.rb +206 -157
- data/lib/active_record/model_schema.rb +148 -22
- data/lib/active_record/nested_attributes.rb +4 -7
- data/lib/active_record/no_touching.rb +8 -1
- data/lib/active_record/null_relation.rb +0 -1
- data/lib/active_record/persistence.rb +267 -59
- data/lib/active_record/query_cache.rb +21 -4
- data/lib/active_record/querying.rb +40 -23
- data/lib/active_record/railtie.rb +116 -59
- data/lib/active_record/railties/console_sandbox.rb +2 -4
- data/lib/active_record/railties/controller_runtime.rb +30 -35
- data/lib/active_record/railties/databases.rake +411 -80
- data/lib/active_record/readonly_attributes.rb +4 -0
- data/lib/active_record/reflection.rb +109 -93
- data/lib/active_record/relation/batches/batch_enumerator.rb +25 -9
- data/lib/active_record/relation/batches.rb +44 -35
- data/lib/active_record/relation/calculations.rb +157 -90
- data/lib/active_record/relation/delegation.rb +35 -50
- data/lib/active_record/relation/finder_methods.rb +64 -39
- data/lib/active_record/relation/from_clause.rb +5 -1
- data/lib/active_record/relation/merger.rb +32 -40
- data/lib/active_record/relation/predicate_builder/array_handler.rb +13 -13
- data/lib/active_record/relation/predicate_builder/association_query_value.rb +5 -9
- data/lib/active_record/relation/predicate_builder/basic_object_handler.rb +1 -2
- data/lib/active_record/relation/predicate_builder/polymorphic_array_value.rb +11 -10
- data/lib/active_record/relation/predicate_builder/range_handler.rb +3 -23
- data/lib/active_record/relation/predicate_builder/relation_handler.rb +1 -1
- data/lib/active_record/relation/predicate_builder.rb +62 -45
- data/lib/active_record/relation/query_attribute.rb +13 -8
- data/lib/active_record/relation/query_methods.rb +476 -187
- data/lib/active_record/relation/record_fetch_warning.rb +3 -3
- data/lib/active_record/relation/spawn_methods.rb +9 -9
- data/lib/active_record/relation/where_clause.rb +115 -62
- data/lib/active_record/relation.rb +379 -115
- data/lib/active_record/result.rb +64 -38
- data/lib/active_record/runtime_registry.rb +2 -2
- data/lib/active_record/sanitization.rb +22 -41
- data/lib/active_record/schema.rb +2 -11
- data/lib/active_record/schema_dumper.rb +54 -9
- data/lib/active_record/schema_migration.rb +7 -9
- data/lib/active_record/scoping/default.rb +4 -8
- data/lib/active_record/scoping/named.rb +17 -24
- data/lib/active_record/scoping.rb +8 -9
- data/lib/active_record/secure_token.rb +16 -8
- data/lib/active_record/serialization.rb +5 -3
- data/lib/active_record/signed_id.rb +116 -0
- data/lib/active_record/statement_cache.rb +49 -6
- data/lib/active_record/store.rb +88 -9
- data/lib/active_record/suppressor.rb +2 -2
- data/lib/active_record/table_metadata.rb +42 -43
- data/lib/active_record/tasks/database_tasks.rb +277 -81
- data/lib/active_record/tasks/mysql_database_tasks.rb +37 -39
- data/lib/active_record/tasks/postgresql_database_tasks.rb +27 -32
- data/lib/active_record/tasks/sqlite_database_tasks.rb +14 -17
- data/lib/active_record/test_databases.rb +24 -0
- data/lib/active_record/test_fixtures.rb +287 -0
- data/lib/active_record/timestamp.rb +43 -32
- data/lib/active_record/touch_later.rb +23 -22
- data/lib/active_record/transactions.rb +62 -118
- data/lib/active_record/translation.rb +1 -1
- data/lib/active_record/type/adapter_specific_registry.rb +3 -13
- data/lib/active_record/type/hash_lookup_type_map.rb +0 -1
- data/lib/active_record/type/serialized.rb +6 -3
- data/lib/active_record/type/time.rb +10 -0
- data/lib/active_record/type/type_map.rb +0 -1
- data/lib/active_record/type/unsigned_integer.rb +0 -1
- data/lib/active_record/type.rb +10 -5
- data/lib/active_record/type_caster/connection.rb +15 -15
- data/lib/active_record/type_caster/map.rb +8 -8
- data/lib/active_record/validations/associated.rb +1 -2
- data/lib/active_record/validations/numericality.rb +35 -0
- data/lib/active_record/validations/uniqueness.rb +38 -30
- data/lib/active_record/validations.rb +4 -3
- data/lib/active_record.rb +13 -12
- data/lib/arel/alias_predication.rb +9 -0
- data/lib/arel/attributes/attribute.rb +41 -0
- data/lib/arel/collectors/bind.rb +29 -0
- data/lib/arel/collectors/composite.rb +39 -0
- data/lib/arel/collectors/plain_string.rb +20 -0
- data/lib/arel/collectors/sql_string.rb +27 -0
- data/lib/arel/collectors/substitute_binds.rb +35 -0
- data/lib/arel/crud.rb +42 -0
- data/lib/arel/delete_manager.rb +18 -0
- data/lib/arel/errors.rb +9 -0
- data/lib/arel/expressions.rb +29 -0
- data/lib/arel/factory_methods.rb +49 -0
- data/lib/arel/insert_manager.rb +49 -0
- data/lib/arel/math.rb +45 -0
- data/lib/arel/nodes/and.rb +32 -0
- data/lib/arel/nodes/ascending.rb +23 -0
- data/lib/arel/nodes/binary.rb +126 -0
- data/lib/arel/nodes/bind_param.rb +44 -0
- data/lib/arel/nodes/case.rb +55 -0
- data/lib/arel/nodes/casted.rb +62 -0
- data/lib/arel/nodes/comment.rb +29 -0
- data/lib/arel/nodes/count.rb +12 -0
- data/lib/arel/nodes/delete_statement.rb +45 -0
- data/lib/arel/nodes/descending.rb +23 -0
- data/lib/arel/nodes/equality.rb +15 -0
- data/lib/arel/nodes/extract.rb +24 -0
- data/lib/arel/nodes/false.rb +16 -0
- data/lib/arel/nodes/full_outer_join.rb +8 -0
- data/lib/arel/nodes/function.rb +44 -0
- data/lib/arel/nodes/grouping.rb +11 -0
- data/lib/arel/nodes/homogeneous_in.rb +76 -0
- data/lib/arel/nodes/in.rb +15 -0
- data/lib/arel/nodes/infix_operation.rb +92 -0
- data/lib/arel/nodes/inner_join.rb +8 -0
- data/lib/arel/nodes/insert_statement.rb +37 -0
- data/lib/arel/nodes/join_source.rb +20 -0
- data/lib/arel/nodes/matches.rb +18 -0
- data/lib/arel/nodes/named_function.rb +23 -0
- data/lib/arel/nodes/node.rb +51 -0
- data/lib/arel/nodes/node_expression.rb +13 -0
- data/lib/arel/nodes/ordering.rb +27 -0
- data/lib/arel/nodes/outer_join.rb +8 -0
- data/lib/arel/nodes/over.rb +15 -0
- data/lib/arel/nodes/regexp.rb +16 -0
- data/lib/arel/nodes/right_outer_join.rb +8 -0
- data/lib/arel/nodes/select_core.rb +67 -0
- data/lib/arel/nodes/select_statement.rb +41 -0
- data/lib/arel/nodes/sql_literal.rb +19 -0
- data/lib/arel/nodes/string_join.rb +11 -0
- data/lib/arel/nodes/table_alias.rb +31 -0
- data/lib/arel/nodes/terminal.rb +16 -0
- data/lib/arel/nodes/true.rb +16 -0
- data/lib/arel/nodes/unary.rb +44 -0
- data/lib/arel/nodes/unary_operation.rb +20 -0
- data/lib/arel/nodes/unqualified_column.rb +22 -0
- data/lib/arel/nodes/update_statement.rb +41 -0
- data/lib/arel/nodes/values_list.rb +9 -0
- data/lib/arel/nodes/window.rb +126 -0
- data/lib/arel/nodes/with.rb +11 -0
- data/lib/arel/nodes.rb +70 -0
- data/lib/arel/order_predications.rb +13 -0
- data/lib/arel/predications.rb +250 -0
- data/lib/arel/select_manager.rb +270 -0
- data/lib/arel/table.rb +118 -0
- data/lib/arel/tree_manager.rb +72 -0
- data/lib/arel/update_manager.rb +34 -0
- data/lib/arel/visitors/dot.rb +308 -0
- data/lib/arel/visitors/mysql.rb +93 -0
- data/lib/arel/visitors/postgresql.rb +120 -0
- data/lib/arel/visitors/sqlite.rb +38 -0
- data/lib/arel/visitors/to_sql.rb +899 -0
- data/lib/arel/visitors/visitor.rb +45 -0
- data/lib/arel/visitors.rb +13 -0
- data/lib/arel/window_predications.rb +9 -0
- data/lib/arel.rb +54 -0
- data/lib/rails/generators/active_record/application_record/application_record_generator.rb +0 -1
- data/lib/rails/generators/active_record/migration/migration_generator.rb +3 -5
- data/lib/rails/generators/active_record/migration/templates/create_table_migration.rb.tt +3 -1
- data/lib/rails/generators/active_record/migration/templates/migration.rb.tt +7 -5
- data/lib/rails/generators/active_record/migration.rb +19 -2
- data/lib/rails/generators/active_record/model/model_generator.rb +39 -2
- data/lib/rails/generators/active_record/model/templates/abstract_base_class.rb.tt +7 -0
- data/lib/rails/generators/active_record/model/templates/model.rb.tt +10 -1
- metadata +116 -30
- data/lib/active_record/attribute_decorators.rb +0 -90
- data/lib/active_record/collection_cache_key.rb +0 -53
- data/lib/active_record/connection_adapters/connection_specification.rb +0 -287
- data/lib/active_record/connection_adapters/determine_if_preparable_visitor.rb +0 -33
- data/lib/active_record/define_callbacks.rb +0 -22
- data/lib/active_record/relation/predicate_builder/base_handler.rb +0 -19
- data/lib/active_record/relation/where_clause_factory.rb +0 -34
@@ -51,7 +51,10 @@ module ActiveRecord
|
|
51
51
|
|
52
52
|
if touch
|
53
53
|
names = touch if touch != true
|
54
|
-
|
54
|
+
names = Array.wrap(names)
|
55
|
+
options = names.extract_options!
|
56
|
+
touch_updates = touch_attributes_with_time(*names, **options)
|
57
|
+
updates.merge!(touch_updates)
|
55
58
|
end
|
56
59
|
|
57
60
|
unscoped.where(primary_key => object.id).update_all(updates)
|
@@ -102,27 +105,7 @@ module ActiveRecord
|
|
102
105
|
# # `updated_at` = '2016-10-13T09:59:23-05:00'
|
103
106
|
# # WHERE id IN (10, 15)
|
104
107
|
def update_counters(id, counters)
|
105
|
-
|
106
|
-
|
107
|
-
updates = counters.map do |counter_name, value|
|
108
|
-
operator = value < 0 ? "-" : "+"
|
109
|
-
quoted_column = connection.quote_column_name(counter_name)
|
110
|
-
"#{quoted_column} = COALESCE(#{quoted_column}, 0) #{operator} #{value.abs}"
|
111
|
-
end
|
112
|
-
|
113
|
-
if touch
|
114
|
-
names = touch if touch != true
|
115
|
-
touch_updates = touch_attributes_with_time(*names)
|
116
|
-
updates << sanitize_sql_for_assignment(touch_updates) unless touch_updates.empty?
|
117
|
-
end
|
118
|
-
|
119
|
-
if id.is_a?(Relation) && self == id.klass
|
120
|
-
relation = id
|
121
|
-
else
|
122
|
-
relation = unscoped.where!(primary_key => id)
|
123
|
-
end
|
124
|
-
|
125
|
-
relation.update_all updates.join(", ")
|
108
|
+
unscoped.where!(primary_key => id).update_counters(counters)
|
126
109
|
end
|
127
110
|
|
128
111
|
# Increment a numeric field by one, via a direct SQL update.
|
@@ -179,14 +162,11 @@ module ActiveRecord
|
|
179
162
|
end
|
180
163
|
|
181
164
|
private
|
182
|
-
|
183
|
-
def _create_record(*)
|
165
|
+
def _create_record(attribute_names = self.attribute_names)
|
184
166
|
id = super
|
185
167
|
|
186
168
|
each_counter_cached_associations do |association|
|
187
|
-
|
188
|
-
association.increment_counters
|
189
|
-
end
|
169
|
+
association.increment_counters
|
190
170
|
end
|
191
171
|
|
192
172
|
id
|
@@ -199,9 +179,7 @@ module ActiveRecord
|
|
199
179
|
each_counter_cached_associations do |association|
|
200
180
|
foreign_key = association.reflection.foreign_key.to_sym
|
201
181
|
unless destroyed_by_association && destroyed_by_association.foreign_key.to_sym == foreign_key
|
202
|
-
|
203
|
-
association.decrement_counters
|
204
|
-
end
|
182
|
+
association.decrement_counters
|
205
183
|
end
|
206
184
|
end
|
207
185
|
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require "active_support/core_ext/enumerable"
|
5
|
+
|
6
|
+
module ActiveRecord
|
7
|
+
class DatabaseConfigurations
|
8
|
+
# Expands a connection string into a hash.
|
9
|
+
class ConnectionUrlResolver # :nodoc:
|
10
|
+
# == Example
|
11
|
+
#
|
12
|
+
# url = "postgresql://foo:bar@localhost:9000/foo_test?pool=5&timeout=3000"
|
13
|
+
# ConnectionUrlResolver.new(url).to_hash
|
14
|
+
# # => {
|
15
|
+
# adapter: "postgresql",
|
16
|
+
# host: "localhost",
|
17
|
+
# port: 9000,
|
18
|
+
# database: "foo_test",
|
19
|
+
# username: "foo",
|
20
|
+
# password: "bar",
|
21
|
+
# pool: "5",
|
22
|
+
# timeout: "3000"
|
23
|
+
# }
|
24
|
+
def initialize(url)
|
25
|
+
raise "Database URL cannot be empty" if url.blank?
|
26
|
+
@uri = uri_parser.parse(url)
|
27
|
+
@adapter = @uri.scheme && @uri.scheme.tr("-", "_")
|
28
|
+
@adapter = "postgresql" if @adapter == "postgres"
|
29
|
+
|
30
|
+
if @uri.opaque
|
31
|
+
@uri.opaque, @query = @uri.opaque.split("?", 2)
|
32
|
+
else
|
33
|
+
@query = @uri.query
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Converts the given URL to a full connection hash.
|
38
|
+
def to_hash
|
39
|
+
config = raw_config.compact_blank
|
40
|
+
config.map { |key, value| config[key] = uri_parser.unescape(value) if value.is_a? String }
|
41
|
+
config
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
attr_reader :uri
|
46
|
+
|
47
|
+
def uri_parser
|
48
|
+
@uri_parser ||= URI::Parser.new
|
49
|
+
end
|
50
|
+
|
51
|
+
# Converts the query parameters of the URI into a hash.
|
52
|
+
#
|
53
|
+
# "localhost?pool=5&reaping_frequency=2"
|
54
|
+
# # => { pool: "5", reaping_frequency: "2" }
|
55
|
+
#
|
56
|
+
# returns empty hash if no query present.
|
57
|
+
#
|
58
|
+
# "localhost"
|
59
|
+
# # => {}
|
60
|
+
def query_hash
|
61
|
+
Hash[(@query || "").split("&").map { |pair| pair.split("=", 2) }].symbolize_keys
|
62
|
+
end
|
63
|
+
|
64
|
+
def raw_config
|
65
|
+
if uri.opaque
|
66
|
+
query_hash.merge(
|
67
|
+
adapter: @adapter,
|
68
|
+
database: uri.opaque
|
69
|
+
)
|
70
|
+
else
|
71
|
+
query_hash.merge(
|
72
|
+
adapter: @adapter,
|
73
|
+
username: uri.user,
|
74
|
+
password: uri.password,
|
75
|
+
port: uri.port,
|
76
|
+
database: database_from_path,
|
77
|
+
host: uri.hostname
|
78
|
+
)
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
# Returns name of the database.
|
83
|
+
def database_from_path
|
84
|
+
if @adapter == "sqlite3"
|
85
|
+
# 'sqlite3:/foo' is absolute, because that makes sense. The
|
86
|
+
# corresponding relative version, 'sqlite3:foo', is handled
|
87
|
+
# elsewhere, as an "opaque".
|
88
|
+
|
89
|
+
uri.path
|
90
|
+
else
|
91
|
+
# Only SQLite uses a filename as the "database" name; for
|
92
|
+
# anything else, a leading slash would be silly.
|
93
|
+
|
94
|
+
uri.path.delete_prefix("/")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# ActiveRecord::Base.configurations will return either a HashConfig or
|
6
|
+
# UrlConfig respectively. It will never return a DatabaseConfig object,
|
7
|
+
# as this is the parent class for the types of database configuration objects.
|
8
|
+
class DatabaseConfig # :nodoc:
|
9
|
+
attr_reader :env_name, :name
|
10
|
+
|
11
|
+
attr_accessor :owner_name
|
12
|
+
|
13
|
+
def initialize(env_name, name)
|
14
|
+
@env_name = env_name
|
15
|
+
@name = name
|
16
|
+
end
|
17
|
+
|
18
|
+
def spec_name
|
19
|
+
@name
|
20
|
+
end
|
21
|
+
deprecate spec_name: "please use name instead"
|
22
|
+
|
23
|
+
def config
|
24
|
+
raise NotImplementedError
|
25
|
+
end
|
26
|
+
|
27
|
+
def adapter_method
|
28
|
+
"#{adapter}_connection"
|
29
|
+
end
|
30
|
+
|
31
|
+
def host
|
32
|
+
raise NotImplementedError
|
33
|
+
end
|
34
|
+
|
35
|
+
def database
|
36
|
+
raise NotImplementedError
|
37
|
+
end
|
38
|
+
|
39
|
+
def _database=(database)
|
40
|
+
raise NotImplementedError
|
41
|
+
end
|
42
|
+
|
43
|
+
def adapter
|
44
|
+
raise NotImplementedError
|
45
|
+
end
|
46
|
+
|
47
|
+
def pool
|
48
|
+
raise NotImplementedError
|
49
|
+
end
|
50
|
+
|
51
|
+
def checkout_timeout
|
52
|
+
raise NotImplementedError
|
53
|
+
end
|
54
|
+
|
55
|
+
def reaping_frequency
|
56
|
+
raise NotImplementedError
|
57
|
+
end
|
58
|
+
|
59
|
+
def idle_timeout
|
60
|
+
raise NotImplementedError
|
61
|
+
end
|
62
|
+
|
63
|
+
def replica?
|
64
|
+
raise NotImplementedError
|
65
|
+
end
|
66
|
+
|
67
|
+
def migrations_paths
|
68
|
+
raise NotImplementedError
|
69
|
+
end
|
70
|
+
|
71
|
+
def for_current_env?
|
72
|
+
env_name == ActiveRecord::ConnectionHandling::DEFAULT_ENV.call
|
73
|
+
end
|
74
|
+
|
75
|
+
def schema_cache_path
|
76
|
+
raise NotImplementedError
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,96 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# A HashConfig object is created for each database configuration entry that
|
6
|
+
# is created from a hash.
|
7
|
+
#
|
8
|
+
# A hash config:
|
9
|
+
#
|
10
|
+
# { "development" => { "database" => "db_name" } }
|
11
|
+
#
|
12
|
+
# Becomes:
|
13
|
+
#
|
14
|
+
# #<ActiveRecord::DatabaseConfigurations::HashConfig:0x00007fd1acbded10
|
15
|
+
# @env_name="development", @name="primary", @config={database: "db_name"}>
|
16
|
+
#
|
17
|
+
# ==== Options
|
18
|
+
#
|
19
|
+
# * <tt>:env_name</tt> - The Rails environment, i.e. "development".
|
20
|
+
# * <tt>:name</tt> - The db config name. In a standard two-tier
|
21
|
+
# database configuration this will default to "primary". In a multiple
|
22
|
+
# database three-tier database configuration this corresponds to the name
|
23
|
+
# used in the second tier, for example "primary_readonly".
|
24
|
+
# * <tt>:config</tt> - The config hash. This is the hash that contains the
|
25
|
+
# database adapter, name, and other important information for database
|
26
|
+
# connections.
|
27
|
+
class HashConfig < DatabaseConfig
|
28
|
+
attr_reader :configuration_hash
|
29
|
+
def initialize(env_name, name, configuration_hash)
|
30
|
+
super(env_name, name)
|
31
|
+
@configuration_hash = configuration_hash.symbolize_keys.freeze
|
32
|
+
end
|
33
|
+
|
34
|
+
def config
|
35
|
+
ActiveSupport::Deprecation.warn("DatabaseConfig#config will be removed in 7.0.0 in favor of DatabaseConfig#configuration_hash which returns a hash with symbol keys")
|
36
|
+
configuration_hash.stringify_keys
|
37
|
+
end
|
38
|
+
|
39
|
+
# Determines whether a database configuration is for a replica / readonly
|
40
|
+
# connection. If the +replica+ key is present in the config, +replica?+ will
|
41
|
+
# return +true+.
|
42
|
+
def replica?
|
43
|
+
configuration_hash[:replica]
|
44
|
+
end
|
45
|
+
|
46
|
+
# The migrations paths for a database configuration. If the
|
47
|
+
# +migrations_paths+ key is present in the config, +migrations_paths+
|
48
|
+
# will return its value.
|
49
|
+
def migrations_paths
|
50
|
+
configuration_hash[:migrations_paths]
|
51
|
+
end
|
52
|
+
|
53
|
+
def host
|
54
|
+
configuration_hash[:host]
|
55
|
+
end
|
56
|
+
|
57
|
+
def database
|
58
|
+
configuration_hash[:database]
|
59
|
+
end
|
60
|
+
|
61
|
+
def _database=(database) # :nodoc:
|
62
|
+
@configuration_hash = configuration_hash.merge(database: database).freeze
|
63
|
+
end
|
64
|
+
|
65
|
+
def pool
|
66
|
+
(configuration_hash[:pool] || 5).to_i
|
67
|
+
end
|
68
|
+
|
69
|
+
def checkout_timeout
|
70
|
+
(configuration_hash[:checkout_timeout] || 5).to_f
|
71
|
+
end
|
72
|
+
|
73
|
+
# +reaping_frequency+ is configurable mostly for historical reasons, but it could
|
74
|
+
# also be useful if someone wants a very low +idle_timeout+.
|
75
|
+
def reaping_frequency
|
76
|
+
configuration_hash.fetch(:reaping_frequency, 60)&.to_f
|
77
|
+
end
|
78
|
+
|
79
|
+
def idle_timeout
|
80
|
+
timeout = configuration_hash.fetch(:idle_timeout, 300).to_f
|
81
|
+
timeout if timeout > 0
|
82
|
+
end
|
83
|
+
|
84
|
+
def adapter
|
85
|
+
configuration_hash[:adapter]
|
86
|
+
end
|
87
|
+
|
88
|
+
# The path to the schema cache dump file for a database.
|
89
|
+
# If omitted, the filename will be read from ENV or a
|
90
|
+
# default will be derived.
|
91
|
+
def schema_cache_path
|
92
|
+
configuration_hash[:schema_cache_path]
|
93
|
+
end
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module ActiveRecord
|
4
|
+
class DatabaseConfigurations
|
5
|
+
# A UrlConfig object is created for each database configuration
|
6
|
+
# entry that is created from a URL. This can either be a URL string
|
7
|
+
# or a hash with a URL in place of the config hash.
|
8
|
+
#
|
9
|
+
# A URL config:
|
10
|
+
#
|
11
|
+
# postgres://localhost/foo
|
12
|
+
#
|
13
|
+
# Becomes:
|
14
|
+
#
|
15
|
+
# #<ActiveRecord::DatabaseConfigurations::UrlConfig:0x00007fdc3238f340
|
16
|
+
# @env_name="default_env", @name="primary",
|
17
|
+
# @config={adapter: "postgresql", database: "foo", host: "localhost"},
|
18
|
+
# @url="postgres://localhost/foo">
|
19
|
+
#
|
20
|
+
# ==== Options
|
21
|
+
#
|
22
|
+
# * <tt>:env_name</tt> - The Rails environment, ie "development".
|
23
|
+
# * <tt>:name</tt> - The db config name. In a standard two-tier
|
24
|
+
# database configuration this will default to "primary". In a multiple
|
25
|
+
# database three-tier database configuration this corresponds to the name
|
26
|
+
# used in the second tier, for example "primary_readonly".
|
27
|
+
# * <tt>:url</tt> - The database URL.
|
28
|
+
# * <tt>:config</tt> - The config hash. This is the hash that contains the
|
29
|
+
# database adapter, name, and other important information for database
|
30
|
+
# connections.
|
31
|
+
class UrlConfig < HashConfig
|
32
|
+
attr_reader :url
|
33
|
+
|
34
|
+
def initialize(env_name, name, url, configuration_hash = {})
|
35
|
+
super(env_name, name, configuration_hash)
|
36
|
+
|
37
|
+
@url = url
|
38
|
+
@configuration_hash = @configuration_hash.merge(build_url_hash).freeze
|
39
|
+
end
|
40
|
+
|
41
|
+
private
|
42
|
+
# Return a Hash that can be merged into the main config that represents
|
43
|
+
# the passed in url
|
44
|
+
def build_url_hash
|
45
|
+
if url.nil? || %w(jdbc: http: https:).any? { |protocol| url.start_with?(protocol) }
|
46
|
+
{ url: url }
|
47
|
+
else
|
48
|
+
ConnectionUrlResolver.new(url).to_hash
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,273 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "uri"
|
4
|
+
require "active_record/database_configurations/database_config"
|
5
|
+
require "active_record/database_configurations/hash_config"
|
6
|
+
require "active_record/database_configurations/url_config"
|
7
|
+
require "active_record/database_configurations/connection_url_resolver"
|
8
|
+
|
9
|
+
module ActiveRecord
|
10
|
+
# ActiveRecord::DatabaseConfigurations returns an array of DatabaseConfig
|
11
|
+
# objects (either a HashConfig or UrlConfig) that are constructed from the
|
12
|
+
# application's database configuration hash or URL string.
|
13
|
+
class DatabaseConfigurations
|
14
|
+
class InvalidConfigurationError < StandardError; end
|
15
|
+
|
16
|
+
attr_reader :configurations
|
17
|
+
delegate :any?, to: :configurations
|
18
|
+
|
19
|
+
def initialize(configurations = {})
|
20
|
+
@configurations = build_configs(configurations)
|
21
|
+
end
|
22
|
+
|
23
|
+
# Collects the configs for the environment and optionally the specification
|
24
|
+
# name passed in. To include replica configurations pass <tt>include_replicas: true</tt>.
|
25
|
+
#
|
26
|
+
# If a name is provided a single DatabaseConfig object will be
|
27
|
+
# returned, otherwise an array of DatabaseConfig objects will be
|
28
|
+
# returned that corresponds with the environment and type requested.
|
29
|
+
#
|
30
|
+
# ==== Options
|
31
|
+
#
|
32
|
+
# * <tt>env_name:</tt> The environment name. Defaults to +nil+ which will collect
|
33
|
+
# configs for all environments.
|
34
|
+
# * <tt>name:</tt> The db config name (i.e. primary, animals, etc.). Defaults
|
35
|
+
# to +nil+. If no +env_name+ is specified the config for the default env and the
|
36
|
+
# passed +name+ will be returned.
|
37
|
+
# * <tt>include_replicas:</tt> Determines whether to include replicas in
|
38
|
+
# the returned list. Most of the time we're only iterating over the write
|
39
|
+
# connection (i.e. migrations don't need to run for the write and read connection).
|
40
|
+
# Defaults to +false+.
|
41
|
+
def configs_for(env_name: nil, spec_name: nil, name: nil, include_replicas: false)
|
42
|
+
if spec_name
|
43
|
+
name = spec_name
|
44
|
+
ActiveSupport::Deprecation.warn("The kwarg `spec_name` is deprecated in favor of `name`. `spec_name` will be removed in Rails 7.0")
|
45
|
+
end
|
46
|
+
|
47
|
+
env_name ||= default_env if name
|
48
|
+
configs = env_with_configs(env_name)
|
49
|
+
|
50
|
+
unless include_replicas
|
51
|
+
configs = configs.select do |db_config|
|
52
|
+
!db_config.replica?
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
if name
|
57
|
+
configs.find do |db_config|
|
58
|
+
db_config.name == name
|
59
|
+
end
|
60
|
+
else
|
61
|
+
configs
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns the config hash that corresponds with the environment
|
66
|
+
#
|
67
|
+
# If the application has multiple databases +default_hash+ will
|
68
|
+
# return the first config hash for the environment.
|
69
|
+
#
|
70
|
+
# { database: "my_db", adapter: "mysql2" }
|
71
|
+
def default_hash(env = default_env)
|
72
|
+
default = find_db_config(env)
|
73
|
+
default.configuration_hash if default
|
74
|
+
end
|
75
|
+
alias :[] :default_hash
|
76
|
+
deprecate "[]": "Use configs_for", default_hash: "Use configs_for"
|
77
|
+
|
78
|
+
# Returns a single DatabaseConfig object based on the requested environment.
|
79
|
+
#
|
80
|
+
# If the application has multiple databases +find_db_config+ will return
|
81
|
+
# the first DatabaseConfig for the environment.
|
82
|
+
def find_db_config(env)
|
83
|
+
configurations
|
84
|
+
.sort_by.with_index { |db_config, i| db_config.for_current_env? ? [0, i] : [1, i] }
|
85
|
+
.find do |db_config|
|
86
|
+
db_config.env_name == env.to_s ||
|
87
|
+
(db_config.for_current_env? && db_config.name == env.to_s)
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
# A primary configuration is one that is named primary or if there is
|
92
|
+
# no primary, the first configuration for an environment will be treated
|
93
|
+
# as primary. This is used as the "default" configuration and is used
|
94
|
+
# when the application needs to treat one configuration differently. For
|
95
|
+
# example, when Rails dumps the schema, the primary configuration's schema
|
96
|
+
# file will be named `schema.rb` instead of `primary_schema.rb`.
|
97
|
+
def primary?(name) # :nodoc:
|
98
|
+
return true if name == "primary"
|
99
|
+
|
100
|
+
first_config = find_db_config(default_env)
|
101
|
+
first_config && name == first_config.name
|
102
|
+
end
|
103
|
+
|
104
|
+
# Returns the DatabaseConfigurations object as a Hash.
|
105
|
+
def to_h
|
106
|
+
configurations.inject({}) do |memo, db_config|
|
107
|
+
memo.merge(db_config.env_name => db_config.configuration_hash.stringify_keys)
|
108
|
+
end
|
109
|
+
end
|
110
|
+
deprecate to_h: "You can use `ActiveRecord::Base.configurations.configs_for(env_name: 'env', name: 'primary').configuration_hash` to get the configuration hashes."
|
111
|
+
|
112
|
+
# Checks if the application's configurations are empty.
|
113
|
+
#
|
114
|
+
# Aliased to blank?
|
115
|
+
def empty?
|
116
|
+
configurations.empty?
|
117
|
+
end
|
118
|
+
alias :blank? :empty?
|
119
|
+
|
120
|
+
# Returns fully resolved connection, accepts hash, string or symbol.
|
121
|
+
# Always returns a DatabaseConfiguration::DatabaseConfig
|
122
|
+
#
|
123
|
+
# == Examples
|
124
|
+
#
|
125
|
+
# Symbol representing current environment.
|
126
|
+
#
|
127
|
+
# DatabaseConfigurations.new("production" => {}).resolve(:production)
|
128
|
+
# # => DatabaseConfigurations::HashConfig.new(env_name: "production", config: {})
|
129
|
+
#
|
130
|
+
# One layer deep hash of connection values.
|
131
|
+
#
|
132
|
+
# DatabaseConfigurations.new({}).resolve("adapter" => "sqlite3")
|
133
|
+
# # => DatabaseConfigurations::HashConfig.new(config: {"adapter" => "sqlite3"})
|
134
|
+
#
|
135
|
+
# Connection URL.
|
136
|
+
#
|
137
|
+
# DatabaseConfigurations.new({}).resolve("postgresql://localhost/foo")
|
138
|
+
# # => DatabaseConfigurations::UrlConfig.new(config: {"adapter" => "postgresql", "host" => "localhost", "database" => "foo"})
|
139
|
+
def resolve(config) # :nodoc:
|
140
|
+
return config if DatabaseConfigurations::DatabaseConfig === config
|
141
|
+
|
142
|
+
case config
|
143
|
+
when Symbol
|
144
|
+
resolve_symbol_connection(config)
|
145
|
+
when Hash, String
|
146
|
+
build_db_config_from_raw_config(default_env, "primary", config)
|
147
|
+
else
|
148
|
+
raise TypeError, "Invalid type for configuration. Expected Symbol, String, or Hash. Got #{config.inspect}"
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
private
|
153
|
+
def default_env
|
154
|
+
ActiveRecord::ConnectionHandling::DEFAULT_ENV.call.to_s
|
155
|
+
end
|
156
|
+
|
157
|
+
def env_with_configs(env = nil)
|
158
|
+
if env
|
159
|
+
configurations.select { |db_config| db_config.env_name == env }
|
160
|
+
else
|
161
|
+
configurations
|
162
|
+
end
|
163
|
+
end
|
164
|
+
|
165
|
+
def build_configs(configs)
|
166
|
+
return configs.configurations if configs.is_a?(DatabaseConfigurations)
|
167
|
+
return configs if configs.is_a?(Array)
|
168
|
+
|
169
|
+
db_configs = configs.flat_map do |env_name, config|
|
170
|
+
if config.is_a?(Hash) && config.all? { |_, v| v.is_a?(Hash) }
|
171
|
+
walk_configs(env_name.to_s, config)
|
172
|
+
else
|
173
|
+
build_db_config_from_raw_config(env_name.to_s, "primary", config)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
unless db_configs.find(&:for_current_env?)
|
178
|
+
db_configs << environment_url_config(default_env, "primary", {})
|
179
|
+
end
|
180
|
+
|
181
|
+
merge_db_environment_variables(default_env, db_configs.compact)
|
182
|
+
end
|
183
|
+
|
184
|
+
def walk_configs(env_name, config)
|
185
|
+
config.map do |name, sub_config|
|
186
|
+
build_db_config_from_raw_config(env_name, name.to_s, sub_config)
|
187
|
+
end
|
188
|
+
end
|
189
|
+
|
190
|
+
def resolve_symbol_connection(name)
|
191
|
+
if db_config = find_db_config(name)
|
192
|
+
db_config
|
193
|
+
else
|
194
|
+
raise AdapterNotSpecified, <<~MSG
|
195
|
+
The `#{name}` database is not configured for the `#{default_env}` environment.
|
196
|
+
|
197
|
+
Available databases configurations are:
|
198
|
+
|
199
|
+
#{build_configuration_sentence}
|
200
|
+
MSG
|
201
|
+
end
|
202
|
+
end
|
203
|
+
|
204
|
+
def build_configuration_sentence
|
205
|
+
configs = configs_for(include_replicas: true)
|
206
|
+
|
207
|
+
configs.group_by(&:env_name).map do |env, config|
|
208
|
+
names = config.map(&:name)
|
209
|
+
if names.size > 1
|
210
|
+
"#{env}: #{names.join(", ")}"
|
211
|
+
else
|
212
|
+
env
|
213
|
+
end
|
214
|
+
end.join("\n")
|
215
|
+
end
|
216
|
+
|
217
|
+
def build_db_config_from_raw_config(env_name, name, config)
|
218
|
+
case config
|
219
|
+
when String
|
220
|
+
build_db_config_from_string(env_name, name, config)
|
221
|
+
when Hash
|
222
|
+
build_db_config_from_hash(env_name, name, config.symbolize_keys)
|
223
|
+
else
|
224
|
+
raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
|
225
|
+
end
|
226
|
+
end
|
227
|
+
|
228
|
+
def build_db_config_from_string(env_name, name, config)
|
229
|
+
url = config
|
230
|
+
uri = URI.parse(url)
|
231
|
+
if uri.scheme
|
232
|
+
UrlConfig.new(env_name, name, url)
|
233
|
+
else
|
234
|
+
raise InvalidConfigurationError, "'{ #{env_name} => #{config} }' is not a valid configuration. Expected '#{config}' to be a URL string or a Hash."
|
235
|
+
end
|
236
|
+
end
|
237
|
+
|
238
|
+
def build_db_config_from_hash(env_name, name, config)
|
239
|
+
if config.has_key?(:url)
|
240
|
+
url = config[:url]
|
241
|
+
config_without_url = config.dup
|
242
|
+
config_without_url.delete :url
|
243
|
+
|
244
|
+
UrlConfig.new(env_name, name, url, config_without_url)
|
245
|
+
else
|
246
|
+
HashConfig.new(env_name, name, config)
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
def merge_db_environment_variables(current_env, configs)
|
251
|
+
configs.map do |config|
|
252
|
+
next config if config.is_a?(UrlConfig) || config.env_name != current_env
|
253
|
+
|
254
|
+
url_config = environment_url_config(current_env, config.name, config.configuration_hash)
|
255
|
+
url_config || config
|
256
|
+
end
|
257
|
+
end
|
258
|
+
|
259
|
+
def environment_url_config(env, name, config)
|
260
|
+
url = environment_value_for(name)
|
261
|
+
return unless url
|
262
|
+
|
263
|
+
UrlConfig.new(env, name, url, config)
|
264
|
+
end
|
265
|
+
|
266
|
+
def environment_value_for(name)
|
267
|
+
name_env_key = "#{name.upcase}_DATABASE_URL"
|
268
|
+
url = ENV[name_env_key]
|
269
|
+
url ||= ENV["DATABASE_URL"] if name == "primary"
|
270
|
+
url
|
271
|
+
end
|
272
|
+
end
|
273
|
+
end
|