diff options
Diffstat (limited to 'activerecord')
79 files changed, 638 insertions, 751 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index ffd19a5334..1d43840573 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,63 @@ ## Rails 4.0.0 (unreleased) ## +* Fix `find_in_batches` crashing when IDs are strings and start option is not specified. + + *Alexis Bernard* + +* `AR::Base#attributes_before_type_cast` now returns unserialized values for serialized attributes. + + *Nikita Afanasenko* + +* Use query cache/uncache when using DATABASE_URL. + Fix #6951. + + *kennyj* + +* Added `#none!` method for mutating `ActiveRecord::Relation` objects to a NullRelation. + It acts like `#none` but modifies relation in place. + + *Juanjo Bazán* + +* Fix bug where `update_columns` and `update_column` would not let you update the primary key column. + + *Henrik Nyh* + +* The `create_table` method raises an `ArgumentError` when the primary key column is redefined. + Fix #6378 + + *Yves Senn* + +* `ActiveRecord::AttributeMethods#[]` raises `ActiveModel::MissingAttributeError` + error if the given attribute is missing. Fixes #5433. + + class Person < ActiveRecord::Base + belongs_to :company + end + + # Before: + person = Person.select('id').first + person[:name] # => nil + person.name # => ActiveModel::MissingAttributeError: missing_attribute: name + person[:company_id] # => nil + person.company # => nil + + # After: + person = Person.select('id').first + person[:name] # => ActiveModel::MissingAttributeError: missing_attribute: name + person.name # => ActiveModel::MissingAttributeError: missing_attribute: name + person[:company_id] # => ActiveModel::MissingAttributeError: missing_attribute: company_id + person.company # => ActiveModel::MissingAttributeError: missing_attribute: company_id + + *Francesco Rodriguez* + +* Small binary fields use the `VARBINARY` MySQL type, instead of `TINYBLOB`. + + *Victor Costan* + +* Decode URI encoded attributes on database connection URLs. + + *Shawn Veader* + * Add `find_or_create_by`, `find_or_create_by!` and `find_or_initialize_by` methods to `Relation`. @@ -38,12 +96,12 @@ *Jon Leighton* -* Fix bug with presence validation of associations. Would incorrectly add duplicated errors +* Fix bug with presence validation of associations. Would incorrectly add duplicated errors when the association was blank. Bug introduced in 1fab518c6a75dac5773654646eb724a59741bc13. *Scott Willson* -* Fix bug where sum(expression) returns string '0' for no matching records +* Fix bug where sum(expression) returns string '0' for no matching records. Fixes #7439 *Tim Macfarlane* @@ -338,7 +396,7 @@ * Fix AR#dup to nullify the validation errors in the dup'ed object. Previously the original and the dup'ed object shared the same errors. - * Christian Seiler* + *Christian Seiler* * Raise `ArgumentError` if list of attributes to change is empty in `update_all`. @@ -926,34 +984,6 @@ *Aaron Patterson* -* Added the `ActiveRecord::Model` module which can be included in a - class as an alternative to inheriting from `ActiveRecord::Base`: - - class Post - include ActiveRecord::Model - end - - Please note: - - * Up until now it has been safe to assume that all AR models are - descendants of `ActiveRecord::Base`. This is no longer a safe - assumption, but it may transpire that there are areas of the - code which still make this assumption. So there may be - 'teething difficulties' with this feature. (But please do try it - and report bugs.) - - * Plugins & libraries etc that add methods to `ActiveRecord::Base` - will not be compatible with `ActiveRecord::Model`. Those libraries - should add to `ActiveRecord::Model` instead (which is included in - `Base`), or better still, avoid monkey-patching AR and instead - provide a module that users can include where they need it. - - * To minimise the risk of conflicts with other code, it is - advisable to include `ActiveRecord::Model` early in your class - definition. - - *Jon Leighton* - * PostgreSQL hstore records can be created. *Aaron Patterson* diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 1675127ab0..45122539f1 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -43,7 +43,6 @@ module ActiveRecord autoload :Integration autoload :Migration autoload :Migrator, 'active_record/migration' - autoload :Model autoload :ModelSchema autoload :NestedAttributes autoload :Observer diff --git a/activerecord/lib/active_record/associations/alias_tracker.rb b/activerecord/lib/active_record/associations/alias_tracker.rb index 84540a7000..0c23029981 100644 --- a/activerecord/lib/active_record/associations/alias_tracker.rb +++ b/activerecord/lib/active_record/associations/alias_tracker.rb @@ -8,7 +8,7 @@ module ActiveRecord attr_reader :aliases, :table_joins, :connection # table_joins is an array of arel joins which might conflict with the aliases we assign here - def initialize(connection = ActiveRecord::Model.connection, table_joins = []) + def initialize(connection = Base.connection, table_joins = []) @aliases = Hash.new { |h,k| h[k] = initial_count_for(k) } @table_joins = table_joins @connection = connection diff --git a/activerecord/lib/active_record/associations/association.rb b/activerecord/lib/active_record/associations/association.rb index 2a5f727728..99e7383d42 100644 --- a/activerecord/lib/active_record/associations/association.rb +++ b/activerecord/lib/active_record/associations/association.rb @@ -85,7 +85,7 @@ module ActiveRecord end def scoped - ActiveSupport::Deprecation.warn("#scoped is deprecated. use #scope instead.") + ActiveSupport::Deprecation.warn "#scoped is deprecated. use #scope instead." scope end diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 7f39d3083e..54215cf88d 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -576,7 +576,9 @@ module ActiveRecord args.shift if args.first.is_a?(Hash) && args.first.empty? collection = fetch_first_or_last_using_find?(args) ? scope : load_target - collection.send(type, *args).tap {|it| set_inverse_instance it } + collection.send(type, *args).tap do |record| + set_inverse_instance record if record.is_a? ActiveRecord::Base + end end end end diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 1dd9a3d45d..437fd00948 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -59,7 +59,7 @@ module ActiveRecord raise DangerousAttributeError, "#{method_name} is defined by ActiveRecord" end - if [Base, Model].include?(active_record_super) + if superclass == Base super else # If B < A and A defines its own attribute method, then we don't want to overwrite that. @@ -269,17 +269,24 @@ module ActiveRecord end # Returns the value of the attribute identified by <tt>attr_name</tt> after it has been typecast (for example, - # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). - # (Alias for <tt>read_attribute</tt>). + # "2004-12-12" in a data column is cast to a date object, like Date.new(2004, 12, 12)). It raises + # <tt>ActiveModel::MissingAttributeError</tt> if the identified attribute is missing. + # + # Alias for the <tt>read_attribute</tt> method. # # class Person < ActiveRecord::Base + # belongs_to :organization # end # # person = Person.new(name: 'Francesco', age: '22') # person[:name] # => "Francesco" # person[:age] # => 22 + # + # person = Person.select('id').first + # person[:name] # => ActiveModel::MissingAttributeError: missing attribute: name + # person[:organization_id] # => ActiveModel::MissingAttributeError: missing attribute: organization_id def [](attr_name) - read_attribute(attr_name) + read_attribute(attr_name) { |n| missing_attribute(n, caller) } end # Updates the attribute identified by <tt>attr_name</tt> with the specified +value+. diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 59f209cec8..0333605eac 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -2,11 +2,6 @@ require 'active_support/core_ext/module/attribute_accessors' require 'active_support/deprecation' module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :partial_writes, instance_accessor: false - self.partial_writes = true - end - module AttributeMethods module Dirty # :nodoc: extend ActiveSupport::Concern @@ -18,7 +13,8 @@ module ActiveRecord raise "You cannot include Dirty after Timestamp" end - config_attribute :partial_writes + class_attribute :partial_writes, instance_writer: false + self.partial_writes = true def self.partial_updates=(v); self.partial_writes = v; end def self.partial_updates?; partial_writes?; end diff --git a/activerecord/lib/active_record/attribute_methods/read.rb b/activerecord/lib/active_record/attribute_methods/read.rb index 46fd6ebfb3..90701938e5 100644 --- a/activerecord/lib/active_record/attribute_methods/read.rb +++ b/activerecord/lib/active_record/attribute_methods/read.rb @@ -1,8 +1,4 @@ module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :attribute_types_cached_by_default, instance_accessor: false - end - module AttributeMethods module Read extend ActiveSupport::Concern @@ -10,7 +6,8 @@ module ActiveRecord ATTRIBUTE_TYPES_CACHED_BY_DEFAULT = [:datetime, :timestamp, :time, :date] included do - config_attribute :attribute_types_cached_by_default + class_attribute :attribute_types_cached_by_default, instance_writer: false + self.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT end module ClassMethods @@ -35,36 +32,21 @@ module ActiveRecord protected - # We want to generate the methods via module_eval rather than - # define_method, because define_method is slower on dispatch and - # uses more memory (because it creates a closure). + # We want to generate the methods via module_eval rather than define_method, + # because define_method is slower on dispatch and uses more memory (because it + # creates a closure). # - # But sometimes the database might return columns with - # characters that are not allowed in normal method names (like - # 'my_column(omg)'. So to work around this we first define with - # the __temp__ identifier, and then use alias method to rename - # it to what we want. - # - # We are also defining a constant to hold the frozen string of - # the attribute name. Using a constant means that we do not have - # to allocate an object on each call to the attribute method. - # Making it frozen means that it doesn't get duped when used to - # key the @attributes_cache in read_attribute. - def define_method_attribute(name) - safe_name = name.unpack('h*').first + # But sometimes the database might return columns with characters that are not + # allowed in normal method names (like 'my_column(omg)'. So to work around this + # we first define with the __temp__ identifier, and then use alias method to + # rename it to what we want. + def define_method_attribute(attr_name) generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 - module AttrNames - unless defined? ATTR_#{safe_name} - ATTR_#{safe_name} = #{name.inspect}.freeze - end + def __temp__ + read_attribute('#{attr_name}') { |n| missing_attribute(n, caller) } end - - def __temp__#{safe_name} - read_attribute(AttrNames::ATTR_#{safe_name}) { |n| missing_attribute(n, caller) } - end - - alias_method #{name.inspect}, :__temp__#{safe_name} - undef_method :__temp__#{safe_name} + alias_method '#{attr_name}', :__temp__ + undef_method :__temp__ STR end @@ -79,8 +61,6 @@ module ActiveRecord end end - ActiveRecord::Model.attribute_types_cached_by_default = ATTRIBUTE_TYPES_CACHED_BY_DEFAULT - # Returns the value of the attribute identified by <tt>attr_name</tt> after # it has been typecast (for example, "2004-12-12" in a data column is cast # to a date object, like Date.new(2004, 12, 12)). diff --git a/activerecord/lib/active_record/attribute_methods/serialization.rb b/activerecord/lib/active_record/attribute_methods/serialization.rb index 9994a81ede..5b9ed81424 100644 --- a/activerecord/lib/active_record/attribute_methods/serialization.rb +++ b/activerecord/lib/active_record/attribute_methods/serialization.rb @@ -45,7 +45,8 @@ module ActiveRecord end def serialized_attributes - ActiveSupport::Deprecation.warn("Instance level serialized_attributes method is deprecated, please use class level method.") + message = "Instance level serialized_attributes method is deprecated, please use class level method." + ActiveSupport::Deprecation.warn message defined?(@serialized_attributes) ? @serialized_attributes : self.class.serialized_attributes end @@ -118,6 +119,16 @@ module ActiveRecord super end end + + def attributes_before_type_cast + super.dup.tap do |attributes| + self.class.serialized_attributes.each_key do |key| + if attributes.key?(key) + attributes[key] = attributes[key].unserialized_value + end + end + end + end end end end diff --git a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb index f36a5806a9..806dc5b1d2 100644 --- a/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb +++ b/activerecord/lib/active_record/attribute_methods/time_zone_conversion.rb @@ -1,13 +1,4 @@ - module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :time_zone_aware_attributes, instance_accessor: false - self.time_zone_aware_attributes = false - - mattr_accessor :skip_time_zone_conversion_for_attributes, instance_accessor: false - self.skip_time_zone_conversion_for_attributes = [] - end - module AttributeMethods module TimeZoneConversion class Type # :nodoc: @@ -28,8 +19,11 @@ module ActiveRecord extend ActiveSupport::Concern included do - config_attribute :time_zone_aware_attributes, global: true - config_attribute :skip_time_zone_conversion_for_attributes + mattr_accessor :time_zone_aware_attributes, instance_writer: false + self.time_zone_aware_attributes = false + + class_attribute :skip_time_zone_conversion_for_attributes, instance_writer: false + self.skip_time_zone_conversion_for_attributes = [] end module ClassMethods diff --git a/activerecord/lib/active_record/attribute_methods/write.rb b/activerecord/lib/active_record/attribute_methods/write.rb index cd33494cc3..fa9097db1f 100644 --- a/activerecord/lib/active_record/attribute_methods/write.rb +++ b/activerecord/lib/active_record/attribute_methods/write.rb @@ -9,19 +9,15 @@ module ActiveRecord module ClassMethods protected - - # See define_method_attribute in read.rb for an explanation of - # this code. - def define_method_attribute=(name) - safe_name = name.unpack('h*').first - generated_attribute_methods.module_eval <<-STR, __FILE__, __LINE__ + 1 - def __temp__#{safe_name}=(value) - write_attribute(AttrNames::ATTR_#{safe_name}, value) + def define_method_attribute=(attr_name) + if attr_name =~ ActiveModel::AttributeMethods::NAME_COMPILABLE_REGEXP + generated_attribute_methods.module_eval("def #{attr_name}=(new_value); write_attribute('#{attr_name}', new_value); end", __FILE__, __LINE__) + else + generated_attribute_methods.send(:define_method, "#{attr_name}=") do |new_value| + write_attribute(attr_name, new_value) + end end - alias_method #{(name + '=').inspect}, :__temp__#{safe_name}= - undef_method :__temp__#{safe_name}= - STR - end + end end # Updates the attribute identified by <tt>attr_name</tt> with the diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index a4705b24ca..eabbd80f66 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -321,8 +321,48 @@ module ActiveRecord #:nodoc: # So it's possible to assign a logger to the class through <tt>Base.logger=</tt> which will then be used by all # instances in the current object space. class Base - include ActiveRecord::Model + extend ActiveModel::Observing::ClassMethods + extend ActiveModel::Naming + + extend ActiveSupport::Benchmarkable + extend ActiveSupport::DescendantsTracker + + extend ConnectionHandling + extend QueryCache::ClassMethods + extend Querying + extend Translation + extend DynamicMatchers + extend Explain + extend ConnectionHandling + + include Persistence + include ReadonlyAttributes + include ModelSchema + include Inheritance + include Scoping + include Sanitization + include AttributeAssignment + include ActiveModel::Conversion + include Integration + include Validations + include CounterCache + include Locking::Optimistic + include Locking::Pessimistic + include AttributeMethods + include Callbacks + include ActiveModel::Observing + include Timestamp + include Associations + include ActiveModel::SecurePassword + include AutosaveAssociation + include NestedAttributes + include Aggregations + include Transactions + include Reflection + include Serialization + include Store + include Core end -end -ActiveSupport.run_load_hooks(:active_record, ActiveRecord::Model::DeprecationProxy.new) + ActiveSupport.run_load_hooks(:active_record, Base) +end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb index 42bd16db80..1da95f451f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -441,11 +441,11 @@ module ActiveRecord end def new_connection - ActiveRecord::Model.send(spec.adapter_method, spec.config) + Base.send(spec.adapter_method, spec.config) end def current_connection_id #:nodoc: - ActiveRecord::Model.connection_id ||= Thread.current.object_id + Base.connection_id ||= Thread.current.object_id end def checkout_new_connection @@ -567,10 +567,10 @@ module ActiveRecord class_to_pool[klass] ||= begin until pool = pool_for(klass) klass = klass.superclass - break unless klass < ActiveRecord::Tag + break unless klass <= Base end - class_to_pool[klass] = pool || pool_for(ActiveRecord::Model) + class_to_pool[klass] = pool end end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb index d61731633a..38960ab873 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb @@ -234,6 +234,10 @@ module ActiveRecord name = name.to_s type = type.to_sym + if primary_key_column_name == name + raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table." + end + column = self[name] || new_column_definition(@base, name, type) limit = options.fetch(:limit) do @@ -302,6 +306,11 @@ module ActiveRecord definition end + def primary_key_column_name + primary_key_column = columns.detect { |c| c.type == :primary_key } + primary_key_column && primary_key_column.name + end + def native @base.native_database_types end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 0cb219767b..8517ce5fc5 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -3,7 +3,7 @@ require 'bigdecimal' require 'bigdecimal/util' require 'active_support/core_ext/benchmark' require 'active_record/connection_adapters/schema_cache' -require 'active_record/connection_adapters/abstract/schema_dumper' +require 'active_record/connection_adapters/abstract/schema_dumper' require 'monitor' require 'active_support/deprecation' @@ -263,7 +263,8 @@ module ActiveRecord end def transaction_joinable=(joinable) - ActiveSupport::Deprecation.warn "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead." + message = "#transaction_joinable= is deprecated. Please pass the :joinable option to #begin_transaction instead." + ActiveSupport::Deprecation.warn message @transaction.joinable = joinable end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 7da77af3a9..84e73e6f0f 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -498,6 +498,13 @@ module ActiveRecord # Maps logical Rails types to MySQL-specific data types. def type_to_sql(type, limit = nil, precision = nil, scale = nil) case type.to_s + when 'binary' + case limit + when 0..0xfff; "varbinary(#{limit})" + when nil; "blob" + when 0x1000..0xffffffff; "blob(#{limit})" + else raise(ActiveRecordError, "No binary type has character length #{limit}") + end when 'integer' case limit when 1; 'tinyint' diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index 816b5e17c1..80984f39c9 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -94,7 +94,7 @@ module ActiveRecord case type when :string, :text then value - when :integer then value.to_i + when :integer then klass.value_to_integer(value) when :float then value.to_f when :decimal then klass.value_to_decimal(value) when :datetime, :timestamp then klass.string_to_time(value) @@ -107,14 +107,15 @@ module ActiveRecord end def type_cast_code(var_name) - ActiveSupport::Deprecation.warn("Column#type_cast_code is deprecated in favor of" \ - "using Column#type_cast only, and it is going to be removed in future Rails versions.") + message = "Column#type_cast_code is deprecated in favor of using Column#type_cast only, " \ + "and it is going to be removed in future Rails versions." + ActiveSupport::Deprecation.warn message klass = self.class.name case type when :string, :text then var_name - when :integer then "(#{var_name}.to_i)" + when :integer then "#{klass}.value_to_integer(#{var_name})" when :float then "#{var_name}.to_f" when :decimal then "#{klass}.value_to_decimal(#{var_name})" when :datetime, :timestamp then "#{klass}.string_to_time(#{var_name})" @@ -197,6 +198,17 @@ module ActiveRecord end end + # Used to convert values to integer. + # handle the case when an integer column is used to store boolean values + def value_to_integer(value) + case value + when TrueClass, FalseClass + value ? 1 : 0 + else + value.to_i + end + end + # convert something to a BigDecimal def value_to_decimal(value) # Using .class is faster than .is_a? and diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index b9a61f7d91..09250d3c01 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -73,6 +73,8 @@ module ActiveRecord :database => config.path.sub(%r{^/},""), :host => config.host } spec.reject!{ |_,value| value.blank? } + uri_parser = URI::Parser.new + spec.map { |key,value| spec[key] = uri_parser.unescape(value) if value.is_a?(String) } if config.query options = Hash[config.query.split("&").map{ |pair| pair.split("=") }].symbolize_keys spec.merge!(options) diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb index 553985bd1e..34d7a246b2 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb @@ -221,10 +221,9 @@ module ActiveRecord end def outside_transaction? - ActiveSupport::Deprecation.warn( - "#outside_transaction? is deprecated. This method was only really used " \ - "internally, but you can use #transaction_open? instead." - ) + message = "#outside_transaction? is deprecated. This method was only really used " \ + "internally, but you can use #transaction_open? instead." + ActiveSupport::Deprecation.warn message @connection.transaction_status == PGconn::PQTRANS_IDLE end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index 4d5cb72c67..b89e9a01a8 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -251,7 +251,7 @@ module ActiveRecord value = super if column.type == :string && value.encoding == Encoding::ASCII_8BIT logger.error "Binary data inserted for `string` type on column `#{column.name}`" if logger - value.encode! 'utf-8' + value = value.encode Encoding::UTF_8 end value end @@ -519,24 +519,22 @@ module ActiveRecord def copy_table(from, to, options = {}) #:nodoc: from_primary_key = primary_key(from) - options[:primary_key] = from_primary_key if from_primary_key != 'id' - unless options[:primary_key] - options[:id] = columns(from).detect{|c| c.name == 'id'}.present? && from_primary_key == 'id' - end + options[:id] = false create_table(to, options) do |definition| @definition = definition + @definition.primary_key(from_primary_key) if from_primary_key.present? columns(from).each do |column| column_name = options[:rename] ? (options[:rename][column.name] || options[:rename][column.name.to_sym] || column.name) : column.name + next if column_name == from_primary_key @definition.column(column_name, column.type, :limit => column.limit, :default => column.default, :precision => column.precision, :scale => column.scale, :null => column.null) end - @definition.primary_key(from_primary_key) if from_primary_key yield @definition if block_given? end diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index 3531be05bf..8ce7a7a463 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -1,4 +1,3 @@ - module ActiveRecord module ConnectionHandling # Establishes the connection to the database. Accepts a hash as input where diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb index f97c363871..98032db2ef 100644 --- a/activerecord/lib/active_record/core.rb +++ b/activerecord/lib/active_record/core.rb @@ -4,73 +4,6 @@ require 'thread' module ActiveRecord ActiveSupport.on_load(:active_record_config) do - ## - # :singleton-method: - # - # Accepts a logger conforming to the interface of Log4r which is then - # passed on to any new database connections made and which can be - # retrieved on both a class and instance level by calling +logger+. - mattr_accessor :logger, instance_accessor: false - - ## - # :singleton-method: - # Contains the database configuration - as is typically stored in config/database.yml - - # as a Hash. - # - # For example, the following database.yml... - # - # development: - # adapter: sqlite3 - # database: db/development.sqlite3 - # - # production: - # adapter: sqlite3 - # database: db/production.sqlite3 - # - # ...would result in ActiveRecord::Base.configurations to look like this: - # - # { - # 'development' => { - # 'adapter' => 'sqlite3', - # 'database' => 'db/development.sqlite3' - # }, - # 'production' => { - # 'adapter' => 'sqlite3', - # 'database' => 'db/production.sqlite3' - # } - # } - mattr_accessor :configurations, instance_accessor: false - self.configurations = {} - - ## - # :singleton-method: - # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling - # dates and times from the database. This is set to :utc by default. - mattr_accessor :default_timezone, instance_accessor: false - self.default_timezone = :utc - - ## - # :singleton-method: - # Specifies the format to use when dumping the database schema with Rails' - # Rakefile. If :sql, the schema is dumped as (potentially database- - # specific) SQL statements. If :ruby, the schema is dumped as an - # ActiveRecord::Schema file which can be loaded into any database that - # supports migrations. Use :ruby if you want to have different database - # adapters for, e.g., your development and test environments. - mattr_accessor :schema_format, instance_accessor: false - self.schema_format = :ruby - - ## - # :singleton-method: - # Specify whether or not to use timestamps for migration versions - mattr_accessor :timestamped_migrations, instance_accessor: false - self.timestamped_migrations = true - - mattr_accessor :connection_handler, instance_accessor: false - self.connection_handler = ConnectionAdapters::ConnectionHandler.new - - mattr_accessor :dependent_restrict_raises, instance_accessor: false - self.dependent_restrict_raises = true end module Core @@ -79,12 +12,68 @@ module ActiveRecord included do ## # :singleton-method: - # The connection handler - config_attribute :connection_handler + # + # Accepts a logger conforming to the interface of Log4r which is then + # passed on to any new database connections made and which can be + # retrieved on both a class and instance level by calling +logger+. + mattr_accessor :logger, instance_writer: false + + ## + # :singleton-method: + # Contains the database configuration - as is typically stored in config/database.yml - + # as a Hash. + # + # For example, the following database.yml... + # + # development: + # adapter: sqlite3 + # database: db/development.sqlite3 + # + # production: + # adapter: sqlite3 + # database: db/production.sqlite3 + # + # ...would result in ActiveRecord::Base.configurations to look like this: + # + # { + # 'development' => { + # 'adapter' => 'sqlite3', + # 'database' => 'db/development.sqlite3' + # }, + # 'production' => { + # 'adapter' => 'sqlite3', + # 'database' => 'db/production.sqlite3' + # } + # } + mattr_accessor :configurations, instance_writer: false + self.configurations = {} - %w(logger configurations default_timezone schema_format timestamped_migrations).each do |name| - config_attribute name, global: true - end + ## + # :singleton-method: + # Determines whether to use Time.utc (using :utc) or Time.local (using :local) when pulling + # dates and times from the database. This is set to :utc by default. + mattr_accessor :default_timezone, instance_writer: false + self.default_timezone = :utc + + ## + # :singleton-method: + # Specifies the format to use when dumping the database schema with Rails' + # Rakefile. If :sql, the schema is dumped as (potentially database- + # specific) SQL statements. If :ruby, the schema is dumped as an + # ActiveRecord::Schema file which can be loaded into any database that + # supports migrations. Use :ruby if you want to have different database + # adapters for, e.g., your development and test environments. + mattr_accessor :schema_format, instance_writer: false + self.schema_format = :ruby + + ## + # :singleton-method: + # Specify whether or not to use timestamps for migration versions + mattr_accessor :timestamped_migrations, instance_writer: false + self.timestamped_migrations = true + + class_attribute :connection_handler, instance_writer: false + self.connection_handler = ConnectionAdapters::ConnectionHandler.new end module ClassMethods @@ -139,7 +128,13 @@ module ActiveRecord # Returns the Arel engine. def arel_engine - @arel_engine ||= connection_handler.retrieve_connection_pool(self) ? self : active_record_super.arel_engine + @arel_engine ||= begin + if Base == self || connection_handler.retrieve_connection_pool(self) + self + else + superclass.arel_engine + end + end end private diff --git a/activerecord/lib/active_record/explain.rb b/activerecord/lib/active_record/explain.rb index 9e0390bed1..af772996f1 100644 --- a/activerecord/lib/active_record/explain.rb +++ b/activerecord/lib/active_record/explain.rb @@ -1,12 +1,10 @@ require 'active_support/lazy_load_hooks' module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false - end - module Explain - delegate :auto_explain_threshold_in_seconds, :auto_explain_threshold_in_seconds=, to: 'ActiveRecord::Model' + def self.extended(base) + base.mattr_accessor :auto_explain_threshold_in_seconds, instance_accessor: false + end # If auto explain is enabled, this method triggers EXPLAIN logging for the # queries triggered by the block if it takes more than the threshold as a diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index 7f1d62af39..29a99a5336 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -553,7 +553,7 @@ module ActiveRecord rows[table_name] = fixtures.map do |label, fixture| row = fixture.to_hash - if model_class && model_class < ActiveRecord::Model + if model_class && model_class < ActiveRecord::Base # fill in timestamp columns if they aren't specified and the model is set to record_timestamps if model_class.record_timestamps timestamp_column_names.each do |c_name| diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 35273b0d81..a448fa1f5c 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -1,29 +1,22 @@ - module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - # Determine whether to store the full constant name including namespace when using STI - mattr_accessor :store_full_sti_class, instance_accessor: false - self.store_full_sti_class = true - end - module Inheritance extend ActiveSupport::Concern included do - config_attribute :store_full_sti_class + # Determine whether to store the full constant name including namespace when using STI + class_attribute :store_full_sti_class, instance_writer: false + self.store_full_sti_class = true end module ClassMethods # True if this isn't a concrete subclass needing a STI type condition. def descends_from_active_record? - sup = active_record_super - - if sup.abstract_class? - sup.descends_from_active_record? - elsif self == Base + if self == Base false + elsif superclass.abstract_class? + superclass.descends_from_active_record? else - [Base, Model].include?(sup) || !columns_hash.include?(inheritance_column) + superclass == Base || !columns_hash.include?(inheritance_column) end end @@ -40,9 +33,8 @@ module ActiveRecord @symbolized_sti_name ||= sti_name.present? ? sti_name.to_sym : symbolized_base_class end - # Returns the class descending directly from ActiveRecord::Base (or - # that includes ActiveRecord::Model), or an abstract class, if any, in - # the inheritance hierarchy. + # Returns the class descending directly from ActiveRecord::Base, or + # an abstract class, if any, in the inheritance hierarchy. # # If A extends AR::Base, A.base_class will return A. If B descends from A # through some arbitrarily deep hierarchy, B.base_class will return A. @@ -50,15 +42,14 @@ module ActiveRecord # If B < A and C < B and if A is an abstract_class then both B.base_class # and C.base_class would return B as the answer since A is an abstract_class. def base_class - unless self < ActiveRecord::Tag + unless self < Base raise ActiveRecordError, "#{name} doesn't belong in a hierarchy descending from ActiveRecord" end - sup = active_record_super - if sup == Base || sup == Model || sup.abstract_class? + if superclass == Base || superclass.abstract_class? self else - sup.base_class + superclass.base_class end end @@ -97,14 +88,6 @@ module ActiveRecord sti_class.allocate.init_with('attributes' => record, 'column_types' => column_types) end - # For internal use. - # - # If this class includes ActiveRecord::Model then it won't have a - # superclass. So this provides a way to get to the 'root' (ActiveRecord::Model). - def active_record_super #:nodoc: - superclass < Model ? superclass : Model - end - protected # Returns the class type of the record using the current module as a prefix. So descendants of diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index e96ed00f9c..035c77c424 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -1,9 +1,4 @@ module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :lock_optimistically, instance_accessor: false - self.lock_optimistically = true - end - module Locking # == What is Optimistic Locking # @@ -56,7 +51,8 @@ module ActiveRecord extend ActiveSupport::Concern included do - config_attribute :lock_optimistically + class_attribute :lock_optimistically, instance_writer: false + self.lock_optimistically = true end def locking_enabled? #:nodoc: diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb index d5ee98382d..5499f37802 100644 --- a/activerecord/lib/active_record/migration.rb +++ b/activerecord/lib/active_record/migration.rb @@ -342,7 +342,9 @@ module ActiveRecord end def call(env) - ActiveRecord::Migration.check_pending! + ActiveRecord::Base.logger.quietly do + ActiveRecord::Migration.check_pending! + end @app.call(env) end end @@ -730,9 +732,8 @@ module ActiveRecord running = runnable if block_given? - ActiveSupport::Deprecation.warn(<<-eomsg) -block argument to migrate is deprecated, please filter migrations before constructing the migrator - eomsg + message = "block argument to migrate is deprecated, please filter migrations before constructing the migrator" + ActiveSupport::Deprecation.warn message running.select! { |m| yield m } end diff --git a/activerecord/lib/active_record/model.rb b/activerecord/lib/active_record/model.rb deleted file mode 100644 index f059840f4d..0000000000 --- a/activerecord/lib/active_record/model.rb +++ /dev/null @@ -1,167 +0,0 @@ -require 'active_support/core_ext/module/attribute_accessors' - -module ActiveRecord - module Configuration # :nodoc: - # This just abstracts out how we define configuration options in AR. Essentially we - # have mattr_accessors on the ActiveRecord:Model constant that define global defaults. - # Classes that then use AR get class_attributes defined, which means that when they - # are assigned the default will be overridden for that class and subclasses. (Except - # when options[:global] == true, in which case there is one global value always.) - def config_attribute(name, options = {}) - if options[:global] - class_eval <<-CODE, __FILE__, __LINE__ + 1 - def self.#{name}; ActiveRecord::Model.#{name}; end - def #{name}; ActiveRecord::Model.#{name}; end - def self.#{name}=(val); ActiveRecord::Model.#{name} = val; end - CODE - else - options[:instance_writer] ||= false - class_attribute name, options - - singleton_class.class_eval <<-CODE, __FILE__, __LINE__ + 1 - remove_method :#{name} - def #{name}; ActiveRecord::Model.#{name}; end - CODE - end - end - end - - # This allows us to detect an ActiveRecord::Model while it's in the process of - # being included. - module Tag; end - - # <tt>ActiveRecord::Model</tt> can be included into a class to add Active Record - # persistence. This is an alternative to inheriting from <tt>ActiveRecord::Base</tt>. - # - # class Post - # include ActiveRecord::Model - # end - module Model - extend ActiveSupport::Concern - extend ConnectionHandling - extend ActiveModel::Observing::ClassMethods - - def self.append_features(base) - base.class_eval do - include Tag - extend Configuration - end - - super - end - - included do - extend ActiveModel::Naming - extend ActiveSupport::Benchmarkable - extend ActiveSupport::DescendantsTracker - - extend QueryCache::ClassMethods - extend Querying - extend Translation - extend DynamicMatchers - extend Explain - extend ConnectionHandling - - initialize_generated_modules unless self == Base - end - - include Persistence - include ReadonlyAttributes - include ModelSchema - include Inheritance - include Scoping - include Sanitization - include AttributeAssignment - include ActiveModel::Conversion - include Integration - include Validations - include CounterCache - include Locking::Optimistic - include Locking::Pessimistic - include AttributeMethods - include Callbacks - include ActiveModel::Observing - include Timestamp - include Associations - include ActiveModel::SecurePassword - include AutosaveAssociation - include NestedAttributes - include Aggregations - include Transactions - include Reflection - include Serialization - include Store - include Core - - class << self - def arel_engine - self - end - - def abstract_class? - false - end - - # Defines the name of the table column which will store the class name on single-table - # inheritance situations. - # - # The default inheritance column name is +type+, which means it's a - # reserved word inside Active Record. To be able to use single-table - # inheritance with another column name, or to use the column +type+ in - # your own model for something else, you can set +inheritance_column+: - # - # self.inheritance_column = 'zoink' - def inheritance_column - 'type' - end - end - - class DeprecationProxy < BasicObject #:nodoc: - def initialize(model = Model, base = Base) - @model = model - @base = base - end - - def method_missing(name, *args, &block) - if @model.respond_to?(name, true) - @model.send(name, *args, &block) - else - ::ActiveSupport::Deprecation.warn( - "The object passed to the active_record load hook was previously ActiveRecord::Base " \ - "(a Class). Now it is ActiveRecord::Model (a Module). You have called `#{name}' which " \ - "is only defined on ActiveRecord::Base. Please change your code so that it works with " \ - "a module rather than a class. (Model is included in Base, so anything added to Model " \ - "will be available on Base as well.)" - ) - @base.send(name, *args, &block) - end - end - - alias send method_missing - - def extend(*mods) - ::ActiveSupport::Deprecation.warn( - "The object passed to the active_record load hook was previously ActiveRecord::Base " \ - "(a Class). Now it is ActiveRecord::Model (a Module). You have called `extend' which " \ - "would add singleton methods to Model. This is presumably not what you want, since the " \ - "methods would not be inherited down to Base. Rather than using extend, please use " \ - "ActiveSupport::Concern + include, which will ensure that your class methods are " \ - "inherited." - ) - @base.extend(*mods) - end - end - end - - # This hook is where config accessors on Model get defined. - # - # We don't want to just open the Model module and add stuff to it in other files, because - # that would cause Model to load, which causes all sorts of loading order issues. - # - # We need this hook rather than just using the :active_record one, because users of the - # :active_record hook may need to use config options. - ActiveSupport.run_load_hooks(:active_record_config, Model) - - # Load Base at this point, because the active_record load hook is run in that file. - Base -end diff --git a/activerecord/lib/active_record/model_schema.rb b/activerecord/lib/active_record/model_schema.rb index 99de16cd33..1b95b72c8a 100644 --- a/activerecord/lib/active_record/model_schema.rb +++ b/activerecord/lib/active_record/model_schema.rb @@ -1,18 +1,4 @@ - module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :primary_key_prefix_type, instance_accessor: false - - mattr_accessor :table_name_prefix, instance_accessor: false - self.table_name_prefix = "" - - mattr_accessor :table_name_suffix, instance_accessor: false - self.table_name_suffix = "" - - mattr_accessor :pluralize_table_names, instance_accessor: false - self.pluralize_table_names = true - end - module ModelSchema extend ActiveSupport::Concern @@ -24,7 +10,7 @@ module ActiveRecord # the Product class will look for "productid" instead of "id" as the primary column. If the # latter is specified, the Product class will look for "product_id" instead of "id". Remember # that this is a global setting for all Active Records. - config_attribute :primary_key_prefix_type, global: true + mattr_accessor :primary_key_prefix_type, instance_writer: false ## # :singleton-method: @@ -36,20 +22,25 @@ module ActiveRecord # If you are organising your models within modules you can add a prefix to the models within # a namespace by defining a singleton method in the parent module called table_name_prefix which # returns your chosen prefix. - config_attribute :table_name_prefix + class_attribute :table_name_prefix, instance_writer: false + self.table_name_prefix = "" ## # :singleton-method: # Works like +table_name_prefix+, but appends instead of prepends (set to "_basecamp" gives "projects_basecamp", # "people_basecamp"). By default, the suffix is the empty string. - config_attribute :table_name_suffix + class_attribute :table_name_suffix, instance_writer: false + self.table_name_suffix = "" ## # :singleton-method: # Indicates whether table names should be the pluralized versions of the corresponding class names. # If true, the default table name for a Product class will be +products+. If false, it would just be +product+. # See table_name for the full rules on table/class naming. This is true, by default. - config_attribute :pluralize_table_names + class_attribute :pluralize_table_names, instance_writer: false + self.pluralize_table_names = true + + self.inheritance_column = 'type' end module ClassMethods @@ -144,9 +135,9 @@ module ActiveRecord # Computes the table name, (re)sets it internally, and returns it. def reset_table_name #:nodoc: self.table_name = if abstract_class? - active_record_super == Base ? nil : active_record_super.table_name - elsif active_record_super.abstract_class? - active_record_super.table_name || compute_table_name + superclass == Base ? nil : superclass.table_name + elsif superclass.abstract_class? + superclass.table_name || compute_table_name else compute_table_name end @@ -156,9 +147,17 @@ module ActiveRecord (parents.detect{ |p| p.respond_to?(:table_name_prefix) } || self).table_name_prefix end - # The name of the column containing the object's class when Single Table Inheritance is used + # Defines the name of the table column which will store the class name on single-table + # inheritance situations. + # + # The default inheritance column name is +type+, which means it's a + # reserved word inside Active Record. To be able to use single-table + # inheritance with another column name, or to use the column +type+ in + # your own model for something else, you can set +inheritance_column+: + # + # self.inheritance_column = 'zoink' def inheritance_column - (@inheritance_column ||= nil) || active_record_super.inheritance_column + (@inheritance_column ||= nil) || superclass.inheritance_column end # Sets the value of inheritance_column @@ -331,7 +330,7 @@ module ActiveRecord base = base_class if self == base # Nested classes are prefixed with singular parent table name. - if parent < ActiveRecord::Model && !parent.abstract_class? + if parent < Base && !parent.abstract_class? contained = parent.table_name contained = contained.singularize if parent.pluralize_table_names contained += '_' diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 43f908ae5f..aba56c2861 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -3,11 +3,6 @@ require 'active_support/core_ext/object/try' require 'active_support/core_ext/hash/indifferent_access' module ActiveRecord - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :nested_attributes_options, instance_accessor: false - self.nested_attributes_options = {} - end - module NestedAttributes #:nodoc: class TooManyRecords < ActiveRecordError end @@ -15,7 +10,8 @@ module ActiveRecord extend ActiveSupport::Concern included do - config_attribute :nested_attributes_options + class_attribute :nested_attributes_options, instance_writer: false + self.nested_attributes_options = {} end # = Active Record Nested Attributes diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 65a31f1566..8e749772a1 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -224,11 +224,13 @@ module ActiveRecord verify_readonly_attribute(key.to_s) end + updated_count = self.class.where(self.class.primary_key => id).update_all(attributes) + attributes.each do |k,v| raw_write_attribute(k,v) end - self.class.where(self.class.primary_key => id).update_all(attributes) == 1 + updated_count == 1 end # Initializes +attribute+ to zero if +nil+ and adds the value passed as +by+ (default is 1). diff --git a/activerecord/lib/active_record/query_cache.rb b/activerecord/lib/active_record/query_cache.rb index 2bd8ecda20..38e18b32a4 100644 --- a/activerecord/lib/active_record/query_cache.rb +++ b/activerecord/lib/active_record/query_cache.rb @@ -5,19 +5,19 @@ module ActiveRecord module ClassMethods # Enable the query cache within the block if Active Record is configured. def cache(&block) - if ActiveRecord::Base.configurations.blank? - yield - else + if ActiveRecord::Base.connected? connection.cache(&block) + else + yield end end # Disable the query cache within the block if Active Record is configured. def uncached(&block) - if ActiveRecord::Base.configurations.blank? - yield - else + if ActiveRecord::Base.connected? connection.uncached(&block) + else + yield end end end diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index d7e35fb771..77e41ea927 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -80,7 +80,7 @@ module ActiveRecord if File.file?(filename) cache = Marshal.load File.binread filename if cache.version == ActiveRecord::Migrator.current_version - ActiveRecord::Model.connection.schema_cache = cache + self.connection.schema_cache = cache else warn "Ignoring db/schema_cache.dump because it has expired. The current schema version is #{ActiveRecord::Migrator.current_version}, but the one in the cache is #{cache.version}." end @@ -122,8 +122,8 @@ module ActiveRecord ActiveSupport.on_load(:active_record) do ActionDispatch::Reloader.send(hook) do - ActiveRecord::Model.clear_reloadable_connections! - ActiveRecord::Model.clear_cache! + ActiveRecord::Base.clear_reloadable_connections! + ActiveRecord::Base.clear_cache! end end end @@ -135,13 +135,12 @@ module ActiveRecord config.after_initialize do |app| ActiveSupport.on_load(:active_record) do - ActiveRecord::Model.instantiate_observers + instantiate_observers ActionDispatch::Reloader.to_prepare do - ActiveRecord::Model.instantiate_observers + ActiveRecord::Base.instantiate_observers end end - end end end diff --git a/activerecord/lib/active_record/readonly_attributes.rb b/activerecord/lib/active_record/readonly_attributes.rb index b3c20c4aff..8499bb16e7 100644 --- a/activerecord/lib/active_record/readonly_attributes.rb +++ b/activerecord/lib/active_record/readonly_attributes.rb @@ -22,7 +22,8 @@ module ActiveRecord end def _attr_readonly - ActiveSupport::Deprecation.warn("Instance level _attr_readonly method is deprecated, please use class level method.") + message = "Instance level _attr_readonly method is deprecated, please use class level method." + ActiveSupport::Deprecation.warn message defined?(@_attr_readonly) ? @_attr_readonly : self.class._attr_readonly end end diff --git a/activerecord/lib/active_record/relation/batches.rb b/activerecord/lib/active_record/relation/batches.rb index 8af0c6a8ef..b921f2eddb 100644 --- a/activerecord/lib/active_record/relation/batches.rb +++ b/activerecord/lib/active_record/relation/batches.rb @@ -62,11 +62,11 @@ module ActiveRecord ActiveRecord::Base.logger.warn("Scoped order and limit are ignored, it's forced to be batch order and batch size") end - start = options.delete(:start) || 0 + start = options.delete(:start) batch_size = options.delete(:batch_size) || 1000 relation = relation.reorder(batch_order).limit(batch_size) - records = relation.where(table[primary_key].gteq(start)).to_a + records = start ? relation.where(table[primary_key].gteq(start)).to_a : relation.to_a while records.any? records_size = records.size diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 84aaa39fed..99c2f45bc8 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -159,7 +159,7 @@ module ActiveRecord # Person.exists?(false) # Person.exists? def exists?(conditions = :none) - conditions = conditions.id if ActiveRecord::Model === conditions + conditions = conditions.id if Base === conditions return false if !conditions join_dependency = construct_join_dependency_for_association_find diff --git a/activerecord/lib/active_record/relation/predicate_builder.rb b/activerecord/lib/active_record/relation/predicate_builder.rb index 71030cb5d7..bd7aeb0c4e 100644 --- a/activerecord/lib/active_record/relation/predicate_builder.rb +++ b/activerecord/lib/active_record/relation/predicate_builder.rb @@ -40,7 +40,7 @@ module ActiveRecord # # For polymorphic relationships, find the foreign key and type: # PriceEstimate.where(:estimate_of => treasure) - if klass && value.class < ActiveRecord::Tag && reflection = klass.reflect_on_association(column.to_sym) + if klass && value.class < Base && reflection = klass.reflect_on_association(column.to_sym) if reflection.polymorphic? queries << build(table[reflection.foreign_type], value.class.base_class) end @@ -67,7 +67,7 @@ module ActiveRecord def self.build(attribute, value) case value when Array, ActiveRecord::Associations::CollectionProxy - values = value.to_a.map {|x| x.is_a?(ActiveRecord::Model) ? x.id : x} + values = value.to_a.map {|x| x.is_a?(Base) ? x.id : x} ranges, values = values.partition {|v| v.is_a?(Range)} values_predicate = if values.include?(nil) @@ -93,7 +93,7 @@ module ActiveRecord attribute.in(value.arel.ast) when Range attribute.in(value) - when ActiveRecord::Model + when ActiveRecord::Base attribute.eq(value.id) when Class # FIXME: I think we need to deprecate this behavior diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 14bcb337e9..4fdc296c7e 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -496,6 +496,11 @@ module ActiveRecord extending(NullRelation) end + # Like #none, but modifies relation in place. + def none! + extending!(NullRelation) + end + # Sets readonly attributes for the returned relation. If value is # true (default), attempting to update a record will result in an error. # diff --git a/activerecord/lib/active_record/result.rb b/activerecord/lib/active_record/result.rb index 425b9b41d8..bea195e9b8 100644 --- a/activerecord/lib/active_record/result.rb +++ b/activerecord/lib/active_record/result.rb @@ -56,7 +56,7 @@ module ActiveRecord @hash_rows ||= begin # We freeze the strings to prevent them getting duped when - # used as keys in ActiveRecord::Model's @attributes hash + # used as keys in ActiveRecord::Base's @attributes hash columns = @columns.map { |c| c.dup.freeze } @rows.map { |row| Hash[columns.zip(row)] diff --git a/activerecord/lib/active_record/serialization.rb b/activerecord/lib/active_record/serialization.rb index e8dd312a47..6b55af4205 100644 --- a/activerecord/lib/active_record/serialization.rb +++ b/activerecord/lib/active_record/serialization.rb @@ -1,19 +1,11 @@ module ActiveRecord #:nodoc: - ActiveSupport.on_load(:active_record_config) do - mattr_accessor :include_root_in_json, instance_accessor: false - self.include_root_in_json = true - end - # = Active Record Serialization module Serialization extend ActiveSupport::Concern include ActiveModel::Serializers::JSON included do - singleton_class.class_eval do - remove_method :include_root_in_json - delegate :include_root_in_json, to: 'ActiveRecord::Model' - end + self.include_root_in_json = true end def serializable_hash(options = nil) diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index ec4588f601..920d6848c1 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -1,8 +1,6 @@ module ActiveRecord ActiveSupport.on_load(:active_record_config) do - mattr_accessor :record_timestamps, instance_accessor: false - self.record_timestamps = true end # = Active Record Timestamp @@ -37,7 +35,8 @@ module ActiveRecord extend ActiveSupport::Concern included do - config_attribute :record_timestamps, instance_writer: true + class_attribute :record_timestamps + self.record_timestamps = true end def initialize_dup(other) # :nodoc: diff --git a/activerecord/lib/active_record/transactions.rb b/activerecord/lib/active_record/transactions.rb index 934393b4e7..f91abfbd19 100644 --- a/activerecord/lib/active_record/transactions.rb +++ b/activerecord/lib/active_record/transactions.rb @@ -328,6 +328,7 @@ module ActiveRecord @_start_transaction_state[:new_record] = @new_record @_start_transaction_state[:destroyed] = @destroyed @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) + 1 + @_start_transaction_state[:frozen?] = @attributes.frozen? end # Clear the new record state and id of a record. @@ -342,8 +343,8 @@ module ActiveRecord @_start_transaction_state[:level] = (@_start_transaction_state[:level] || 0) - 1 if @_start_transaction_state[:level] < 1 || force restore_state = @_start_transaction_state - was_frozen = @attributes.frozen? - @attributes = @attributes.dup if was_frozen + was_frozen = restore_state[:frozen?] + @attributes = @attributes.dup if @attributes.frozen? @new_record = restore_state[:new_record] @destroyed = restore_state[:destroyed] if restore_state.has_key?(:id) diff --git a/activerecord/test/cases/adapter_test.rb b/activerecord/test/cases/adapter_test.rb index 93b01a3934..404b492288 100644 --- a/activerecord/test/cases/adapter_test.rb +++ b/activerecord/test/cases/adapter_test.rb @@ -69,16 +69,16 @@ module ActiveRecord def test_not_specifying_database_name_for_cross_database_selects begin assert_nothing_raised do - ActiveRecord::Model.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database)) + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database)) config = ARTest.connection_config - ActiveRecord::Model.connection.execute( + ActiveRecord::Base.connection.execute( "SELECT #{config['arunit']['database']}.pirates.*, #{config['arunit2']['database']}.courses.* " \ "FROM #{config['arunit']['database']}.pirates, #{config['arunit2']['database']}.courses" ) end ensure - ActiveRecord::Model.establish_connection 'arunit' + ActiveRecord::Base.establish_connection 'arunit' end end end diff --git a/activerecord/test/cases/adapters/mysql/connection_test.rb b/activerecord/test/cases/adapters/mysql/connection_test.rb index 4bccd2cc59..534dc2c2df 100644 --- a/activerecord/test/cases/adapters/mysql/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql/connection_test.rb @@ -3,13 +3,13 @@ require "cases/helper" class MysqlConnectionTest < ActiveRecord::TestCase def setup super - @connection = ActiveRecord::Model.connection + @connection = ActiveRecord::Base.connection end def test_mysql_reconnect_attribute_after_connection_with_reconnect_true run_without_connection do |orig_connection| - ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => true})) - assert ActiveRecord::Model.connection.raw_connection.reconnect + ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => true})) + assert ActiveRecord::Base.connection.raw_connection.reconnect end end @@ -25,8 +25,8 @@ class MysqlConnectionTest < ActiveRecord::TestCase def test_mysql_reconnect_attribute_after_connection_with_reconnect_false run_without_connection do |orig_connection| - ActiveRecord::Model.establish_connection(orig_connection.merge({:reconnect => false})) - assert !ActiveRecord::Model.connection.raw_connection.reconnect + ActiveRecord::Base.establish_connection(orig_connection.merge({:reconnect => false})) + assert !ActiveRecord::Base.connection.raw_connection.reconnect end end @@ -117,7 +117,7 @@ class MysqlConnectionTest < ActiveRecord::TestCase # Test that MySQL allows multiple results for stored procedures if defined?(Mysql) && Mysql.const_defined?(:CLIENT_MULTI_RESULTS) def test_multi_results - rows = ActiveRecord::Model.connection.select_rows('CALL ten();') + rows = ActiveRecord::Base.connection.select_rows('CALL ten();') assert_equal 10, rows[0][0].to_i, "ten() did not return 10 as expected: #{rows.inspect}" assert @connection.active?, "Bad connection use by 'MysqlAdapter.select_rows'" end @@ -130,9 +130,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase def test_mysql_strict_mode_disabled_dont_override_global_sql_mode run_without_connection do |orig_connection| - ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false})) - global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode" - session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode" + ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) + global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode" + session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" assert_equal global_sql_mode.rows, session_sql_mode.rows end end @@ -140,11 +140,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase private def run_without_connection - original_connection = ActiveRecord::Model.remove_connection + original_connection = ActiveRecord::Base.remove_connection begin yield original_connection ensure - ActiveRecord::Model.establish_connection(original_connection) + ActiveRecord::Base.establish_connection(original_connection) end end end diff --git a/activerecord/test/cases/adapters/mysql/sql_types_test.rb b/activerecord/test/cases/adapters/mysql/sql_types_test.rb new file mode 100644 index 0000000000..1ddb1b91c9 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/sql_types_test.rb @@ -0,0 +1,14 @@ +require "cases/helper" + +class SqlTypesTest < ActiveRecord::TestCase + def test_binary_types + assert_equal 'varbinary(64)', type_to_sql(:binary, 64) + assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095) + assert_equal 'blob(4096)', type_to_sql(:binary, 4096) + assert_equal 'blob', type_to_sql(:binary) + end + + def type_to_sql(*args) + ActiveRecord::Base.connection.type_to_sql(*args) + end +end diff --git a/activerecord/test/cases/adapters/mysql2/connection_test.rb b/activerecord/test/cases/adapters/mysql2/connection_test.rb index c63e4fe5b6..14c22d2519 100644 --- a/activerecord/test/cases/adapters/mysql2/connection_test.rb +++ b/activerecord/test/cases/adapters/mysql2/connection_test.rb @@ -3,7 +3,7 @@ require "cases/helper" class MysqlConnectionTest < ActiveRecord::TestCase def setup super - @connection = ActiveRecord::Model.connection + @connection = ActiveRecord::Base.connection @connection.extend(LogIntercepter) @connection.intercepted = true end @@ -46,9 +46,9 @@ class MysqlConnectionTest < ActiveRecord::TestCase def test_mysql_strict_mode_disabled_dont_override_global_sql_mode run_without_connection do |orig_connection| - ActiveRecord::Model.establish_connection(orig_connection.merge({:strict => false})) - global_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@GLOBAL.sql_mode" - session_sql_mode = ActiveRecord::Model.connection.exec_query "SELECT @@SESSION.sql_mode" + ActiveRecord::Base.establish_connection(orig_connection.merge({:strict => false})) + global_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@GLOBAL.sql_mode" + session_sql_mode = ActiveRecord::Base.connection.exec_query "SELECT @@SESSION.sql_mode" assert_equal global_sql_mode.rows, session_sql_mode.rows end end @@ -76,11 +76,11 @@ class MysqlConnectionTest < ActiveRecord::TestCase private def run_without_connection - original_connection = ActiveRecord::Model.remove_connection + original_connection = ActiveRecord::Base.remove_connection begin yield original_connection ensure - ActiveRecord::Model.establish_connection(original_connection) + ActiveRecord::Base.establish_connection(original_connection) end end end diff --git a/activerecord/test/cases/adapters/mysql2/sql_types_test.rb b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb new file mode 100644 index 0000000000..1ddb1b91c9 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/sql_types_test.rb @@ -0,0 +1,14 @@ +require "cases/helper" + +class SqlTypesTest < ActiveRecord::TestCase + def test_binary_types + assert_equal 'varbinary(64)', type_to_sql(:binary, 64) + assert_equal 'varbinary(4095)', type_to_sql(:binary, 4095) + assert_equal 'blob(4096)', type_to_sql(:binary, 4096) + assert_equal 'blob', type_to_sql(:binary) + end + + def type_to_sql(*args) + ActiveRecord::Base.connection.type_to_sql(*args) + end +end diff --git a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb index 74288a98d1..d03d1dd94c 100644 --- a/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/copy_table_test.rb @@ -32,6 +32,11 @@ class CopyTableTest < ActiveRecord::TestCase end end + def test_copy_table_allows_to_pass_options_to_create_table + @connection.create_table('blocker_table') + test_copy_table('customers', 'blocker_table', force: true) + end + def test_copy_table_with_index test_copy_table('comments', 'comments_with_index') do @connection.add_index('comments_with_index', ['post_id', 'type']) @@ -43,7 +48,9 @@ class CopyTableTest < ActiveRecord::TestCase end def test_copy_table_without_primary_key - test_copy_table('developers_projects', 'programmers_projects') + test_copy_table('developers_projects', 'programmers_projects') do + assert_nil @connection.primary_key('programmers_projects') + end end def test_copy_table_with_id_col_that_is_not_primary_key diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 4e26c5dda1..003052bac4 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -154,6 +154,12 @@ module ActiveRecord DualEncoding.connection.drop_table('dual_encodings') end + def test_type_cast_should_not_mutate_encoding + name = 'hello'.force_encoding(Encoding::ASCII_8BIT) + Owner.create(name: name) + assert_equal Encoding::ASCII_8BIT, name.encoding + end + def test_execute @conn.execute "INSERT INTO items (number) VALUES (10)" records = @conn.execute "SELECT * FROM items" diff --git a/activerecord/test/cases/associations/inverse_associations_test.rb b/activerecord/test/cases/associations/inverse_associations_test.rb index aad48e7ce9..8c9b4fb921 100644 --- a/activerecord/test/cases/associations/inverse_associations_test.rb +++ b/activerecord/test/cases/associations/inverse_associations_test.rb @@ -261,10 +261,23 @@ class InverseHasManyTests < ActiveRecord::TestCase def test_parent_instance_should_be_shared_with_first_and_last_child man = Man.first + assert man.interests.first.man.equal? man assert man.interests.last.man.equal? man end + def test_parent_instance_should_be_shared_with_first_n_and_last_n_children + man = Man.first + + interests = man.interests.first(2) + assert interests[0].man.equal? man + assert interests[1].man.equal? man + + interests = man.interests.last(2) + assert interests[0].man.equal? man + assert interests[1].man.equal? man + end + def test_trying_to_use_inverses_that_dont_exist_should_raise_an_error assert_raise(ActiveRecord::InverseOfAssociationNotFoundError) { Man.first.secret_interests } end diff --git a/activerecord/test/cases/attribute_methods/read_test.rb b/activerecord/test/cases/attribute_methods/read_test.rb index da5d9d8c2a..8d8ff2f952 100644 --- a/activerecord/test/cases/attribute_methods/read_test.rb +++ b/activerecord/test/cases/attribute_methods/read_test.rb @@ -11,10 +11,8 @@ module ActiveRecord def setup @klass = Class.new do def self.superclass; Base; end - def self.active_record_super; Base; end def self.base_class; self; end - extend ActiveRecord::Configuration include ActiveRecord::AttributeMethods def self.define_attribute_methods diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index c2b58fd7d1..8b82b79219 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -287,6 +287,12 @@ class AttributeMethodsTest < ActiveRecord::TestCase assert_equal "Don't change the topic", topic[:title] end + def test_read_attribute_raises_missing_attribute_error_when_not_exists + computer = Computer.select('id').first + assert_raises(ActiveModel::MissingAttributeError) { computer[:developer] } + assert_raises(ActiveModel::MissingAttributeError) { computer[:extendedWarranty] } + end + def test_read_attribute_when_false topic = topics(:first) topic.approved = false diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 0f859bf452..203e44857a 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -23,7 +23,6 @@ require 'models/edge' require 'models/joke' require 'models/bulb' require 'models/bird' -require 'models/teapot' require 'rexml/document' require 'active_support/core_ext/exception' @@ -1196,10 +1195,6 @@ class BasicsTest < ActiveRecord::TestCase # Concrete subclasses an abstract class which has a type column. assert !SubStiPost.descends_from_active_record? - - assert Teapot.descends_from_active_record? - assert !OtherTeapot.descends_from_active_record? - assert CoolTeapot.descends_from_active_record? end def test_find_on_abstract_base_class_doesnt_use_type_condition @@ -1453,15 +1448,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal scope, Bird.uniq end - def test_active_record_super - assert_equal ActiveRecord::Model, ActiveRecord::Base.active_record_super - assert_equal ActiveRecord::Base, Topic.active_record_super - assert_equal Topic, ImportantTopic.active_record_super - assert_equal ActiveRecord::Model, Teapot.active_record_super - assert_equal Teapot, OtherTeapot.active_record_super - assert_equal ActiveRecord::Model, CoolTeapot.active_record_super - end - def test_table_name_with_2_abstract_subclasses assert_equal "photos", Photo.table_name end diff --git a/activerecord/test/cases/batches_test.rb b/activerecord/test/cases/batches_test.rb index 12d5245fbd..acb8b5f562 100644 --- a/activerecord/test/cases/batches_test.rb +++ b/activerecord/test/cases/batches_test.rb @@ -136,4 +136,12 @@ class EachTest < ActiveRecord::TestCase assert_equal nick_order_subscribers[1..-1].map(&:id), subscribers.map(&:id) end + + def test_find_in_batches_should_use_any_column_as_primary_key_when_start_is_not_specified + assert_queries(Subscriber.count + 1) do + Subscriber.find_each(:batch_size => 1) do |subscriber| + assert_kind_of Subscriber, subscriber + end + end + end end diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb index a7b63d15c9..2124c256fa 100644 --- a/activerecord/test/cases/column_test.rb +++ b/activerecord/test/cases/column_test.rb @@ -33,6 +33,8 @@ module ActiveRecord assert_equal 0, column.type_cast('bad1') assert_equal 0, column.type_cast('bad') assert_equal 1, column.type_cast(1.7) + assert_equal 0, column.type_cast(false) + assert_equal 1, column.type_cast(true) assert_nil column.type_cast(nil) end @@ -41,11 +43,9 @@ module ActiveRecord assert_raises(NoMethodError) do column.type_cast([]) end + assert_raises(NoMethodError) do - column.type_cast(true) - end - assert_raises(NoMethodError) do - column.type_cast(false) + column.type_cast(Object.new) end end diff --git a/activerecord/test/cases/connection_adapters/connection_handler_test.rb b/activerecord/test/cases/connection_adapters/connection_handler_test.rb index 4467ddfc39..631bf1aaac 100644 --- a/activerecord/test/cases/connection_adapters/connection_handler_test.rb +++ b/activerecord/test/cases/connection_adapters/connection_handler_test.rb @@ -4,8 +4,8 @@ module ActiveRecord module ConnectionAdapters class ConnectionHandlerTest < ActiveRecord::TestCase def setup - @klass = Class.new { include ActiveRecord::Tag } - @subklass = Class.new(@klass) { include ActiveRecord::Tag } + @klass = Class.new(Base) + @subklass = Class.new(@klass) @handler = ConnectionHandler.new @handler.establish_connection @klass, Base.connection_pool.spec diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index 434d2b7ba5..ee9818678d 100644 --- a/activerecord/test/cases/connection_specification/resolver_test.rb +++ b/activerecord/test/cases/connection_specification/resolver_test.rb @@ -9,7 +9,7 @@ module ActiveRecord end def test_url_host_no_db - skip "only if mysql is available" unless defined?(MysqlAdapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) spec = resolve 'mysql://foo?encoding=utf8' assert_equal({ :adapter => "mysql", @@ -18,7 +18,7 @@ module ActiveRecord end def test_url_host_db - skip "only if mysql is available" unless defined?(MysqlAdapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) spec = resolve 'mysql://foo/bar?encoding=utf8' assert_equal({ :adapter => "mysql", @@ -28,7 +28,7 @@ module ActiveRecord end def test_url_port - skip "only if mysql is available" unless defined?(MysqlAdapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) spec = resolve 'mysql://foo:123?encoding=utf8' assert_equal({ :adapter => "mysql", @@ -36,6 +36,14 @@ module ActiveRecord :host => "foo", :encoding => "utf8" }, spec) end + + def test_encoded_password + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + password = 'am@z1ng_p@ssw0rd#!' + encoded_password = URI.encode_www_form_component(password) + spec = resolve "mysql://foo:#{encoded_password}@localhost/bar" + assert_equal password, spec[:password] + end end end end diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index 0df872ff10..ed7eedaa27 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -52,12 +52,12 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) self.use_transactional_fixtures = false def using_strict(strict) - connection = ActiveRecord::Model.remove_connection - ActiveRecord::Model.establish_connection connection.merge(strict: strict) + connection = ActiveRecord::Base.remove_connection + ActiveRecord::Base.establish_connection connection.merge(strict: strict) yield ensure - ActiveRecord::Model.remove_connection - ActiveRecord::Model.establish_connection connection + ActiveRecord::Base.remove_connection + ActiveRecord::Base.establish_connection connection end # MySQL cannot have defaults on text/blob columns. It reports the diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb deleted file mode 100644 index 8f095e4953..0000000000 --- a/activerecord/test/cases/inclusion_test.rb +++ /dev/null @@ -1,133 +0,0 @@ -require 'cases/helper' -require 'models/teapot' - -class BasicInclusionModelTest < ActiveRecord::TestCase - def test_basic_model - Teapot.create!(:name => "Ronnie Kemper") - assert_equal "Ronnie Kemper", Teapot.first.name - end - - def test_initialization - t = Teapot.new(:name => "Bob") - assert_equal "Bob", t.name - end - - def test_inherited_model - teapot = CoolTeapot.create!(:name => "Bob") - teapot.reload - - assert_equal "Bob", teapot.name - assert_equal "mmm", teapot.aaahhh - end - - def test_generated_feature_methods - assert Teapot < Teapot::GeneratedFeatureMethods - end - - def test_exists - t = Teapot.create!(:name => "Ronnie Kemper") - assert Teapot.exists?(t) - end - - def test_predicate_builder - t = Teapot.create!(:name => "Bob") - assert_equal "Bob", Teapot.where(:id => [t]).first.name - assert_equal "Bob", Teapot.where(:id => t).first.name - end - - def test_nested_model - assert_equal "ceiling_teapots", Ceiling::Teapot.table_name - end -end - -class InclusionUnitTest < ActiveRecord::TestCase - def setup - @klass = Class.new { include ActiveRecord::Model } - end - - def test_non_abstract_class - assert !@klass.abstract_class? - end - - def test_abstract_class - @klass.abstract_class = true - assert @klass.abstract_class? - end - - def test_establish_connection - assert @klass.respond_to?(:establish_connection) - assert ActiveRecord::Model.respond_to?(:establish_connection) - end - - def test_adapter_connection - name = "#{ActiveRecord::Base.connection_config[:adapter]}_connection" - assert @klass.respond_to?(name) - assert ActiveRecord::Model.respond_to?(name) - end - - def test_connection_handler - assert_equal ActiveRecord::Base.connection_handler, @klass.connection_handler - end - - def test_mirrored_configuration - ActiveRecord::Base.time_zone_aware_attributes = true - assert @klass.time_zone_aware_attributes - ActiveRecord::Base.time_zone_aware_attributes = false - assert !@klass.time_zone_aware_attributes - ensure - ActiveRecord::Base.time_zone_aware_attributes = false - end - - # Doesn't really test anything, but this is here to ensure warnings don't occur - def test_included_twice - @klass.send :include, ActiveRecord::Model - end - - def test_deprecation_proxy - proxy = ActiveRecord::Model::DeprecationProxy.new - - assert_equal ActiveRecord::Model.name, proxy.name - assert_equal ActiveRecord::Base.superclass, assert_deprecated { proxy.superclass } - - sup, sup2 = nil, nil - ActiveSupport.on_load(:__test_active_record_model_deprecation) do - sup = superclass - sup2 = send(:superclass) - end - assert_deprecated do - ActiveSupport.run_load_hooks(:__test_active_record_model_deprecation, proxy) - end - assert_equal ActiveRecord::Base.superclass, sup - assert_equal ActiveRecord::Base.superclass, sup2 - end - - test "including in deprecation proxy" do - model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup - proxy = ActiveRecord::Model::DeprecationProxy.new(model, base) - - mod = Module.new - proxy.include mod - assert model < mod - end - - test "extending in deprecation proxy" do - model, base = ActiveRecord::Model.dup, ActiveRecord::Base.dup - proxy = ActiveRecord::Model::DeprecationProxy.new(model, base) - - mod = Module.new - assert_deprecated { proxy.extend mod } - assert base.singleton_class < mod - end -end - -class InclusionFixturesTest < ActiveRecord::TestCase - fixtures :teapots - - def test_fixtured_record - assert_equal "Bob", teapots(:bob).name - end - - def test_timestamped_fixture - assert_not_nil teapots(:bob).created_at - end -end diff --git a/activerecord/test/cases/inheritance_test.rb b/activerecord/test/cases/inheritance_test.rb index 8fded9159f..aab7aa51dd 100644 --- a/activerecord/test/cases/inheritance_test.rb +++ b/activerecord/test/cases/inheritance_test.rb @@ -4,7 +4,6 @@ require 'models/person' require 'models/post' require 'models/project' require 'models/subscriber' -require 'models/teapot' require 'models/vegetables' class InheritanceTest < ActiveRecord::TestCase @@ -81,10 +80,6 @@ class InheritanceTest < ActiveRecord::TestCase assert_equal SubStiPost, SubStiPost.base_class end - def test_active_record_model_included_base_class - assert_equal Teapot, Teapot.base_class - end - def test_abstract_inheritance_base_class assert_equal LoosePerson, LoosePerson.base_class assert_equal LooseDescendant, LooseDescendant.base_class @@ -93,11 +88,7 @@ class InheritanceTest < ActiveRecord::TestCase end def test_base_class_activerecord_error - klass = Class.new { - extend ActiveRecord::Configuration - include ActiveRecord::Inheritance - } - + klass = Class.new { include ActiveRecord::Inheritance } assert_raise(ActiveRecord::ActiveRecordError) { klass.base_class } end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index 17c1634444..86451289e7 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -132,6 +132,26 @@ module ActiveRecord assert_equal %w(foo testingid), connection.columns(:testings).map(&:name).sort end + def test_create_table_raises_when_redefining_primary_key_column + error = assert_raise(ArgumentError) do + connection.create_table :testings do |t| + t.column :id, :string + end + end + + assert_equal "you can't redefine the primary key column 'id'. To define a custom primary key, pass { id: false } to create_table.", error.message + end + + def test_create_table_raises_when_redefining_custom_primary_key_column + error = assert_raise(ArgumentError) do + connection.create_table :testings, primary_key: :testing_id do |t| + t.column :testing_id, :string + end + end + + assert_equal "you can't redefine the primary key column 'testing_id'. To define a custom primary key, pass { id: false } to create_table.", error.message + end + def test_create_table_with_timestamps_should_create_datetime_columns connection.create_table table_name do |t| t.timestamps diff --git a/activerecord/test/cases/multiple_db_test.rb b/activerecord/test/cases/multiple_db_test.rb index 42461e8ecb..2e386a172a 100644 --- a/activerecord/test/cases/multiple_db_test.rb +++ b/activerecord/test/cases/multiple_db_test.rb @@ -96,12 +96,12 @@ class MultipleDbTest < ActiveRecord::TestCase unless in_memory_db? def test_associations_should_work_when_model_has_no_connection begin - ActiveRecord::Model.remove_connection + ActiveRecord::Base.remove_connection assert_nothing_raised ActiveRecord::ConnectionNotEstablished do College.first.courses.first end ensure - ActiveRecord::Model.establish_connection 'arunit' + ActiveRecord::Base.establish_connection 'arunit' end end end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index b5f32a57b2..4b938da5c4 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -592,6 +592,19 @@ class PersistencesTest < ActiveRecord::TestCase assert_equal 'super_title', t.title end + def test_update_columns_changing_id + topic = Topic.find(1) + topic.update_columns(id: 123) + assert_equal 123, topic.id + topic.reload + assert_equal 123, topic.id + end + + def test_update_columns_returns_boolean + topic = Topic.find(1) + assert_equal true, topic.update_columns(title: "New title") + end + def test_update_attributes topic = Topic.find(1) assert !topic.approved? diff --git a/activerecord/test/cases/pooled_connections_test.rb b/activerecord/test/cases/pooled_connections_test.rb index 0a6354f5cc..a8a9b06ec4 100644 --- a/activerecord/test/cases/pooled_connections_test.rb +++ b/activerecord/test/cases/pooled_connections_test.rb @@ -7,17 +7,17 @@ class PooledConnectionsTest < ActiveRecord::TestCase def setup @per_test_teardown = [] - @connection = ActiveRecord::Model.remove_connection + @connection = ActiveRecord::Base.remove_connection end def teardown - ActiveRecord::Model.clear_all_connections! - ActiveRecord::Model.establish_connection(@connection) + ActiveRecord::Base.clear_all_connections! + ActiveRecord::Base.establish_connection(@connection) @per_test_teardown.each {|td| td.call } end def checkout_connections - ActiveRecord::Model.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3})) + ActiveRecord::Base.establish_connection(@connection.merge({:pool => 2, :checkout_timeout => 0.3})) @connections = [] @timed_out = 0 @@ -34,15 +34,15 @@ class PooledConnectionsTest < ActiveRecord::TestCase # Will deadlock due to lack of Monitor timeouts in 1.9 def checkout_checkin_connections(pool_size, threads) - ActiveRecord::Model.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5})) + ActiveRecord::Base.establish_connection(@connection.merge({:pool => pool_size, :checkout_timeout => 0.5})) @connection_count = 0 @timed_out = 0 threads.times do Thread.new do begin - conn = ActiveRecord::Model.connection_pool.checkout + conn = ActiveRecord::Base.connection_pool.checkout sleep 0.1 - ActiveRecord::Model.connection_pool.checkin conn + ActiveRecord::Base.connection_pool.checkin conn @connection_count += 1 rescue ActiveRecord::ConnectionTimeoutError @timed_out += 1 @@ -55,13 +55,13 @@ class PooledConnectionsTest < ActiveRecord::TestCase checkout_checkin_connections 1, 2 assert_equal 2, @connection_count assert_equal 0, @timed_out - assert_equal 1, ActiveRecord::Model.connection_pool.connections.size + assert_equal 1, ActiveRecord::Base.connection_pool.connections.size end private def add_record(name) - ActiveRecord::Model.connection_pool.with_connection { Project.create! :name => name } + ActiveRecord::Base.connection_pool.with_connection { Project.create! :name => name } end end unless current_adapter?(:FrontBase) || in_memory_db? diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index e6e50a4cd4..bf8aacc363 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -188,14 +188,14 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase def test_set_primary_key_with_no_connection return skip("disconnect wipes in-memory db") if in_memory_db? - connection = ActiveRecord::Model.remove_connection + connection = ActiveRecord::Base.remove_connection model = Class.new(ActiveRecord::Base) model.primary_key = 'foo' assert_equal 'foo', model.primary_key - ActiveRecord::Model.establish_connection(connection) + ActiveRecord::Base.establish_connection(connection) assert_equal 'foo', model.primary_key end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 51a285a2b4..4ff481e6a5 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -184,6 +184,17 @@ class QueryCacheTest < ActiveRecord::TestCase assert_queries(2) { task.lock!; task.lock! } end end + + def test_cache_is_available_when_connection_is_connected + conf = ActiveRecord::Base.configurations + + ActiveRecord::Base.configurations = {} + Task.cache do + assert_queries(1) { Task.find(1); Task.find(1) } + end + ensure + ActiveRecord::Base.configurations = conf + end end class QueryCacheExpiryTest < ActiveRecord::TestCase diff --git a/activerecord/test/cases/relation_test.rb b/activerecord/test/cases/relation_test.rb index 6399111be6..98e278df82 100644 --- a/activerecord/test/cases/relation_test.rb +++ b/activerecord/test/cases/relation_test.rb @@ -256,5 +256,11 @@ module ActiveRecord test 'merge with a proc' do assert_equal [:foo], relation.merge(-> { where(:foo) }).where_values end + + test 'none!' do + assert relation.none!.equal?(relation) + assert_equal [NullRelation], relation.extending_values + assert relation.is_a?(NullRelation) + end end end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 5f96145b47..bc6cac0c6c 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -1391,6 +1391,15 @@ class RelationTest < ActiveRecord::TestCase end end + test "loaded relations cannot be mutated by extending!" do + relation = Post.all + relation.to_a + + assert_raises(ActiveRecord::ImmutableRelation) do + relation.extending! Module.new + end + end + test "relations show the records in #inspect" do relation = Post.limit(2) assert_equal "#<ActiveRecord::Relation [#{Post.limit(2).map(&:inspect).join(', ')}]>", relation.inspect diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 5f13124e5b..7ff0044bd4 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -203,6 +203,12 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{t.text\s+"body",\s+null: false$}, output end + def test_schema_dump_includes_length_for_mysql_binary_fields + output = standard_dump + assert_match %r{t.binary\s+"var_binary",\s+limit: 255$}, output + assert_match %r{t.binary\s+"var_binary_large",\s+limit: 4095$}, output + end + def test_schema_dump_includes_length_for_mysql_blob_and_text_fields output = standard_dump assert_match %r{t.binary\s+"tiny_blob",\s+limit: 255$}, output diff --git a/activerecord/test/cases/serialization_test.rb b/activerecord/test/cases/serialization_test.rb index 25b860878a..eb9cb91e32 100644 --- a/activerecord/test/cases/serialization_test.rb +++ b/activerecord/test/cases/serialization_test.rb @@ -45,4 +45,20 @@ class SerializationTest < ActiveRecord::TestCase assert_equal @contact_attributes[:awesome], contact.awesome, "For #{format}" end end + + def test_include_root_in_json_allows_inheritance + original_root_in_json = ActiveRecord::Base.include_root_in_json + ActiveRecord::Base.include_root_in_json = true + + klazz = Class.new(ActiveRecord::Base) + klazz.table_name = 'topics' + assert klazz.include_root_in_json + + klazz.include_root_in_json = false + assert ActiveRecord::Base.include_root_in_json + assert !klazz.include_root_in_json + assert !klazz.new.include_root_in_json + ensure + ActiveRecord::Base.include_root_in_json = original_root_in_json + end end diff --git a/activerecord/test/cases/serialized_attribute_test.rb b/activerecord/test/cases/serialized_attribute_test.rb index f24ee54cd2..068f3cf3cd 100644 --- a/activerecord/test/cases/serialized_attribute_test.rb +++ b/activerecord/test/cases/serialized_attribute_test.rb @@ -56,11 +56,21 @@ class SerializedAttributeTest < ActiveRecord::TestCase def test_serialized_attribute_before_type_cast_returns_unserialized_value Topic.serialize :content, Hash - t = Topic.new(:content => { :foo => :bar }) - assert_equal({ :foo => :bar }, t.content_before_type_cast) + t = Topic.new(content: { foo: :bar }) + assert_equal({ foo: :bar }, t.content_before_type_cast) t.save! t.reload - assert_equal({ :foo => :bar }, t.content_before_type_cast) + assert_equal({ foo: :bar }, t.content_before_type_cast) + end + + def test_serialized_attributes_before_type_cast_returns_unserialized_value + Topic.serialize :content, Hash + + t = Topic.new(content: { foo: :bar }) + assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"]) + t.save! + t.reload + assert_equal({ foo: :bar }, t.attributes_before_type_cast["content"]) end def test_serialized_attribute_calling_dup_method diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index bb4f2c8064..fdca10f4fb 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -14,6 +14,21 @@ class TransactionTest < ActiveRecord::TestCase @first, @second = Topic.find(1, 2).sort_by { |t| t.id } end + def test_raise_after_destroy + refute @first.frozen? + + assert_raises(RuntimeError) { + Topic.transaction do + @first.destroy + assert @first.frozen? + raise + end + } + + assert @first.reload + refute @first.frozen? + end + def test_successful Topic.transaction do @first.approved = true diff --git a/activerecord/test/cases/unconnected_test.rb b/activerecord/test/cases/unconnected_test.rb index 5a69054445..e82ca3f93d 100644 --- a/activerecord/test/cases/unconnected_test.rb +++ b/activerecord/test/cases/unconnected_test.rb @@ -7,13 +7,13 @@ class TestUnconnectedAdapter < ActiveRecord::TestCase self.use_transactional_fixtures = false def setup - @underlying = ActiveRecord::Model.connection - @specification = ActiveRecord::Model.remove_connection + @underlying = ActiveRecord::Base.connection + @specification = ActiveRecord::Base.remove_connection end def teardown @underlying = nil - ActiveRecord::Model.establish_connection(@specification) + ActiveRecord::Base.establish_connection(@specification) load_schema if in_memory_db? end diff --git a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb index 174d96aa4e..32d2bf746f 100644 --- a/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb +++ b/activerecord/test/cases/validations/i18n_generate_message_validation_test.rb @@ -59,4 +59,18 @@ class I18nGenerateMessageValidationTest < ActiveRecord::TestCase assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title') end + test "translation for 'taken' can be overridden in activerecord scope" do + I18n.backend.store_translations "en", {activerecord: {errors: {messages: {taken: "Custom taken message" }}}} + assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title') + end + + test "translation for 'taken' can be overridden in activerecord model scope" do + I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {taken: "Custom taken message" }}}}} + assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title') + end + + test "translation for 'taken' can be overridden in activerecord attributes scope" do + I18n.backend.store_translations "en", {activerecord: {errors: {models: {topic: {attributes: {title: {taken: "Custom taken message" }}}}}}} + assert_equal "Custom taken message", @topic.errors.generate_message(:title, :taken, :value => 'title') + end end diff --git a/activerecord/test/models/teapot.rb b/activerecord/test/models/teapot.rb deleted file mode 100644 index b035b18c1b..0000000000 --- a/activerecord/test/models/teapot.rb +++ /dev/null @@ -1,35 +0,0 @@ -class Teapot - # I'm a little teapot, - # Short and stout, - # Here is my handle - # Here is my spout - # When I get all steamed up, - # Hear me shout, - # Tip me over and pour me out! - # - # HELL YEAH TEAPOT SONG - - include ActiveRecord::Model -end - -class OtherTeapot < Teapot -end - -class OMFGIMATEAPOT - def aaahhh - "mmm" - end -end - -class CoolTeapot < OMFGIMATEAPOT - include ActiveRecord::Model - self.table_name = "teapots" -end - -class Ceiling - include ActiveRecord::Model - - class Teapot - include ActiveRecord::Model - end -end diff --git a/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb index 24a43d7ece..f25f72c481 100644 --- a/activerecord/test/schema/mysql2_specific_schema.rb +++ b/activerecord/test/schema/mysql2_specific_schema.rb @@ -1,15 +1,19 @@ ActiveRecord::Schema.define do - create_table :binary_fields, :force => true do |t| - t.binary :tiny_blob, :limit => 255 - t.binary :normal_blob, :limit => 65535 - t.binary :medium_blob, :limit => 16777215 - t.binary :long_blob, :limit => 2147483647 - t.text :tiny_text, :limit => 255 - t.text :normal_text, :limit => 65535 - t.text :medium_text, :limit => 16777215 - t.text :long_text, :limit => 2147483647 + create_table :binary_fields, force: true do |t| + t.binary :var_binary, limit: 255 + t.binary :var_binary_large, limit: 4095 + t.column :tiny_blob, 'tinyblob', limit: 255 + t.binary :normal_blob, limit: 65535 + t.binary :medium_blob, limit: 16777215 + t.binary :long_blob, limit: 2147483647 + t.text :tiny_text, limit: 255 + t.text :normal_text, limit: 65535 + t.text :medium_text, limit: 16777215 + t.text :long_text, limit: 2147483647 end + add_index :binary_fields, :var_binary + ActiveRecord::Base.connection.execute <<-SQL DROP PROCEDURE IF EXISTS ten; SQL diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb index 802c08b819..5401c12ed5 100644 --- a/activerecord/test/schema/mysql_specific_schema.rb +++ b/activerecord/test/schema/mysql_specific_schema.rb @@ -1,15 +1,19 @@ ActiveRecord::Schema.define do - create_table :binary_fields, :force => true do |t| - t.binary :tiny_blob, :limit => 255 - t.binary :normal_blob, :limit => 65535 - t.binary :medium_blob, :limit => 16777215 - t.binary :long_blob, :limit => 2147483647 - t.text :tiny_text, :limit => 255 - t.text :normal_text, :limit => 65535 - t.text :medium_text, :limit => 16777215 - t.text :long_text, :limit => 2147483647 + create_table :binary_fields, force: true do |t| + t.binary :var_binary, limit: 255 + t.binary :var_binary_large, limit: 4095 + t.column :tiny_blob, 'tinyblob', limit: 255 + t.binary :normal_blob, limit: 65535 + t.binary :medium_blob, limit: 16777215 + t.binary :long_blob, limit: 2147483647 + t.text :tiny_text, limit: 255 + t.text :normal_text, limit: 65535 + t.text :medium_text, limit: 16777215 + t.text :long_text, limit: 2147483647 end + add_index :binary_fields, :var_binary + ActiveRecord::Base.connection.execute <<-SQL DROP PROCEDURE IF EXISTS ten; SQL diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index 2e4ec96933..eec06754a5 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -648,12 +648,6 @@ ActiveRecord::Schema.define do t.datetime :ending end - create_table :teapots, :force => true do |t| - t.string :name - t.string :type - t.timestamps - end - create_table :topics, :force => true do |t| t.string :title t.string :author_name diff --git a/activerecord/test/support/connection.rb b/activerecord/test/support/connection.rb index bea894a583..196b3a9493 100644 --- a/activerecord/test/support/connection.rb +++ b/activerecord/test/support/connection.rb @@ -13,9 +13,9 @@ module ARTest def self.connect puts "Using #{connection_name}" - ActiveRecord::Model.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024) - ActiveRecord::Model.configurations = connection_config - ActiveRecord::Model.establish_connection 'arunit' + ActiveRecord::Base.logger = ActiveSupport::Logger.new("debug.log", 0, 100 * 1024 * 1024) + ActiveRecord::Base.configurations = connection_config + ActiveRecord::Base.establish_connection 'arunit' ARUnit2Model.establish_connection 'arunit2' end end |