diff options
45 files changed, 234 insertions, 159 deletions
diff --git a/actionmailer/test/abstract_unit.rb b/actionmailer/test/abstract_unit.rb index 7681679dc7..c4d5cb8c33 100644 --- a/actionmailer/test/abstract_unit.rb +++ b/actionmailer/test/abstract_unit.rb @@ -15,7 +15,7 @@ require 'mail' # Emulate AV railtie require 'action_view' -ActionMailer::Base.send(:include, ActionView::Layouts) +ActionMailer::Base.include(ActionView::Layouts) # Show backtraces for deprecated behavior for quicker cleanup. ActiveSupport::Deprecation.debug = true diff --git a/actionpack/lib/abstract_controller/railties/routes_helpers.rb b/actionpack/lib/abstract_controller/railties/routes_helpers.rb index 568c47e43a..14b574e322 100644 --- a/actionpack/lib/abstract_controller/railties/routes_helpers.rb +++ b/actionpack/lib/abstract_controller/railties/routes_helpers.rb @@ -6,9 +6,9 @@ module AbstractController define_method(:inherited) do |klass| super(klass) if namespace = klass.parents.detect { |m| m.respond_to?(:railtie_routes_url_helpers) } - klass.send(:include, namespace.railtie_routes_url_helpers(include_path_helpers)) + klass.include(namespace.railtie_routes_url_helpers(include_path_helpers)) else - klass.send(:include, routes.url_helpers(include_path_helpers)) + klass.include(routes.url_helpers(include_path_helpers)) end end end diff --git a/actionpack/lib/action_dispatch/testing/assertions/routing.rb b/actionpack/lib/action_dispatch/testing/assertions/routing.rb index 28dc88d317..a927738b42 100644 --- a/actionpack/lib/action_dispatch/testing/assertions/routing.rb +++ b/actionpack/lib/action_dispatch/testing/assertions/routing.rb @@ -144,7 +144,7 @@ module ActionDispatch old_controller, @controller = @controller, @controller.clone _routes = @routes - @controller.singleton_class.send(:include, _routes.url_helpers) + @controller.singleton_class.include(_routes.url_helpers) @controller.view_context_class = Class.new(@controller.view_context_class) do include _routes.url_helpers end diff --git a/actionpack/test/controller/helper_test.rb b/actionpack/test/controller/helper_test.rb index 936b8c2450..e263ed341f 100644 --- a/actionpack/test/controller/helper_test.rb +++ b/actionpack/test/controller/helper_test.rb @@ -29,7 +29,7 @@ module ImpressiveLibrary def useful_function() end end -ActionController::Base.send :include, ImpressiveLibrary +ActionController::Base.include(ImpressiveLibrary) class JustMeController < ActionController::Base clear_helpers @@ -223,10 +223,10 @@ class HelperTest < ActiveSupport::TestCase # fun/pdf_helper.rb assert methods.include?(:foobar) end - + def test_helper_proxy_config AllHelpersController.config.my_var = 'smth' - + assert_equal 'smth', AllHelpersController.helpers.config.my_var end diff --git a/actionpack/test/controller/integration_test.rb b/actionpack/test/controller/integration_test.rb index 2139cf2661..17d5bae00b 100644 --- a/actionpack/test/controller/integration_test.rb +++ b/actionpack/test/controller/integration_test.rb @@ -682,7 +682,7 @@ class IntegrationProcessTest < ActionDispatch::IntegrationTest get 'get/:action', :to => controller, :as => :get_action end - self.singleton_class.send(:include, set.url_helpers) + self.singleton_class.include(set.url_helpers) yield end diff --git a/actionpack/test/controller/localized_templates_test.rb b/actionpack/test/controller/localized_templates_test.rb index 2be947c648..3576015513 100644 --- a/actionpack/test/controller/localized_templates_test.rb +++ b/actionpack/test/controller/localized_templates_test.rb @@ -30,7 +30,7 @@ class LocalizedTemplatesTest < ActionController::TestCase def test_use_fallback_locales I18n.locale = :"de-AT" - I18n.backend.class.send(:include, I18n::Backend::Fallbacks) + I18n.backend.class.include(I18n::Backend::Fallbacks) I18n.fallbacks[:"de-AT"] = [:de] get :hello_world diff --git a/actionpack/test/controller/resources_test.rb b/actionpack/test/controller/resources_test.rb index 05806177e3..02e7614ba2 100644 --- a/actionpack/test/controller/resources_test.rb +++ b/actionpack/test/controller/resources_test.rb @@ -1184,7 +1184,7 @@ class ResourcesTest < ActionController::TestCase end @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @routes.url_helpers) + @controller.singleton_class.include(@routes.url_helpers) @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new get :index, params: options[:options] @@ -1254,7 +1254,7 @@ class ResourcesTest < ActionController::TestCase def assert_singleton_named_routes_for(singleton_name, options = {}) (options[:options] ||= {})[:controller] ||= singleton_name.to_s.pluralize @controller = "#{options[:options][:controller].camelize}Controller".constantize.new - @controller.singleton_class.send(:include, @routes.url_helpers) + @controller.singleton_class.include(@routes.url_helpers) @request = ActionController::TestRequest.new @response = ActionController::TestResponse.new get :show, params: options[:options] diff --git a/actionview/lib/action_view/railtie.rb b/actionview/lib/action_view/railtie.rb index 81f9c40b85..ee3dce24b7 100644 --- a/actionview/lib/action_view/railtie.rb +++ b/actionview/lib/action_view/railtie.rb @@ -38,7 +38,7 @@ module ActionView initializer "action_view.setup_action_pack" do |app| ActiveSupport.on_load(:action_controller) do - ActionView::RoutingUrlFor.send(:include, ActionDispatch::Routing::UrlFor) + ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor) end end diff --git a/actionview/lib/action_view/test_case.rb b/actionview/lib/action_view/test_case.rb index 812b011bd7..06810ad14d 100644 --- a/actionview/lib/action_view/test_case.rb +++ b/actionview/lib/action_view/test_case.rb @@ -204,7 +204,7 @@ module ActionView def view @view ||= begin view = @controller.view_context - view.singleton_class.send :include, _helpers + view.singleton_class.include(_helpers) view.extend(Locals) view.rendered_views = self.rendered_views view.output_buffer = self.output_buffer diff --git a/actionview/test/abstract_unit.rb b/actionview/test/abstract_unit.rb index 4aa56f60f7..fc1ca9efdf 100644 --- a/actionview/test/abstract_unit.rb +++ b/actionview/test/abstract_unit.rb @@ -268,7 +268,7 @@ class Rack::TestCase < ActionDispatch::IntegrationTest end end -ActionView::RoutingUrlFor.send(:include, ActionDispatch::Routing::UrlFor) +ActionView::RoutingUrlFor.include(ActionDispatch::Routing::UrlFor) module ActionController class Base diff --git a/actionview/test/activerecord/controller_runtime_test.rb b/actionview/test/activerecord/controller_runtime_test.rb index 469adff39a..af91348d76 100644 --- a/actionview/test/activerecord/controller_runtime_test.rb +++ b/actionview/test/activerecord/controller_runtime_test.rb @@ -4,7 +4,7 @@ require 'fixtures/project' require 'active_support/log_subscriber/test_helper' require 'action_controller/log_subscriber' -ActionController::Base.send :include, ActiveRecord::Railties::ControllerRuntime +ActionController::Base.include(ActiveRecord::Railties::ControllerRuntime) class ControllerRuntimeLogSubscriberTest < ActionController::TestCase class LogSubscriberController < ActionController::Base diff --git a/activejob/test/support/integration/helper.rb b/activejob/test/support/integration/helper.rb index 9bd45e09e8..39e41b6d29 100644 --- a/activejob/test/support/integration/helper.rb +++ b/activejob/test/support/integration/helper.rb @@ -20,7 +20,7 @@ require 'rails/test_help' Rails.backtrace_cleaner.remove_silencers! require_relative 'test_case_helpers' -ActiveSupport::TestCase.send(:include, TestCaseHelpers) +ActiveSupport::TestCase.include(TestCaseHelpers) JobsManager.current_manager.start_workers diff --git a/activerecord/lib/active_record/attribute.rb b/activerecord/lib/active_record/attribute.rb index 48b50d9017..91886f1324 100644 --- a/activerecord/lib/active_record/attribute.rb +++ b/activerecord/lib/active_record/attribute.rb @@ -66,6 +66,10 @@ module ActiveRecord self.class.with_cast_value(name, value, type) end + def with_type(type) + self.class.new(name, value_before_type_cast, type) + end + def type_cast(*) raise NotImplementedError end @@ -137,6 +141,10 @@ module ActiveRecord nil end + def with_type(type) + self.class.with_cast_value(name, nil, type) + end + def with_value_from_database(value) raise ActiveModel::MissingAttributeError, "can't write unknown attribute `#{name}`" end diff --git a/activerecord/lib/active_record/attribute_decorators.rb b/activerecord/lib/active_record/attribute_decorators.rb index 5b96623b6e..7d0ae32411 100644 --- a/activerecord/lib/active_record/attribute_decorators.rb +++ b/activerecord/lib/active_record/attribute_decorators.rb @@ -15,7 +15,7 @@ module ActiveRecord end def decorate_matching_attribute_types(matcher, decorator_name, &block) - clear_caches_calculated_from_columns + reload_schema_from_cache decorator_name = decorator_name.to_s # Create new hashes so we don't modify parent classes @@ -24,10 +24,11 @@ module ActiveRecord private - def add_user_provided_columns(*) - super.map do |column| - decorated_type = attribute_type_decorations.apply(column.name, column.cast_type) - column.with_type(decorated_type) + def load_schema! + super + attribute_types.each do |name, type| + decorated_type = attribute_type_decorations.apply(name, type) + define_attribute(name, decorated_type) end end end diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 6de71896ee..9d58a19304 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -83,7 +83,7 @@ module ActiveRecord generated_attribute_methods.synchronize do return false if @attribute_methods_generated superclass.define_attribute_methods unless self == base_class - super(column_names) + super(attribute_names) @attribute_methods_generated = true end true @@ -185,7 +185,7 @@ module ActiveRecord # # => ["id", "created_at", "updated_at", "name", "age"] def attribute_names @attribute_names ||= if !abstract_class? && table_exists? - column_names + attribute_types.keys else [] end diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 06d87ee01e..7ba907f786 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -131,10 +131,8 @@ module ActiveRecord partial_writes? ? super(keys_for_partial_write) : super end - # Serialized attributes should always be written in case they've been - # changed in place. def keys_for_partial_write - changed & persistable_attribute_names + changed & self.class.column_names end def _field_changed?(attr, old_value) diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb index 0c9793d470..9142317646 100644 --- a/activerecord/lib/active_record/attribute_set.rb +++ b/activerecord/lib/active_record/attribute_set.rb @@ -10,6 +10,10 @@ module ActiveRecord attributes[name] || Attribute.null(name) end + def []=(name, value) + attributes[name] = value + end + def values_before_type_cast attributes.transform_values(&:value_before_type_cast) end @@ -49,7 +53,7 @@ module ActiveRecord end def initialize_dup(_) - @attributes = attributes.dup + @attributes = attributes.deep_dup super end diff --git a/activerecord/lib/active_record/attributes.rb b/activerecord/lib/active_record/attributes.rb index faf5d632ec..c1b69092bb 100644 --- a/activerecord/lib/active_record/attributes.rb +++ b/activerecord/lib/active_record/attributes.rb @@ -5,12 +5,8 @@ module ActiveRecord Type = ActiveRecord::Type included do - class_attribute :user_provided_columns, instance_accessor: false # :internal: - class_attribute :user_provided_defaults, instance_accessor: false # :internal: - self.user_provided_columns = {} - self.user_provided_defaults = {} - - delegate :persistable_attribute_names, to: :class + class_attribute :user_provided_types, instance_accessor: false # :internal: + self.user_provided_types = {} end module ClassMethods # :nodoc: @@ -77,70 +73,44 @@ module ActiveRecord # # store_listing = StoreListing.new(price_in_cents: '$10.00') # store_listing.price_in_cents # => 1000 - def attribute(name, cast_type, options = {}) + def attribute(name, cast_type, **options) name = name.to_s - clear_caches_calculated_from_columns - # Assign a new hash to ensure that subclasses do not share a hash - self.user_provided_columns = user_provided_columns.merge(name => cast_type) - - if options.key?(:default) - self.user_provided_defaults = user_provided_defaults.merge(name => options[:default]) - end - end + reload_schema_from_cache - # Returns an array of column objects for the table associated with this class. - def columns - @columns ||= add_user_provided_columns(connection.schema_cache.columns(table_name)) + self.user_provided_types = user_provided_types.merge(name => [cast_type, options]) end - # Returns a hash of column objects for the table associated with this class. - def columns_hash - @columns_hash ||= Hash[columns.map { |c| [c.name, c] }] + def define_attribute( + name, + cast_type, + default: NO_DEFAULT_PROVIDED, + user_provided_default: true + ) + attribute_types[name] = cast_type + define_default_attribute(name, default, cast_type, from_user: user_provided_default) end - def persistable_attribute_names # :nodoc: - @persistable_attribute_names ||= connection.schema_cache.columns_hash(table_name).keys - end - - def reset_column_information # :nodoc: + def load_schema! super - clear_caches_calculated_from_columns + user_provided_types.each do |name, (type, options)| + define_attribute(name, type, **options) + end end private - def add_user_provided_columns(schema_columns) - existing_columns = schema_columns.map do |column| - new_type = user_provided_columns[column.name] - if new_type - column.with_type(new_type) - else - column - end - end + NO_DEFAULT_PROVIDED = Object.new # :nodoc: + private_constant :NO_DEFAULT_PROVIDED - existing_column_names = existing_columns.map(&:name) - new_columns = user_provided_columns.except(*existing_column_names).map do |(name, type)| - connection.new_column(name, nil, type) + def define_default_attribute(name, value, type, from_user:) + if value == NO_DEFAULT_PROVIDED + default_attribute = _default_attributes[name].with_type(type) + elsif from_user + default_attribute = Attribute.from_user(name, value, type) + else + default_attribute = Attribute.from_database(name, value, type) end - - existing_columns + new_columns - end - - def clear_caches_calculated_from_columns - @arel_table = nil - @attributes_builder = nil - @column_names = nil - @column_types = nil - @columns = nil - @columns_hash = nil - @content_columns = nil - @default_attributes = nil - @persistable_attribute_names = nil - end - - def raw_default_values - super.merge(user_provided_defaults) + _default_attributes[name] = default_attribute end end end diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index e68b2c399c..4416217897 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -210,7 +210,7 @@ module ActiveRecord elsif !connected? "#{super} (call '#{super}.connection' to establish a connection)" elsif table_exists? - attr_list = column_types.map { |name, type| "#{name}: #{type.type}" } * ', ' + attr_list = attribute_types.map { |name, type| "#{name}: #{type.type}" } * ', ' "#{super}(#{attr_list})" else "#{super}(Table doesn't exist)" diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 5b1b7fe73d..739be524da 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -1,6 +1,7 @@ require 'erb' require 'yaml' require 'zlib' +require 'set' require 'active_support/dependencies' require 'active_support/core_ext/digest/uuid' require 'active_record/fixture_set/file' @@ -131,7 +132,7 @@ module ActiveRecord # Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path))) # end # end - # ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers + # ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers # # - use the helper method in a fixture # photo: @@ -521,12 +522,16 @@ module ActiveRecord update_all_loaded_fixtures fixtures_map connection.transaction(:requires_new => true) do + deleted_tables = Set.new fixture_sets.each do |fs| conn = fs.model_class.respond_to?(:connection) ? fs.model_class.connection : connection table_rows = fs.table_rows table_rows.each_key do |table| - conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete' + unless deleted_tables.include? table + conn.delete "DELETE FROM #{conn.quote_table_name(table)}", 'Fixture Delete' + end + deleted_tables << table end table_rows.each do |fixture_set_name, rows| diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index fd1e22349b..24098f72dc 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -192,7 +192,7 @@ module ActiveRecord # If this is a StrongParameters hash, and access to inheritance_column is not permitted, # this will ignore the inheritance column and return nil def subclass_from_attributes?(attrs) - columns_hash.include?(inheritance_column) && attrs.is_a?(Hash) + attribute_names.include?(inheritance_column) && attrs.is_a?(Hash) end def subclass_from_attributes(attrs) diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 6f2b65c137..008cda46cd 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -144,7 +144,7 @@ module ActiveRecord # Set the column to use for optimistic locking. Defaults to +lock_version+. def locking_column=(value) - clear_caches_calculated_from_columns + reload_schema_from_cache @locking_column = value.to_s end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index af0b667262..293db1c57f 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -217,28 +217,37 @@ module ActiveRecord end def attributes_builder # :nodoc: - @attributes_builder ||= AttributeSet::Builder.new(column_types, primary_key) + @attributes_builder ||= AttributeSet::Builder.new(attribute_types, primary_key) end - def column_types # :nodoc: - @column_types ||= columns_hash.transform_values(&:cast_type).tap do |h| - h.default = Type::Value.new - end + def columns_hash # :nodoc: + load_schema + @columns_hash + end + + def columns + load_schema + @columns ||= columns_hash.values + end + + def attribute_types # :nodoc: + load_schema + @attribute_types ||= Hash.new(Type::Value.new) end def type_for_attribute(attr_name) # :nodoc: - column_types[attr_name] + attribute_types[attr_name] end # Returns a hash where the keys are column names and the values are # default values when instantiating the AR object for this table. def column_defaults + load_schema _default_attributes.to_hash end def _default_attributes # :nodoc: - @default_attributes ||= attributes_builder.build_from_database( - raw_default_values) + @default_attributes ||= AttributeSet.new({}) end # Returns an array of column names as strings. @@ -281,19 +290,53 @@ module ActiveRecord def reset_column_information connection.clear_cache! undefine_attribute_methods - connection.schema_cache.clear_table_cache!(table_name) if table_exists? + connection.schema_cache.clear_table_cache!(table_name) - @arel_engine = nil - @arel_table = nil - @column_names = nil - @column_types = nil - @content_columns = nil - @default_attributes = nil - @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column + reload_schema_from_cache end private + def schema_loaded? + defined?(@columns_hash) && @columns_hash + end + + def load_schema + unless schema_loaded? + load_schema! + end + end + + def load_schema! + @columns_hash = connection.schema_cache.columns_hash(table_name) + @columns_hash.each do |name, column| + define_attribute( + name, + column.cast_type, + default: column.default, + user_provided_default: false + ) + end + end + + def reload_schema_from_cache + @arel_engine = nil + @arel_table = nil + @column_names = nil + @attribute_types = nil + @content_columns = nil + @default_attributes = nil + @inheritance_column = nil unless defined?(@explicit_inheritance_column) && @explicit_inheritance_column + @attributes_builder = nil + @column_names = nil + @attribute_types = nil + @columns = nil + @columns_hash = nil + @content_columns = nil + @default_attributes = nil + @attribute_names = nil + end + # Guesses the table name, but does not decorate it with prefix and suffix information. def undecorated_table_name(class_name = base_class.name) table_name = class_name.to_s.demodulize.underscore @@ -317,10 +360,6 @@ module ActiveRecord base.table_name end end - - def raw_default_values - columns_hash.transform_values(&:default) - end end end end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index c3c4d7f1ce..63e0d2fc21 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -167,7 +167,7 @@ module ActiveRecord columns_hash.key?(cn) ? arel_table[cn] : cn } result = klass.connection.select_all(relation.arel, nil, bound_attributes) - result.cast_values(klass.column_types) + result.cast_values(klass.attribute_types) end end diff --git a/activerecord/test/active_record/connection_adapters/fake_adapter.rb b/activerecord/test/active_record/connection_adapters/fake_adapter.rb index 64cde143a1..ad9279aaca 100644 --- a/activerecord/test/active_record/connection_adapters/fake_adapter.rb +++ b/activerecord/test/active_record/connection_adapters/fake_adapter.rb @@ -22,7 +22,7 @@ module ActiveRecord end def primary_key(table) - @primary_keys[table] + @primary_keys[table] || "id" end def merge_column(table_name, name, sql_type = nil, options = {}) @@ -38,6 +38,10 @@ module ActiveRecord @columns[table_name] end + def table_exists?(*) + true + end + def active? true end diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index e38b32d7fc..74e556211b 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -17,7 +17,7 @@ module ActiveRecord include ActiveRecord::AttributeMethods - def self.column_names + def self.attribute_names %w{ one two three } end @@ -25,11 +25,11 @@ module ActiveRecord end def self.columns - column_names.map { FakeColumn.new(name) } + attribute_names.map { FakeColumn.new(name) } end def self.columns_hash - Hash[column_names.map { |name| + Hash[attribute_names.map { |name| [name, FakeColumn.new(name)] }] end @@ -39,13 +39,13 @@ module ActiveRecord def test_define_attribute_methods instance = @klass.new - @klass.column_names.each do |name| + @klass.attribute_names.each do |name| assert !instance.methods.map(&:to_s).include?(name) end @klass.define_attribute_methods - @klass.column_names.each do |name| + @klass.attribute_names.each do |name| assert instance.methods.map(&:to_s).include?(name), "#{name} is not defined" end end diff --git a/activerecord/test/cases/attributes_test.rb b/activerecord/test/cases/attributes_test.rb index 4ddf6e7ba0..6f331c5985 100644 --- a/activerecord/test/cases/attributes_test.rb +++ b/activerecord/test/cases/attributes_test.rb @@ -50,8 +50,8 @@ module ActiveRecord end test "overloaded properties with limit" do - assert_equal 50, OverloadedType.columns_hash['overloaded_string_with_limit'].limit - assert_equal 255, UnoverloadedType.columns_hash['overloaded_string_with_limit'].limit + assert_equal 50, OverloadedType.type_for_attribute('overloaded_string_with_limit').limit + assert_equal 255, UnoverloadedType.type_for_attribute('overloaded_string_with_limit').limit end test "nonexistent attribute" do @@ -87,29 +87,42 @@ module ActiveRecord assert_equal 4.4, data.overloaded_float end - test "overloading properties does not change column order" do - column_names = OverloadedType.column_names - assert_equal %w(id overloaded_float unoverloaded_float overloaded_string_with_limit string_with_default non_existent_decimal), column_names + test "overloading properties does not attribute method order" do + attribute_names = OverloadedType.attribute_names + assert_equal %w(id overloaded_float unoverloaded_float overloaded_string_with_limit string_with_default non_existent_decimal), attribute_names end test "caches are cleared" do klass = Class.new(OverloadedType) - assert_equal 6, klass.columns.length - assert_not klass.columns_hash.key?('wibble') - assert_equal 6, klass.column_types.length + assert_equal 6, klass.attribute_types.length assert_equal 6, klass.column_defaults.length - assert_not klass.column_names.include?('wibble') - assert_equal 5, klass.content_columns.length + assert_not klass.attribute_types.include?('wibble') klass.attribute :wibble, Type::Value.new - assert_equal 7, klass.columns.length - assert klass.columns_hash.key?('wibble') - assert_equal 7, klass.column_types.length + assert_equal 7, klass.attribute_types.length assert_equal 7, klass.column_defaults.length - assert klass.column_names.include?('wibble') - assert_equal 6, klass.content_columns.length + assert klass.attribute_types.include?('wibble') + end + + test "the given default value is cast from user" do + custom_type = Class.new(Type::Value) do + def type_cast_from_user(*) + "from user" + end + + def type_cast_from_database(*) + "from database" + end + end + + klass = Class.new(OverloadedType) do + attribute :wibble, custom_type.new, default: "default" + end + model = klass.new + + assert_equal "from user", model.wibble end end end diff --git a/activerecord/test/cases/fixtures_test.rb b/activerecord/test/cases/fixtures_test.rb index 07ec08ccf5..f41245dfd2 100644 --- a/activerecord/test/cases/fixtures_test.rb +++ b/activerecord/test/cases/fixtures_test.rb @@ -672,7 +672,8 @@ class FasterFixturesTest < ActiveRecord::TestCase end class FoxyFixturesTest < ActiveRecord::TestCase - fixtures :parrots, :parrots_pirates, :pirates, :treasures, :mateys, :ships, :computers, :developers, :"admin/accounts", :"admin/users" + fixtures :parrots, :parrots_pirates, :pirates, :treasures, :mateys, :ships, :computers, + :developers, :"admin/accounts", :"admin/users", :live_parrots, :dead_parrots if ActiveRecord::Base.connection.adapter_name == 'PostgreSQL' require 'models/uuid_parent' @@ -812,6 +813,12 @@ class FoxyFixturesTest < ActiveRecord::TestCase assert_equal pirates(:blackbeard), parrots(:polly).killer end + def test_supports_sti_with_respective_files + assert_kind_of LiveParrot, live_parrots(:dusty) + assert_kind_of DeadParrot, dead_parrots(:deadbird) + assert_equal pirates(:blackbeard), dead_parrots(:deadbird).killer + end + def test_namespaced_models assert admin_accounts(:signals37).users.include?(admin_users(:david)) assert_equal 2, admin_accounts(:signals37).users.size @@ -834,9 +841,9 @@ class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase set_fixture_class :randomly_named_a9 => ClassNameThatDoesNotFollowCONVENTIONS, :'admin/randomly_named_a9' => - Admin::ClassNameThatDoesNotFollowCONVENTIONS, + Admin::ClassNameThatDoesNotFollowCONVENTIONS1, 'admin/randomly_named_b0' => - Admin::ClassNameThatDoesNotFollowCONVENTIONS + Admin::ClassNameThatDoesNotFollowCONVENTIONS2 fixtures :randomly_named_a9, 'admin/randomly_named_a9', :'admin/randomly_named_b0' @@ -847,15 +854,15 @@ class CustomNameForFixtureOrModelTest < ActiveRecord::TestCase end def test_named_accessor_for_randomly_named_namespaced_fixture_and_class - assert_kind_of Admin::ClassNameThatDoesNotFollowCONVENTIONS, + assert_kind_of Admin::ClassNameThatDoesNotFollowCONVENTIONS1, admin_randomly_named_a9(:first_instance) - assert_kind_of Admin::ClassNameThatDoesNotFollowCONVENTIONS, + assert_kind_of Admin::ClassNameThatDoesNotFollowCONVENTIONS2, admin_randomly_named_b0(:second_instance) end def test_table_name_is_defined_in_the_model - assert_equal 'randomly_named_table', ActiveRecord::FixtureSet::all_loaded_fixtures["admin/randomly_named_a9"].table_name - assert_equal 'randomly_named_table', Admin::ClassNameThatDoesNotFollowCONVENTIONS.table_name + assert_equal 'randomly_named_table2', ActiveRecord::FixtureSet::all_loaded_fixtures["admin/randomly_named_a9"].table_name + assert_equal 'randomly_named_table2', Admin::ClassNameThatDoesNotFollowCONVENTIONS1.table_name end end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index a5d7cc2dff..6ea8b93be7 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -162,6 +162,7 @@ class MigrationTest < ActiveRecord::TestCase assert !BigNumber.table_exists? GiveMeBigNumbers.up + BigNumber.reset_column_information assert BigNumber.create( :bank_balance => 1586.43, @@ -397,6 +398,7 @@ class MigrationTest < ActiveRecord::TestCase Thing.reset_table_name Thing.reset_sequence_name WeNeedThings.up + Thing.reset_column_information assert Thing.create("content" => "hello world") assert_equal "hello world", Thing.first.content @@ -416,6 +418,7 @@ class MigrationTest < ActiveRecord::TestCase ActiveRecord::Base.table_name_suffix = '_suffix' Reminder.reset_table_name Reminder.reset_sequence_name + Reminder.reset_column_information WeNeedReminders.up assert Reminder.create("content" => "hello world", "remind_at" => Time.now) assert_equal "hello world", Reminder.first.content diff --git a/activerecord/test/fixtures/dead_parrots.yml b/activerecord/test/fixtures/dead_parrots.yml new file mode 100644 index 0000000000..da5529dd27 --- /dev/null +++ b/activerecord/test/fixtures/dead_parrots.yml @@ -0,0 +1,5 @@ +deadbird: + name: "Dusty DeadBird" + treasures: [ruby, sapphire] + parrot_sti_class: DeadParrot + killer: blackbeard diff --git a/activerecord/test/fixtures/live_parrots.yml b/activerecord/test/fixtures/live_parrots.yml new file mode 100644 index 0000000000..95b2078da7 --- /dev/null +++ b/activerecord/test/fixtures/live_parrots.yml @@ -0,0 +1,4 @@ +dusty: + name: "Dusty Bluebird" + treasures: [ruby, sapphire] + parrot_sti_class: LiveParrot diff --git a/activerecord/test/models/admin/randomly_named_c1.rb b/activerecord/test/models/admin/randomly_named_c1.rb index 2f81d5b831..b64ae7fc41 100644 --- a/activerecord/test/models/admin/randomly_named_c1.rb +++ b/activerecord/test/models/admin/randomly_named_c1.rb @@ -1,3 +1,7 @@ -class Admin::ClassNameThatDoesNotFollowCONVENTIONS < ActiveRecord::Base
- self.table_name = :randomly_named_table
+class Admin::ClassNameThatDoesNotFollowCONVENTIONS1 < ActiveRecord::Base
+ self.table_name = :randomly_named_table2
+end
+
+class Admin::ClassNameThatDoesNotFollowCONVENTIONS2 < ActiveRecord::Base
+ self.table_name = :randomly_named_table3
end
diff --git a/activerecord/test/models/randomly_named_c1.rb b/activerecord/test/models/randomly_named_c1.rb index 18a86c4989..d4be1e13b4 100644 --- a/activerecord/test/models/randomly_named_c1.rb +++ b/activerecord/test/models/randomly_named_c1.rb @@ -1,3 +1,3 @@ class ClassNameThatDoesNotFollowCONVENTIONS < ActiveRecord::Base
- self.table_name = :randomly_named_table
+ self.table_name = :randomly_named_table1
end
diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 1add85cc05..49dbc5dabf 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -623,7 +623,17 @@ ActiveRecord::Schema.define do t.string :type end - create_table :randomly_named_table, force: true do |t| + create_table :randomly_named_table1, force: true do |t| + t.string :some_attribute + t.integer :another_attribute + end + + create_table :randomly_named_table2, force: true do |t| + t.string :some_attribute + t.integer :another_attribute + end + + create_table :randomly_named_table3, force: true do |t| t.string :some_attribute t.integer :another_attribute end diff --git a/activesupport/lib/active_support/concern.rb b/activesupport/lib/active_support/concern.rb index 342d3a9d52..4082d2d464 100644 --- a/activesupport/lib/active_support/concern.rb +++ b/activesupport/lib/active_support/concern.rb @@ -114,7 +114,7 @@ module ActiveSupport return false else return false if base < self - @_dependencies.each { |dep| base.send(:include, dep) } + @_dependencies.each { |dep| base.include(dep) } super base.extend const_get(:ClassMethods) if const_defined?(:ClassMethods) base.class_eval(&@_included_block) if instance_variable_defined?(:@_included_block) diff --git a/activesupport/lib/active_support/i18n_railtie.rb b/activesupport/lib/active_support/i18n_railtie.rb index 9e742b1917..95f3f6255a 100644 --- a/activesupport/lib/active_support/i18n_railtie.rb +++ b/activesupport/lib/active_support/i18n_railtie.rb @@ -68,7 +68,7 @@ module I18n end def self.include_fallbacks_module - I18n.backend.class.send(:include, I18n::Backend::Fallbacks) + I18n.backend.class.include(I18n::Backend::Fallbacks) end def self.init_fallbacks(fallbacks) diff --git a/activesupport/lib/active_support/xml_mini/libxml.rb b/activesupport/lib/active_support/xml_mini/libxml.rb index 47a2824186..bb0ea9c582 100644 --- a/activesupport/lib/active_support/xml_mini/libxml.rb +++ b/activesupport/lib/active_support/xml_mini/libxml.rb @@ -75,5 +75,5 @@ module LibXML #:nodoc: end end -LibXML::XML::Document.send(:include, LibXML::Conversions::Document) -LibXML::XML::Node.send(:include, LibXML::Conversions::Node) +LibXML::XML::Document.include(LibXML::Conversions::Document) +LibXML::XML::Node.include(LibXML::Conversions::Node) diff --git a/activesupport/lib/active_support/xml_mini/nokogiri.rb b/activesupport/lib/active_support/xml_mini/nokogiri.rb index 7398d4fa82..619cc7522d 100644 --- a/activesupport/lib/active_support/xml_mini/nokogiri.rb +++ b/activesupport/lib/active_support/xml_mini/nokogiri.rb @@ -77,7 +77,7 @@ module ActiveSupport end end - Nokogiri::XML::Document.send(:include, Conversions::Document) - Nokogiri::XML::Node.send(:include, Conversions::Node) + Nokogiri::XML::Document.include(Conversions::Document) + Nokogiri::XML::Node.include(Conversions::Node) end end diff --git a/activesupport/test/concern_test.rb b/activesupport/test/concern_test.rb index 60bd8a06aa..253c1adc23 100644 --- a/activesupport/test/concern_test.rb +++ b/activesupport/test/concern_test.rb @@ -59,24 +59,24 @@ class ConcernTest < ActiveSupport::TestCase end def test_module_is_included_normally - @klass.send(:include, Baz) + @klass.include(Baz) assert_equal "baz", @klass.new.baz assert @klass.included_modules.include?(ConcernTest::Baz) end def test_class_methods_are_extended - @klass.send(:include, Baz) + @klass.include(Baz) assert_equal "baz", @klass.baz assert_equal ConcernTest::Baz::ClassMethods, (class << @klass; self.included_modules; end)[0] end def test_included_block_is_ran - @klass.send(:include, Baz) + @klass.include(Baz) assert_equal true, @klass.included_ran end def test_modules_dependencies_are_met - @klass.send(:include, Bar) + @klass.include(Bar) assert_equal "bar", @klass.new.bar assert_equal "bar+baz", @klass.new.baz assert_equal "bar's baz + baz", @klass.baz @@ -84,7 +84,7 @@ class ConcernTest < ActiveSupport::TestCase end def test_dependencies_with_multiple_modules - @klass.send(:include, Foo) + @klass.include(Foo) assert_equal [ConcernTest::Foo, ConcernTest::Bar, ConcernTest::Baz], @klass.included_modules[0..2] end diff --git a/guides/source/upgrading_ruby_on_rails.md b/guides/source/upgrading_ruby_on_rails.md index d7fbe575c2..909a92b9dd 100644 --- a/guides/source/upgrading_ruby_on_rails.md +++ b/guides/source/upgrading_ruby_on_rails.md @@ -534,7 +534,7 @@ module FixtureFileHelpers Digest::SHA2.hexdigest(File.read(Rails.root.join('test/fixtures', path))) end end -ActiveRecord::FixtureSet.context_class.send :include, FixtureFileHelpers +ActiveRecord::FixtureSet.context_class.include FixtureFileHelpers ``` ### I18n enforcing available locales diff --git a/railties/lib/rails/commands/console.rb b/railties/lib/rails/commands/console.rb index 35a815a34f..5d37a2b699 100644 --- a/railties/lib/rails/commands/console.rb +++ b/railties/lib/rails/commands/console.rb @@ -79,7 +79,7 @@ module Rails end if defined?(console::ExtendCommandBundle) - console::ExtendCommandBundle.send :include, Rails::ConsoleMethods + console::ExtendCommandBundle.include(Rails::ConsoleMethods) end console.start end diff --git a/railties/lib/rails/engine.rb b/railties/lib/rails/engine.rb index 1290b16872..dc8785c1c1 100644 --- a/railties/lib/rails/engine.rb +++ b/railties/lib/rails/engine.rb @@ -484,7 +484,7 @@ module Rails helpers = Module.new all = ActionController::Base.all_helpers_from_path(helpers_paths) ActionController::Base.modules_for_helpers(all).each do |mod| - helpers.send(:include, mod) + helpers.include(mod) end helpers end diff --git a/railties/lib/rails/generators/app_base.rb b/railties/lib/rails/generators/app_base.rb index 4c53248762..057c8b0aec 100644 --- a/railties/lib/rails/generators/app_base.rb +++ b/railties/lib/rails/generators/app_base.rb @@ -127,7 +127,7 @@ module Rails def builder @builder ||= begin builder_class = get_builder_class - builder_class.send(:include, ActionMethods) + builder_class.include(ActionMethods) builder_class.new(self) end end diff --git a/railties/lib/rails/generators/resource_helpers.rb b/railties/lib/rails/generators/resource_helpers.rb index 3f84d76ae0..9c2037783e 100644 --- a/railties/lib/rails/generators/resource_helpers.rb +++ b/railties/lib/rails/generators/resource_helpers.rb @@ -8,7 +8,7 @@ module Rails module ResourceHelpers # :nodoc: def self.included(base) #:nodoc: - base.send :include, Rails::Generators::ModelHelpers + base.include(Rails::Generators::ModelHelpers) base.class_option :model_name, type: :string, desc: "ModelName to be used" end diff --git a/railties/test/rails_info_controller_test.rb b/railties/test/rails_info_controller_test.rb index d336a2e6c0..25b0e761cb 100644 --- a/railties/test/rails_info_controller_test.rb +++ b/railties/test/rails_info_controller_test.rb @@ -16,7 +16,7 @@ class InfoControllerTest < ActionController::TestCase end @routes = Rails.application.routes - Rails::InfoController.send(:include, @routes.url_helpers) + Rails::InfoController.include(@routes.url_helpers) @request.env["REMOTE_ADDR"] = "127.0.0.1" end |