diff options
Diffstat (limited to 'activerecord')
88 files changed, 582 insertions, 426 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index 756bad5507..5a0c391154 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,7 +1,28 @@ ## Rails 4.0.0 (unreleased) ## +* Remove support for parsing YAML parameters from request. + + *Aaron Patterson* + +* Support for PostgreSQL's `ltree` data type. + + *Rob Worley* + +* Fix undefined method `to_i` when calling `new` on a scope that uses an + Array; Fix FloatDomainError when setting integer column to NaN. + Fixes #8718, #8734, #8757. + + *Jason Stirk + Tristan Harward* + +* Rename `update_attributes` to `update`, keep `update_attributes` as an alias for `update` method. + This is a soft-deprecation for `update_attributes`, although it will still work without any + deprecation message in 4.0 is recommended to start using `update` since `update_attributes` will be + deprecated and removed in future versions of Rails. + + *Amparo Luna + Guillermo Iguaran* + * `after_commit` and `after_rollback` now validate the `:on` option and raise an `ArgumentError` - if it is not one of `:create`, `:destroy` or ``:update` + if it is not one of `:create`, `:destroy` or `:update` *Pascal Friederich* @@ -18,7 +39,8 @@ If migrating down, the given migration / block is run normally. See the [Guide on Migration](https://github.com/rails/rails/blob/master/guides/source/migrations.md#reverting-previous-migrations) - Attempting to revert the methods `execute`, `remove_columns` and `change_column` will now raise an IrreversibleMigration instead of actually executing them without any output. + Attempting to revert the methods `execute`, `remove_columns` and `change_column` will now + raise an `IrreversibleMigration` instead of actually executing them without any output. *Marc-André Lafortune* diff --git a/activerecord/MIT-LICENSE b/activerecord/MIT-LICENSE index 03bde18130..0d7fb865e2 100644 --- a/activerecord/MIT-LICENSE +++ b/activerecord/MIT-LICENSE @@ -1,4 +1,4 @@ -Copyright (c) 2004-2012 David Heinemeier Hansson +Copyright (c) 2004-2013 David Heinemeier Hansson Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the diff --git a/activerecord/examples/performance.rb b/activerecord/examples/performance.rb index cd9825b50c..ad12f8597f 100644 --- a/activerecord/examples/performance.rb +++ b/activerecord/examples/performance.rb @@ -143,7 +143,7 @@ Benchmark.ips(TIME) do |x| end x.report 'Resource#update' do - Exhibit.first.update_attributes(:name => 'bob') + Exhibit.first.update(name: 'bob') end x.report 'Resource#destroy' do diff --git a/activerecord/lib/active_record.rb b/activerecord/lib/active_record.rb index 822da84d19..c33f03f13f 100644 --- a/activerecord/lib/active_record.rb +++ b/activerecord/lib/active_record.rb @@ -1,5 +1,5 @@ #-- -# Copyright (c) 2004-2012 David Heinemeier Hansson +# Copyright (c) 2004-2013 David Heinemeier Hansson # # Permission is hereby granted, free of charge, to any person obtaining # a copy of this software and associated documentation files (the diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb index 8101f7a45e..9d1c12ec62 100644 --- a/activerecord/lib/active_record/aggregations.rb +++ b/activerecord/lib/active_record/aggregations.rb @@ -113,7 +113,7 @@ module ActiveRecord # other than the writer method. # # The immutable requirement is enforced by Active Record by freezing any object assigned as a value - # object. Attempting to change it afterwards will result in a ActiveSupport::FrozenObjectError. + # object. Attempting to change it afterwards will result in a RuntimeError. # # Read more about value objects on http://c2.com/cgi/wiki?ValueObject and on the dangers of not # keeping value objects immutable on http://c2.com/cgi/wiki?ValueObjectsShouldBeImmutable @@ -165,7 +165,7 @@ module ActiveRecord # by specifying an instance of the value object in the conditions hash. The following example # finds all customers with +balance_amount+ equal to 20 and +balance_currency+ equal to "USD": # - # Customer.where(balance: Money.new(20, "USD")).all + # Customer.where(balance: Money.new(20, "USD")) # module ClassMethods # Adds reader and writer methods for manipulating a value object: diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index d8b6d7a86b..16a46a59d1 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1,8 +1,6 @@ require 'active_support/core_ext/enumerable' require 'active_support/core_ext/string/conversions' require 'active_support/core_ext/module/remove_method' -require 'active_support/dependencies/autoload' -require 'active_support/concern' require 'active_record/errors' module ActiveRecord @@ -194,7 +192,7 @@ module ActiveRecord # * <tt>Project#project_manager, Project#project_manager=(project_manager), Project#project_manager.nil?,</tt> # * <tt>Project#milestones.empty?, Project#milestones.size, Project#milestones, Project#milestones<<(milestone),</tt> # <tt>Project#milestones.delete(milestone), Project#milestones.destroy(mileston), Project#milestones.find(milestone_id),</tt> - # <tt>Project#milestones.all(options), Project#milestones.build, Project#milestones.create</tt> + # <tt>Project#milestones.build, Project#milestones.create</tt> # * <tt>Project#categories.empty?, Project#categories.size, Project#categories, Project#categories<<(category1),</tt> # <tt>Project#categories.delete(category1), Project#categories.destroy(category1)</tt> # @@ -459,7 +457,7 @@ module ActiveRecord # has_many :people do # def find_or_create_by_name(name) # first_name, last_name = name.split(" ", 2) - # find_or_create_by_first_name_and_last_name(first_name, last_name) + # find_or_create_by(first_name: first_name, last_name: last_name) # end # end # end @@ -474,7 +472,7 @@ module ActiveRecord # module FindOrCreateByNameExtension # def find_or_create_by_name(name) # first_name, last_name = name.split(" ", 2) - # find_or_create_by_first_name_and_last_name(first_name, last_name) + # find_or_create_by(first_name: first_name, last_name: last_name) # end # end # @@ -743,7 +741,7 @@ module ActiveRecord # other than the main one. If this is the case Active Record falls back to the previously # used LEFT OUTER JOIN based strategy. For example # - # Post.includes([:author, :comments]).where(['comments.approved = ?', true]).all + # Post.includes([:author, :comments]).where(['comments.approved = ?', true]) # # This will result in a single SQL query with joins along the lines of: # <tt>LEFT OUTER JOIN comments ON comments.post_id = posts.id</tt> and @@ -951,7 +949,7 @@ module ActiveRecord # # The <tt>:dependent</tt> option can have different values which specify how the deletion # is done. For more information, see the documentation for this option on the different - # specific association types. When no option is given, the behaviour is to do nothing + # specific association types. When no option is given, the behavior is to do nothing # with the associated records when destroying a record. # # Note that <tt>:dependent</tt> is implemented using Rails' callback @@ -1081,7 +1079,7 @@ module ActiveRecord # === Example # # Example: A Firm class declares <tt>has_many :clients</tt>, which will add: - # * <tt>Firm#clients</tt> (similar to <tt>Clients.all conditions: ["firm_id = ?", id]</tt>) + # * <tt>Firm#clients</tt> (similar to <tt>Client.where(firm_id: id)</tt>) # * <tt>Firm#clients<<</tt> # * <tt>Firm#clients.delete</tt> # * <tt>Firm#clients.destroy</tt> @@ -1091,7 +1089,7 @@ module ActiveRecord # * <tt>Firm#clients.clear</tt> # * <tt>Firm#clients.empty?</tt> (similar to <tt>firm.clients.size == 0</tt>) # * <tt>Firm#clients.size</tt> (similar to <tt>Client.count "firm_id = #{id}"</tt>) - # * <tt>Firm#clients.find</tt> (similar to <tt>Client.find(id, conditions: "firm_id = #{id}")</tt>) + # * <tt>Firm#clients.find</tt> (similar to <tt>Client.where(firm_id: id).find(id)</tt>) # * <tt>Firm#clients.exists?(name: 'ACME')</tt> (similar to <tt>Client.exists?(name: 'ACME', firm_id: firm.id)</tt>) # * <tt>Firm#clients.build</tt> (similar to <tt>Client.new("firm_id" => id)</tt>) # * <tt>Firm#clients.create</tt> (similar to <tt>c = Client.new("firm_id" => id); c.save; c</tt>) @@ -1213,7 +1211,7 @@ module ActiveRecord # === Example # # An Account class declares <tt>has_one :beneficiary</tt>, which will add: - # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.first(conditions: "account_id = #{id}")</tt>) + # * <tt>Account#beneficiary</tt> (similar to <tt>Beneficiary.where(account_id: id).first</tt>) # * <tt>Account#beneficiary=(beneficiary)</tt> (similar to <tt>beneficiary.account_id = account.id; beneficiary.save</tt>) # * <tt>Account#build_beneficiary</tt> (similar to <tt>Beneficiary.new("account_id" => id)</tt>) # * <tt>Account#create_beneficiary</tt> (similar to <tt>b = Beneficiary.new("account_id" => id); b.save; b</tt>) diff --git a/activerecord/lib/active_record/associations/belongs_to_association.rb b/activerecord/lib/active_record/associations/belongs_to_association.rb index 75f72c1a46..532af3e83e 100644 --- a/activerecord/lib/active_record/associations/belongs_to_association.rb +++ b/activerecord/lib/active_record/associations/belongs_to_association.rb @@ -50,8 +50,11 @@ module ActiveRecord # Checks whether record is different to the current target, without loading it def different_target?(record) - record.nil? && owner[reflection.foreign_key] || - record && record.id != owner[reflection.foreign_key] + if record.nil? + owner[reflection.foreign_key] + else + record.id != owner[reflection.foreign_key] + end end def replace_keys(record) diff --git a/activerecord/lib/active_record/associations/collection_proxy.rb b/activerecord/lib/active_record/associations/collection_proxy.rb index 7c43e37cf2..33dce58982 100644 --- a/activerecord/lib/active_record/associations/collection_proxy.rb +++ b/activerecord/lib/active_record/associations/collection_proxy.rb @@ -758,7 +758,7 @@ module ActiveRecord # person.pets.count # => 0 # person.pets.any? # => true # - # You can also pass a block to define criteria. The behaviour + # You can also pass a block to define criteria. The behavior # is the same, it returns true if the collection based on the # criteria is not empty. # @@ -793,7 +793,7 @@ module ActiveRecord # person.pets.many? #=> true # # You can also pass a block to define criteria. The - # behaviour is the same, it returns true if the collection + # behavior is the same, it returns true if the collection # based on the criteria has more than one record. # # person.pets diff --git a/activerecord/lib/active_record/associations/has_many_through_association.rb b/activerecord/lib/active_record/associations/has_many_through_association.rb index c3266f2bb4..d1458f30ba 100644 --- a/activerecord/lib/active_record/associations/has_many_through_association.rb +++ b/activerecord/lib/active_record/associations/has_many_through_association.rb @@ -114,11 +114,7 @@ module ActiveRecord end def target_reflection_has_associated_record? - if through_reflection.macro == :belongs_to && owner[through_reflection.foreign_key].blank? - false - else - true - end + !(through_reflection.macro == :belongs_to && owner[through_reflection.foreign_key].blank?) end def update_through_counter?(method) diff --git a/activerecord/lib/active_record/associations/has_one_through_association.rb b/activerecord/lib/active_record/associations/has_one_through_association.rb index fdf8ae1453..08e0ec691f 100644 --- a/activerecord/lib/active_record/associations/has_one_through_association.rb +++ b/activerecord/lib/active_record/associations/has_one_through_association.rb @@ -23,7 +23,7 @@ module ActiveRecord attributes = construct_join_attributes(record) if through_record - through_record.update_attributes(attributes) + through_record.update(attributes) elsif owner.new_record? through_proxy.build(attributes) else diff --git a/activerecord/lib/active_record/associations/preloader.rb b/activerecord/lib/active_record/associations/preloader.rb index 0848e7afb3..82bf426b22 100644 --- a/activerecord/lib/active_record/associations/preloader.rb +++ b/activerecord/lib/active_record/associations/preloader.rb @@ -100,7 +100,9 @@ module ActiveRecord case association when Hash preload_hash(association) - when String, Symbol + when Symbol + preload_one(association) + when String preload_one(association.to_sym) else raise ArgumentError, "#{association.inspect} was not recognised for preload" diff --git a/activerecord/lib/active_record/associations/preloader/association.rb b/activerecord/lib/active_record/associations/preloader/association.rb index cbf5e734ea..82588905c6 100644 --- a/activerecord/lib/active_record/associations/preloader/association.rb +++ b/activerecord/lib/active_record/associations/preloader/association.rb @@ -76,7 +76,7 @@ module ActiveRecord else # Some databases impose a limit on the number of ids in a list (in Oracle it's 1000) # Make several smaller queries if necessary or make one query if the adapter supports it - sliced = owner_keys.each_slice(model.connection.in_clause_length || owner_keys.size) + sliced = owner_keys.each_slice(klass.connection.in_clause_length || owner_keys.size) records = sliced.map { |slice| records_for(slice).to_a }.flatten end diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 0333605eac..616ae1631f 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -1,5 +1,4 @@ require 'active_support/core_ext/module/attribute_accessors' -require 'active_support/deprecation' module ActiveRecord module AttributeMethods @@ -71,11 +70,11 @@ module ActiveRecord super(attr, value) end - def update(*) + def update_record(*) partial_writes? ? super(keys_for_partial_write) : super end - def create(*) + def create_record(*) partial_writes? ? super(keys_for_partial_write) : super end diff --git a/activerecord/lib/active_record/attribute_methods/primary_key.rb b/activerecord/lib/active_record/attribute_methods/primary_key.rb index 0857b02c8e..310f1b6e75 100644 --- a/activerecord/lib/active_record/attribute_methods/primary_key.rb +++ b/activerecord/lib/active_record/attribute_methods/primary_key.rb @@ -76,7 +76,7 @@ module ActiveRecord end def get_primary_key(base_name) #:nodoc: - return 'id' unless base_name && !base_name.blank? + return 'id' if base_name.blank? case primary_key_prefix_type when :table_name diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index aab832c2f7..bf5793d454 100644 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -162,12 +162,9 @@ module ActiveRecord #:nodoc: # # Dynamic attribute-based finders are a cleaner way of getting (and/or creating) objects # by simple queries without turning to SQL. They work by appending the name of an attribute - # to <tt>find_by_</tt>, <tt>find_last_by_</tt>, or <tt>find_all_by_</tt> and thus produces finders - # like <tt>Person.find_by_user_name</tt>, <tt>Person.find_all_by_last_name</tt>, and - # <tt>Payment.find_by_transaction_id</tt>. Instead of writing - # <tt>Person.where(user_name: user_name).first</tt>, you just do <tt>Person.find_by_user_name(user_name)</tt>. - # And instead of writing <tt>Person.where(last_name: last_name).all</tt>, you just do - # <tt>Person.find_all_by_last_name(last_name)</tt>. + # to <tt>find_by_</tt> # like <tt>Person.find_by_user_name</tt>. + # Instead of writing # <tt>Person.where(user_name: user_name).first</tt>, you just do + # <tt>Person.find_by_user_name(user_name)</tt>. # # It's possible to add an exclamation point (!) on the end of the dynamic finders to get them to raise an # <tt>ActiveRecord::RecordNotFound</tt> error if they do not return any records, @@ -180,46 +177,7 @@ module ActiveRecord #:nodoc: # # It's even possible to call these dynamic finder methods on relations and named scopes. # - # Payment.order("created_on").find_all_by_amount(50) - # Payment.pending.find_last_by_amount(100) - # - # The same dynamic finder style can be used to create the object if it doesn't already exist. - # This dynamic finder is called with <tt>find_or_create_by_</tt> and will return the object if - # it already exists and otherwise creates it, then returns it. Protected attributes won't be set - # unless they are given in a block. - # - # # No 'Summer' tag exists - # Tag.find_or_create_by_name("Summer") # equal to Tag.create(name: "Summer") - # - # # Now the 'Summer' tag does exist - # Tag.find_or_create_by_name("Summer") # equal to Tag.find_by_name("Summer") - # - # # Now 'Bob' exist and is an 'admin' - # User.find_or_create_by_name('Bob', age: 40) { |u| u.admin = true } - # - # Adding an exclamation point (!) on to the end of <tt>find_or_create_by_</tt> will - # raise an <tt>ActiveRecord::RecordInvalid</tt> error if the new record is invalid. - # - # Use the <tt>find_or_initialize_by_</tt> finder if you want to return a new record without - # saving it first. Protected attributes won't be set unless they are given in a block. - # - # # No 'Winter' tag exists - # winter = Tag.find_or_initialize_by_name("Winter") - # winter.persisted? # false - # - # To find by a subset of the attributes to be used for instantiating a new object, pass a hash instead of - # a list of parameters. - # - # Tag.find_or_create_by_name(name: "rails", creator: current_user) - # - # That will either find an existing tag named "rails", or create a new one while setting the - # user that created it. - # - # Just like <tt>find_by_*</tt>, you can also use <tt>scoped_by_*</tt> to retrieve data. The good thing about - # using this feature is that the very first time result is returned using <tt>method_missing</tt> technique - # but after that the method is declared on the class. Henceforth <tt>method_missing</tt> will not be hit. - # - # User.scoped_by_user_name('David') + # Payment.order("created_on").find_by_amount(50) # # == Saving arrays, hashes, and other non-mappable objects in text columns # diff --git a/activerecord/lib/active_record/callbacks.rb b/activerecord/lib/active_record/callbacks.rb index 1c9c627090..22226b2f4f 100644 --- a/activerecord/lib/active_record/callbacks.rb +++ b/activerecord/lib/active_record/callbacks.rb @@ -299,11 +299,11 @@ module ActiveRecord run_callbacks(:save) { super } end - def create #:nodoc: + def create_record #:nodoc: run_callbacks(:create) { super } end - def update(*) #:nodoc: + def update_record(*) #:nodoc: run_callbacks(:update) { super } end 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 82d0cf7e2e..27e6e8898c 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/connection_pool.rb @@ -2,7 +2,6 @@ require 'thread' require 'thread_safe' require 'monitor' require 'set' -require 'active_support/deprecation' module ActiveRecord # Raised when a connection could not be obtained within the connection diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 8517ce5fc5..cbb6869e66 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -5,7 +5,6 @@ require 'active_support/core_ext/benchmark' require 'active_record/connection_adapters/schema_cache' require 'active_record/connection_adapters/abstract/schema_dumper' require 'monitor' -require 'active_support/deprecation' module ActiveRecord module ConnectionAdapters # :nodoc: 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 124a2419ec..52b0b3fe79 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -14,7 +14,7 @@ module ActiveRecord end def extract_default(default) - if sql_type =~ /blob/i || type == :text + if blob_or_text_column? if default.blank? null || strict ? nil : '' else @@ -28,9 +28,13 @@ module ActiveRecord end def has_default? - return false if sql_type =~ /blob/i || type == :text #mysql forbids defaults on blob and text columns + return false if blob_or_text_column? #mysql forbids defaults on blob and text columns super end + + def blob_or_text_column? + sql_type =~ /blob/i || type == :text + end # Must return the relevant concrete adapter def adapter diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb index fd36a5b075..fb28ecb6cf 100644 --- a/activerecord/lib/active_record/connection_adapters/column.rb +++ b/activerecord/lib/active_record/connection_adapters/column.rb @@ -206,7 +206,7 @@ module ActiveRecord when TrueClass, FalseClass value ? 1 : 0 else - value.to_i + value.to_i rescue nil end end 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 34d7a246b2..9b5170f657 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/database_statements.rb @@ -1,5 +1,3 @@ -require 'active_support/deprecation' - module ActiveRecord module ConnectionAdapters class PostgreSQLAdapter < AbstractAdapter diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index 18ea83ce42..02c295983f 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -82,7 +82,7 @@ module ActiveRecord def type_cast(value) return if value.nil? - value.to_i rescue value ? 1 : 0 + ConnectionAdapters::Column.value_to_integer value end end @@ -276,6 +276,7 @@ module ActiveRecord register_type 'circle', OID::Identity.new register_type 'hstore', OID::Hstore.new register_type 'json', OID::Json.new + register_type 'ltree', OID::Identity.new register_type 'int4range', OID::IntRange.new alias_type 'int8range', 'int4range' diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index d62a375470..b1b0467379 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -17,22 +17,25 @@ require 'ipaddr' module ActiveRecord module ConnectionHandling + VALID_CONN_PARAMS = [:host, :hostaddr, :port, :dbname, :user, :password, :connect_timeout, + :client_encoding, :options, :application_name, :fallback_application_name, + :keepalives, :keepalives_idle, :keepalives_interval, :keepalives_count, + :tty, :sslmode, :requiressl, :sslcert, :sslkey, :sslrootcert, :sslcrl, + :requirepeer, :krbsrvname, :gsslib, :service] + # Establishes a connection to the database that's used by all Active Record objects def postgresql_connection(config) # :nodoc: conn_params = config.symbolize_keys - # Forward any unused config params to PGconn.connect. - [:statement_limit, :encoding, :min_messages, :schema_search_path, - :schema_order, :adapter, :pool, :checkout_timeout, :template, - :reaping_frequency, :insert_returning, :variables].each do |key| - conn_params.delete key - end - conn_params.delete_if { |k,v| v.nil? } + conn_params.delete_if { |_, v| v.nil? } # Map ActiveRecords param names to PGs. conn_params[:user] = conn_params.delete(:username) if conn_params[:username] conn_params[:dbname] = conn_params.delete(:database) if conn_params[:database] + # Forward only valid config params to PGconn.connect. + conn_params.keep_if { |k, _| VALID_CONN_PARAMS.include?(k) } + # The postgres drivers don't allow the creation of an unconnected PGconn object, # so just pass a nil connection object for the time being. ConnectionAdapters::PostgreSQLAdapter.new(nil, logger, conn_params, config) @@ -173,6 +176,8 @@ module ActiveRecord :decimal when 'hstore' :hstore + when 'ltree' + :ltree # Network address types when 'inet' :inet @@ -275,6 +280,10 @@ module ActiveRecord column(name, 'hstore', options) end + def ltree(name, options = {}) + column(name, 'ltree', options) + end + def inet(name, options = {}) column(name, 'inet', options) end @@ -340,7 +349,8 @@ module ActiveRecord macaddr: { name: "macaddr" }, uuid: { name: "uuid" }, json: { name: "json" }, - intrange: { name: "int4range" } + intrange: { name: "int4range" }, + ltree: { name: "ltree" } } include Quoting @@ -451,8 +461,6 @@ module ActiveRecord @visitor = BindSubstitution.new self end - connection_parameters.delete :prepared_statements - @connection_parameters, @config = connection_parameters, config # @local_tz is initialized as nil to avoid warnings when connect tries to use it @@ -640,32 +648,30 @@ module ActiveRecord end def exec_cache(sql, binds) + stmt_key = prepare_statement sql + + # Clear the queue + @connection.get_last_result + @connection.send_query_prepared(stmt_key, binds.map { |col, val| + type_cast(val, col) + }) + @connection.block + @connection.get_last_result + rescue PGError => e + # Get the PG code for the failure. Annoyingly, the code for + # prepared statements whose return value may have changed is + # FEATURE_NOT_SUPPORTED. Check here for more details: + # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573 begin - stmt_key = prepare_statement sql - - # Clear the queue - @connection.get_last_result - @connection.send_query_prepared(stmt_key, binds.map { |col, val| - type_cast(val, col) - }) - @connection.block - @connection.get_last_result - rescue PGError => e - # Get the PG code for the failure. Annoyingly, the code for - # prepared statements whose return value may have changed is - # FEATURE_NOT_SUPPORTED. Check here for more details: - # http://git.postgresql.org/gitweb/?p=postgresql.git;a=blob;f=src/backend/utils/cache/plancache.c#l573 - begin - code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE) - rescue - raise e - end - if FEATURE_NOT_SUPPORTED == code - @statements.delete sql_key(sql) - retry - else - raise e - end + code = e.result.result_error_field(PGresult::PG_DIAG_SQLSTATE) + rescue + raise e + end + if FEATURE_NOT_SUPPORTED == code + @statements.delete sql_key(sql) + retry + else + raise e end end diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb index ea3bb8f33f..5a4ef5991d 100644 --- a/activerecord/lib/active_record/fixtures.rb +++ b/activerecord/lib/active_record/fixtures.rb @@ -5,8 +5,6 @@ require 'active_support/dependencies' require 'active_record/fixture_set/file' require 'active_record/errors' -require 'active_support/deprecation' # temporary - module ActiveRecord class FixtureClassNotFound < ActiveRecord::ActiveRecordError #:nodoc: end diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb index 6ab67fdece..e630897a4b 100644 --- a/activerecord/lib/active_record/inheritance.rb +++ b/activerecord/lib/active_record/inheritance.rb @@ -1,3 +1,5 @@ +require 'active_support/core_ext/hash/indifferent_access' + module ActiveRecord module Inheritance extend ActiveSupport::Concern diff --git a/activerecord/lib/active_record/locking/optimistic.rb b/activerecord/lib/active_record/locking/optimistic.rb index 035c77c424..701949e57b 100644 --- a/activerecord/lib/active_record/locking/optimistic.rb +++ b/activerecord/lib/active_record/locking/optimistic.rb @@ -66,7 +66,7 @@ module ActiveRecord send(lock_col + '=', previous_lock_value + 1) end - def update(attribute_names = @attributes.keys) #:nodoc: + def update_record(attribute_names = @attributes.keys) #:nodoc: return super unless locking_enabled? return 0 if attribute_names.empty? diff --git a/activerecord/lib/active_record/locking/pessimistic.rb b/activerecord/lib/active_record/locking/pessimistic.rb index b4bb95a392..8e4ddcac82 100644 --- a/activerecord/lib/active_record/locking/pessimistic.rb +++ b/activerecord/lib/active_record/locking/pessimistic.rb @@ -26,7 +26,7 @@ module ActiveRecord # # Account.transaction do # # select * from accounts where ... - # accounts = Account.where(...).all + # accounts = Account.where(...) # account1 = accounts.detect { |account| ... } # account2 = accounts.detect { |account| ... } # # select * from accounts where id=? for update diff --git a/activerecord/lib/active_record/log_subscriber.rb b/activerecord/lib/active_record/log_subscriber.rb index 2366a91bb5..c1ba524c84 100644 --- a/activerecord/lib/active_record/log_subscriber.rb +++ b/activerecord/lib/active_record/log_subscriber.rb @@ -21,13 +21,15 @@ module ActiveRecord end def render_bind(column, value) - if column.type == :binary - rendered_value = "<#{value.bytesize} bytes of binary data>" + if column + if column.binary? + value = "<#{value.bytesize} bytes of binary data>" + end + + [column.name, value] else - rendered_value = value + [nil, value] end - - [column.name, rendered_value] end def sql(event) diff --git a/activerecord/lib/active_record/nested_attributes.rb b/activerecord/lib/active_record/nested_attributes.rb index 4c9bd76d7c..c5bd11edbf 100644 --- a/activerecord/lib/active_record/nested_attributes.rb +++ b/activerecord/lib/active_record/nested_attributes.rb @@ -58,7 +58,7 @@ module ActiveRecord # It also allows you to update the avatar through the member: # # params = { member: { avatar_attributes: { id: '2', icon: 'sad' } } } - # member.update_attributes params[:member] + # member.update params[:member] # member.avatar.icon # => 'sad' # # By default you will only be able to set and update attributes on the diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 4d1a9c94b7..3011f959a5 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -212,7 +212,7 @@ module ActiveRecord # Updates the attributes of the model from the passed-in hash and saves the # record, all wrapped in a transaction. If the object is invalid, the saving # will fail and false will be returned. - def update_attributes(attributes) + def update(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do @@ -220,10 +220,12 @@ module ActiveRecord save end end + + alias update_attributes update - # Updates its receiver just like +update_attributes+ but calls <tt>save!</tt> instead + # Updates its receiver just like +update+ but calls <tt>save!</tt> instead # of +save+, so an exception is raised if the record is invalid. - def update_attributes!(attributes) + def update!(attributes) # The following transaction covers any possible database side-effects of the # attributes assignment. For example, setting the IDs of a child collection. with_transaction_returning_status do @@ -231,6 +233,8 @@ module ActiveRecord save! end end + + alias update_attributes! update! # Updates a single attribute of an object, without having to explicitly call save on that object. # @@ -406,13 +410,13 @@ module ActiveRecord def create_or_update raise ReadOnlyRecord if readonly? - result = new_record? ? create : update + result = new_record? ? create_record : update_record result != false end # Updates the associated record with values matching those of the instance attributes. # Returns the number of affected rows. - def update(attribute_names = @attributes.keys) + def update_record(attribute_names = @attributes.keys) attributes_with_values = arel_attributes_with_values_for_update(attribute_names) if attributes_with_values.empty? @@ -426,7 +430,7 @@ module ActiveRecord # Creates a record with values matching those of the instance attributes # and returns its id. - def create(attribute_names = @attributes.keys) + def create_record(attribute_names = @attributes.keys) attributes_values = arel_attributes_with_values_for_create(attribute_names) new_id = self.class.unscoped.insert attributes_values diff --git a/activerecord/lib/active_record/railtie.rb b/activerecord/lib/active_record/railtie.rb index 1081b82bc6..aceb70bc45 100644 --- a/activerecord/lib/active_record/railtie.rb +++ b/activerecord/lib/active_record/railtie.rb @@ -112,7 +112,7 @@ module ActiveRecord `config/application.rb` file and any `mass_assignment_sanitizer` options from your `config/environments/*.rb` files. - See http://edgeguides.rubyonrails.org/security.html#mass-assignment for more information + See http://guides.rubyonrails.org/security.html#mass-assignment for more information EOF end @@ -124,7 +124,7 @@ module ActiveRecord To disable this message remove the `observers` option from your `config/application.rb` or from your initializers. - See http://edgeguides.rubyonrails.org/4_0_release_notes.html for more information + See http://guides.rubyonrails.org/4_0_release_notes.html for more information EOF end ensure diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index b25c0270c2..259d0ff12b 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -300,7 +300,9 @@ db_namespace = namespace :db do end if ActiveRecord::Base.connection.supports_migrations? - File.open(filename, "a") { |f| f << ActiveRecord::Base.connection.dump_schema_information } + File.open(filename, "a") do |f| + f.puts ActiveRecord::Base.connection.dump_schema_information + end end db_namespace['structure:dump'].reenable end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index 0df895eb67..6ec5cf3e18 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -308,7 +308,7 @@ module ActiveRecord id.map.with_index { |one_id, idx| update(one_id, attributes[idx]) } else object = find(id) - object.update_attributes(attributes) + object.update(attributes) object end end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index ccc14dddeb..3f154bd1cc 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -1,5 +1,3 @@ -require 'active_support/deprecation' - module ActiveRecord module Calculations # Count the records. @@ -231,6 +229,8 @@ module ActiveRecord # Postgresql doesn't like ORDER BY when there are no GROUP BY relation = reorder(nil) + column_alias = column_name + if operation == "count" && (relation.limit_value || relation.offset_value) # Shortcut when limit is zero. return 0 if relation.limit_value == 0 @@ -241,13 +241,20 @@ module ActiveRecord select_value = operation_over_aggregate_column(column, operation, distinct) + column_alias = select_value.alias relation.select_values = [select_value] query_builder = relation.arel end - result = @klass.connection.select_value(query_builder, nil, relation.bind_values) - type_cast_calculated_value(result, column_for(column_name), operation) + result = @klass.connection.select_all(query_builder, nil, relation.bind_values) + row = result.first + value = row && row.values.first + column = result.column_types.fetch(column_alias) do + column_for(column_name) + end + + type_cast_calculated_value(value, column, operation) end def execute_grouped_calculation(operation, column_name, distinct) #:nodoc: @@ -265,7 +272,7 @@ module ActiveRecord column_alias_for(field) } group_columns = group_aliases.zip(group_fields).map { |aliaz,field| - [aliaz, column_for(field)] + [aliaz, field] } group = group_fields @@ -305,7 +312,10 @@ module ActiveRecord end Hash[calculated_data.map do |row| - key = group_columns.map { |aliaz, column| + key = group_columns.map { |aliaz, col_name| + column = calculated_data.column_types.fetch(aliaz) do + column_for(col_name) + end type_cast_calculated_value(row[aliaz], column) } key = key.first if key.size == 1 diff --git a/activerecord/lib/active_record/relation/delegation.rb b/activerecord/lib/active_record/relation/delegation.rb index 431d083f21..615309964c 100644 --- a/activerecord/lib/active_record/relation/delegation.rb +++ b/activerecord/lib/active_record/relation/delegation.rb @@ -1,4 +1,3 @@ -require 'active_support/concern' require 'thread' require 'thread_safe' diff --git a/activerecord/lib/active_record/relation/spawn_methods.rb b/activerecord/lib/active_record/relation/spawn_methods.rb index d417e82548..de784f9f57 100644 --- a/activerecord/lib/active_record/relation/spawn_methods.rb +++ b/activerecord/lib/active_record/relation/spawn_methods.rb @@ -50,10 +50,7 @@ module ActiveRecord # Post.order('id asc').except(:order) # discards the order condition # Post.where('id > 10').order('id asc').except(:where) # discards the where condition but keeps the order def except(*skips) - result = Relation.new(klass, table, values.except(*skips)) - result.default_scoped = default_scoped - result.extend(*extending_values) if extending_values.any? - result + relation_with values.except(*skips) end # Removes any condition from the query other than the one(s) specified in +onlies+. @@ -61,11 +58,16 @@ module ActiveRecord # Post.order('id asc').only(:where) # discards the order condition # Post.order('id asc').only(:where, :order) # uses the specified order def only(*onlies) - result = Relation.new(klass, table, values.slice(*onlies)) - result.default_scoped = default_scoped - result.extend(*extending_values) if extending_values.any? - result + relation_with values.slice(*onlies) end + private + + def relation_with(values) # :nodoc: + result = Relation.new(klass, table, values) + result.default_scoped = default_scoped + result.extend(*extending_values) if extending_values.any? + result + end end end diff --git a/activerecord/lib/active_record/scoping/named.rb b/activerecord/lib/active_record/scoping/named.rb index 8b7eda6eee..01fbb96b8e 100644 --- a/activerecord/lib/active_record/scoping/named.rb +++ b/activerecord/lib/active_record/scoping/named.rb @@ -134,16 +134,14 @@ module ActiveRecord # end # # def self.titles - # map(&:title) + # pluck(:title) # end - # # end # # We are able to call the methods like this: # # Article.published.featured.latest_article # Article.featured.titles - def scope(name, body, &block) extension = Module.new(&block) if block diff --git a/activerecord/lib/active_record/store.rb b/activerecord/lib/active_record/store.rb index df7f58c81f..cf4cf9e602 100644 --- a/activerecord/lib/active_record/store.rb +++ b/activerecord/lib/active_record/store.rb @@ -107,7 +107,7 @@ module ActiveRecord private def initialize_store_attribute(store_attribute) attribute = send(store_attribute) - unless attribute.is_a?(HashWithIndifferentAccess) + unless attribute.is_a?(ActiveSupport::HashWithIndifferentAccess) attribute = IndifferentCoder.as_indifferent_hash(attribute) send :"#{store_attribute}=", attribute end @@ -134,12 +134,12 @@ module ActiveRecord def self.as_indifferent_hash(obj) case obj - when HashWithIndifferentAccess + when ActiveSupport::HashWithIndifferentAccess obj when Hash obj.with_indifferent_access else - HashWithIndifferentAccess.new + ActiveSupport::HashWithIndifferentAccess.new end end end diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index cf17b1d8a4..8ded6d4a86 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -43,7 +43,7 @@ module ActiveRecord private - def create + def create_record if self.record_timestamps current_time = current_time_from_proper_timezone @@ -57,7 +57,7 @@ module ActiveRecord super end - def update(*args) + def update_record(*args) if should_record_timestamps? current_time = current_time_from_proper_timezone diff --git a/activerecord/test/cases/adapters/mysql/active_schema_test.rb b/activerecord/test/cases/adapters/mysql/active_schema_test.rb index 94fc3564df..8812cf1b7d 100644 --- a/activerecord/test/cases/adapters/mysql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/mysql/active_schema_test.rb @@ -42,7 +42,7 @@ class ActiveSchemaTest < ActiveRecord::TestCase assert_equal "DROP TABLE `people`", drop_table(:people) end - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + if current_adapter?(:MysqlAdapter, :Mysql2Adapter) def test_create_mysql_database_with_encoding assert_equal "CREATE DATABASE `matt` DEFAULT CHARACTER SET `utf8`", create_database(:matt) assert_equal "CREATE DATABASE `aimonetti` DEFAULT CHARACTER SET `latin1`", create_database(:aimonetti, {:charset => 'latin1'}) diff --git a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb b/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb index ddfe42b375..0eb1cc511e 100644 --- a/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb +++ b/activerecord/test/cases/adapters/mysql/mysql_adapter_test.rb @@ -49,13 +49,11 @@ module ActiveRecord end def test_tables_quoting - begin - @conn.tables(nil, "foo-bar", nil) - flunk - rescue => e - # assertion for *quoted* database properly - assert_match(/database 'foo-bar'/, e.inspect) - end + @conn.tables(nil, "foo-bar", nil) + flunk + rescue => e + # assertion for *quoted* database properly + assert_match(/database 'foo-bar'/, e.inspect) end def test_pk_and_sequence_for diff --git a/activerecord/test/cases/adapters/mysql2/schema_test.rb b/activerecord/test/cases/adapters/mysql2/schema_test.rb index 2c0ed73c92..94429e772f 100644 --- a/activerecord/test/cases/adapters/mysql2/schema_test.rb +++ b/activerecord/test/cases/adapters/mysql2/schema_test.rb @@ -37,13 +37,11 @@ module ActiveRecord end def test_tables_quoting - begin - @connection.tables(nil, "foo-bar", nil) - flunk - rescue => e - # assertion for *quoted* database properly - assert_match(/database 'foo-bar'/, e.inspect) - end + @connection.tables(nil, "foo-bar", nil) + flunk + rescue => e + # assertion for *quoted* database properly + assert_match(/database 'foo-bar'/, e.inspect) end end diff --git a/activerecord/test/cases/adapters/postgresql/datatype_test.rb b/activerecord/test/cases/adapters/postgresql/datatype_test.rb index c7ce43d71e..2254be8612 100644 --- a/activerecord/test/cases/adapters/postgresql/datatype_test.rb +++ b/activerecord/test/cases/adapters/postgresql/datatype_test.rb @@ -30,6 +30,9 @@ end class PostgresqlUUID < ActiveRecord::Base end +class PostgresqlLtree < ActiveRecord::Base +end + class PostgresqlDataTypeTest < ActiveRecord::TestCase self.use_transactional_fixtures = false @@ -37,38 +40,43 @@ class PostgresqlDataTypeTest < ActiveRecord::TestCase @connection = ActiveRecord::Base.connection @connection.execute("set lc_monetary = 'C'") - @connection.execute("INSERT INTO postgresql_arrays (commission_by_quarter, nicknames) VALUES ( '{35000,21000,18000,17000}', '{foo,bar,baz}' )") + @connection.execute("INSERT INTO postgresql_arrays (id, commission_by_quarter, nicknames) VALUES (1, '{35000,21000,18000,17000}', '{foo,bar,baz}')") @first_array = PostgresqlArray.find(1) - @connection.execute("INSERT INTO postgresql_tsvectors (text_vector) VALUES (' ''text'' ''vector'' ')") + @connection.execute("INSERT INTO postgresql_tsvectors (id, text_vector) VALUES (1, ' ''text'' ''vector'' ')") @first_tsvector = PostgresqlTsvector.find(1) - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('567.89'::money)") - @connection.execute("INSERT INTO postgresql_moneys (wealth) VALUES ('-567.89'::money)") + @connection.execute("INSERT INTO postgresql_moneys (id, wealth) VALUES (1, '567.89'::money)") + @connection.execute("INSERT INTO postgresql_moneys (id, wealth) VALUES (2, '-567.89'::money)") @first_money = PostgresqlMoney.find(1) @second_money = PostgresqlMoney.find(2) - @connection.execute("INSERT INTO postgresql_numbers (single, double) VALUES (123.456, 123456.789)") + @connection.execute("INSERT INTO postgresql_numbers (id, single, double) VALUES (1, 123.456, 123456.789)") @first_number = PostgresqlNumber.find(1) - @connection.execute("INSERT INTO postgresql_times (time_interval, scaled_time_interval) VALUES ('1 year 2 days ago', '3 weeks ago')") + @connection.execute("INSERT INTO postgresql_times (id, time_interval, scaled_time_interval) VALUES (1, '1 year 2 days ago', '3 weeks ago')") @first_time = PostgresqlTime.find(1) - @connection.execute("INSERT INTO postgresql_network_addresses (cidr_address, inet_address, mac_address) VALUES('192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')") + @connection.execute("INSERT INTO postgresql_network_addresses (id, cidr_address, inet_address, mac_address) VALUES(1, '192.168.0/24', '172.16.1.254/32', '01:23:45:67:89:0a')") @first_network_address = PostgresqlNetworkAddress.find(1) - @connection.execute("INSERT INTO postgresql_bit_strings (bit_string, bit_string_varying) VALUES (B'00010101', X'15')") + @connection.execute("INSERT INTO postgresql_bit_strings (id, bit_string, bit_string_varying) VALUES (1, B'00010101', X'15')") @first_bit_string = PostgresqlBitString.find(1) - @connection.execute("INSERT INTO postgresql_oids (obj_id) VALUES (1234)") + @connection.execute("INSERT INTO postgresql_oids (id, obj_id) VALUES (1, 1234)") @first_oid = PostgresqlOid.find(1) - @connection.execute("INSERT INTO postgresql_timestamp_with_zones (time) VALUES ('2010-01-01 10:00:00-1')") + @connection.execute("INSERT INTO postgresql_timestamp_with_zones (id, time) VALUES (1, '2010-01-01 10:00:00-1')") - @connection.execute("INSERT INTO postgresql_uuids (guid, compact_guid) VALUES('d96c3da0-96c1-012f-1316-64ce8f32c6d8', 'f06c715096c1012f131764ce8f32c6d8')") + @connection.execute("INSERT INTO postgresql_uuids (id, guid, compact_guid) VALUES(1, 'd96c3da0-96c1-012f-1316-64ce8f32c6d8', 'f06c715096c1012f131764ce8f32c6d8')") @first_uuid = PostgresqlUUID.find(1) end + def teardown + [PostgresqlArray, PostgresqlTsvector, PostgresqlMoney, PostgresqlNumber, PostgresqlTime, PostgresqlNetworkAddress, + PostgresqlBitString, PostgresqlOid, PostgresqlTimestampWithZone, PostgresqlUUID].each(&:delete_all) + end + def test_data_type_of_array_types assert_equal :integer, @first_array.column_for_attribute(:commission_by_quarter).type assert_equal :text, @first_array.column_for_attribute(:nicknames).type diff --git a/activerecord/test/cases/adapters/postgresql/ltree_test.rb b/activerecord/test/cases/adapters/postgresql/ltree_test.rb new file mode 100644 index 0000000000..5d12ca75ca --- /dev/null +++ b/activerecord/test/cases/adapters/postgresql/ltree_test.rb @@ -0,0 +1,41 @@ +# encoding: utf-8 +require "cases/helper" +require 'active_record/base' +require 'active_record/connection_adapters/postgresql_adapter' + +class PostgresqlLtreeTest < ActiveRecord::TestCase + class Ltree < ActiveRecord::Base + self.table_name = 'ltrees' + end + + def setup + @connection = ActiveRecord::Base.connection + @connection.transaction do + @connection.create_table('ltrees') do |t| + t.ltree 'path' + end + end + rescue ActiveRecord::StatementInvalid + skip "do not test on PG without ltree" + end + + def teardown + @connection.execute 'drop table if exists ltrees' + end + + def test_column + column = Ltree.columns_hash['path'] + assert_equal :ltree, column.type + end + + def test_write + ltree = Ltree.new(path: '1.2.3.4') + assert ltree.save! + end + + def test_select + @connection.execute "insert into ltrees (path) VALUES ('1.2.3')" + ltree = Ltree.first + assert_equal '1.2.3', ltree.path + end +end diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index 630bdeec67..dbc69a529c 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -1,7 +1,16 @@ require 'cases/helper' require 'models/developer' +require 'models/topic' class TimestampTest < ActiveRecord::TestCase + fixtures :topics + + def test_group_by_date + keys = Topic.group("date_trunc('month', created_at)").count.keys + assert_operator keys.length, :>, 0 + keys.each { |k| assert_kind_of Time, k } + end + def test_load_infinity_and_beyond unless current_adapter?(:PostgreSQLAdapter) return skip("only tested on postgresql") diff --git a/activerecord/test/cases/aggregations_test.rb b/activerecord/test/cases/aggregations_test.rb index 48b06a767f..10195e3ae4 100644 --- a/activerecord/test/cases/aggregations_test.rb +++ b/activerecord/test/cases/aggregations_test.rb @@ -1,6 +1,5 @@ require "cases/helper" require 'models/customer' -require 'active_support/core_ext/exception' class AggregationsTest < ActiveRecord::TestCase fixtures :customers @@ -26,7 +25,7 @@ class AggregationsTest < ActiveRecord::TestCase def test_immutable_value_objects customers(:david).balance = Money.new(100) - assert_raise(ActiveSupport::FrozenObjectError) { customers(:david).balance.instance_eval { @amount = 20 } } + assert_raise(RuntimeError) { customers(:david).balance.instance_eval { @amount = 20 } } end def test_inferred_mapping diff --git a/activerecord/test/cases/ar_schema_test.rb b/activerecord/test/cases/ar_schema_test.rb index b2eac0349b..aa5b27623e 100644 --- a/activerecord/test/cases/ar_schema_test.rb +++ b/activerecord/test/cases/ar_schema_test.rb @@ -7,6 +7,7 @@ if ActiveRecord::Base.connection.supports_migrations? def setup @connection = ActiveRecord::Base.connection + ActiveRecord::SchemaMigration.drop_table end def teardown @@ -45,5 +46,4 @@ if ActiveRecord::Base.connection.supports_migrations? assert_nothing_raised { @connection.select_all "SELECT * FROM fruits" } end end - end diff --git a/activerecord/test/cases/associations/belongs_to_associations_test.rb b/activerecord/test/cases/associations/belongs_to_associations_test.rb index 04d0f755b6..3a6da0e59f 100644 --- a/activerecord/test/cases/associations/belongs_to_associations_test.rb +++ b/activerecord/test/cases/associations/belongs_to_associations_test.rb @@ -33,7 +33,7 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase def test_belongs_to_with_primary_key_joins_on_correct_column sql = Client.joins(:firm_with_primary_key).to_sql - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + if current_adapter?(:MysqlAdapter, :Mysql2Adapter) assert_no_match(/`firm_with_primary_keys_companies`\.`id`/, sql) assert_match(/`firm_with_primary_keys_companies`\.`name`/, sql) elsif current_adapter?(:OracleAdapter) @@ -63,6 +63,13 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal apple.id, citibank.firm_id end + def test_id_assignment + apple = Firm.create("name" => "Apple") + citibank = Account.create("credit_limit" => 10) + citibank.firm_id = apple + assert_nil citibank.firm_id + end + def test_natural_assignment_with_primary_key apple = Firm.create("name" => "Apple") citibank = Client.create("name" => "Primary key client") @@ -317,12 +324,12 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal 1, Topic.find(topic.id)[:replies_count] end - def test_belongs_to_counter_after_update_attributes - topic = Topic.create!(:title => "37s") - topic.replies.create!(:title => "re: 37s", :content => "rails") + def test_belongs_to_counter_after_update + topic = Topic.create!(title: "37s") + topic.replies.create!(title: "re: 37s", content: "rails") assert_equal 1, Topic.find(topic.id)[:replies_count] - topic.update_attributes(:title => "37signals") + topic.update(title: "37signals") assert_equal 1, Topic.find(topic.id)[:replies_count] end @@ -567,6 +574,11 @@ class BelongsToAssociationsTest < ActiveRecord::TestCase assert_equal new_firm.name, "Apple" end + def test_attributes_are_set_without_error_when_initialized_from_belongs_to_association_with_array_in_where_clause + new_account = Account.where(:credit_limit => [ 50, 60 ]).new + assert_nil new_account.credit_limit + end + def test_reassigning_the_parent_id_updates_the_object client = companies(:second_client) diff --git a/activerecord/test/cases/associations/eager_test.rb b/activerecord/test/cases/associations/eager_test.rb index 94437380a4..be2d30641e 100644 --- a/activerecord/test/cases/associations/eager_test.rb +++ b/activerecord/test/cases/associations/eager_test.rb @@ -93,31 +93,31 @@ class EagerAssociationTest < ActiveRecord::TestCase end def test_preloading_has_many_in_multiple_queries_with_more_ids_than_database_can_handle - Post.connection.expects(:in_clause_length).at_least_once.returns(5) + Comment.connection.expects(:in_clause_length).at_least_once.returns(5) posts = Post.all.merge!(:includes=>:comments).to_a assert_equal 11, posts.size end def test_preloading_has_many_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle - Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + Comment.connection.expects(:in_clause_length).at_least_once.returns(nil) posts = Post.all.merge!(:includes=>:comments).to_a assert_equal 11, posts.size end def test_preloading_habtm_in_multiple_queries_with_more_ids_than_database_can_handle - Post.connection.expects(:in_clause_length).at_least_once.returns(5) + Comment.connection.expects(:in_clause_length).at_least_once.returns(5) posts = Post.all.merge!(:includes=>:categories).to_a assert_equal 11, posts.size end def test_preloading_habtm_in_one_queries_when_database_has_no_limit_on_ids_it_can_handle - Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + Comment.connection.expects(:in_clause_length).at_least_once.returns(nil) posts = Post.all.merge!(:includes=>:categories).to_a assert_equal 11, posts.size end def test_load_associated_records_in_one_query_when_adapter_has_no_limit - Post.connection.expects(:in_clause_length).at_least_once.returns(nil) + Comment.connection.expects(:in_clause_length).at_least_once.returns(nil) post = posts(:welcome) assert_queries(2) do @@ -126,7 +126,7 @@ class EagerAssociationTest < ActiveRecord::TestCase end def test_load_associated_records_in_several_queries_when_many_ids_passed - Post.connection.expects(:in_clause_length).at_least_once.returns(1) + Comment.connection.expects(:in_clause_length).at_least_once.returns(1) post1, post2 = posts(:welcome), posts(:thinking) assert_queries(3) do @@ -135,7 +135,7 @@ class EagerAssociationTest < ActiveRecord::TestCase end def test_load_associated_records_in_one_query_when_a_few_ids_passed - Post.connection.expects(:in_clause_length).at_least_once.returns(3) + Comment.connection.expects(:in_clause_length).at_least_once.returns(3) post = posts(:welcome) assert_queries(2) do @@ -212,8 +212,9 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_finding_with_includes_on_null_belongs_to_association_with_same_include_includes_only_once post = posts(:welcome) - post.update_attributes!(:author => nil) - post = assert_queries(1) { Post.all.merge!(:includes => {:author_with_address => :author_address}).find(post.id) } # find the post, then find the author which is null so no query for the author or address + post.update!(author: nil) + post = assert_queries(1) { Post.all.merge!(includes: {author_with_address: :author_address}).find(post.id) } + # find the post, then find the author which is null so no query for the author or address assert_no_queries do assert_equal nil, post.author_with_address end @@ -221,7 +222,7 @@ class EagerAssociationTest < ActiveRecord::TestCase def test_finding_with_includes_on_null_belongs_to_polymorphic_association sponsor = sponsors(:moustache_club_sponsor_for_groucho) - sponsor.update_attributes!(:sponsorable => nil) + sponsor.update!(sponsorable: nil) sponsor = assert_queries(1) { Sponsor.all.merge!(:includes => :sponsorable).find(sponsor.id) } assert_no_queries do assert_equal nil, sponsor.sponsorable diff --git a/activerecord/test/cases/associations/has_many_through_associations_test.rb b/activerecord/test/cases/associations/has_many_through_associations_test.rb index 2b96b42032..af91fb2920 100644 --- a/activerecord/test/cases/associations/has_many_through_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_through_associations_test.rb @@ -706,7 +706,7 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase def test_can_update_through_association assert_nothing_raised do - people(:michael).posts.first.update_attributes!(:title => "Can write") + people(:michael).posts.first.update!(title: "Can write") end end diff --git a/activerecord/test/cases/associations/join_model_test.rb b/activerecord/test/cases/associations/join_model_test.rb index 9b00c21b52..10ec33be75 100644 --- a/activerecord/test/cases/associations/join_model_test.rb +++ b/activerecord/test/cases/associations/join_model_test.rb @@ -443,8 +443,8 @@ class AssociationsJoinModelTest < ActiveRecord::TestCase def test_has_many_through_uses_conditions_specified_on_the_has_many_association author = Author.first - assert_present author.comments - assert_blank author.nonexistant_comments + assert author.comments.present? + assert author.nonexistant_comments.blank? end def test_has_many_through_uses_correct_attributes diff --git a/activerecord/test/cases/autosave_association_test.rb b/activerecord/test/cases/autosave_association_test.rb index 16ce150396..e5cb4f8f7a 100644 --- a/activerecord/test/cases/autosave_association_test.rb +++ b/activerecord/test/cases/autosave_association_test.rb @@ -161,16 +161,16 @@ class TestDefaultAutosaveAssociationOnAHasOneAssociation < ActiveRecord::TestCas end def test_callbacks_firing_order_on_update - eye = Eye.create(:iris_attributes => {:color => 'honey'}) - eye.update_attributes(:iris_attributes => {:color => 'green'}) + eye = Eye.create(iris_attributes: {color: 'honey'}) + eye.update(iris_attributes: {color: 'green'}) assert_equal [true, false], eye.after_update_callbacks_stack end def test_callbacks_firing_order_on_save - eye = Eye.create(:iris_attributes => {:color => 'honey'}) + eye = Eye.create(iris_attributes: {color: 'honey'}) assert_equal [false, false], eye.after_save_callbacks_stack - eye.update_attributes(:iris_attributes => {:color => 'blue'}) + eye.update(iris_attributes: {color: 'blue'}) assert_equal [false, false, false, false], eye.after_save_callbacks_stack end end diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index d326ed7863..4f46459ab3 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -26,7 +26,6 @@ require 'models/bird' require 'models/car' require 'models/bulb' require 'rexml/document' -require 'active_support/core_ext/exception' class FirstAbstractClass < ActiveRecord::Base self.abstract_class = true @@ -125,7 +124,7 @@ class BasicsTest < ActiveRecord::TestCase assert_nil Edge.primary_key end - unless current_adapter?(:PostgreSQLAdapter,:OracleAdapter,:SQLServerAdapter) + unless current_adapter?(:PostgreSQLAdapter, :OracleAdapter, :SQLServerAdapter) def test_limit_with_comma assert Topic.limit("1,2").to_a end @@ -154,7 +153,7 @@ class BasicsTest < ActiveRecord::TestCase end end - unless current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) + unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) def test_limit_should_allow_sql_literal assert_equal 1, Topic.limit(Arel.sql('2-1')).to_a.length end @@ -223,7 +222,7 @@ class BasicsTest < ActiveRecord::TestCase ) # For adapters which support microsecond resolution. - if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:SQLite3Adapter) + if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter) assert_equal 11, Topic.find(1).written_on.sec assert_equal 223300, Topic.find(1).written_on.usec assert_equal 9900, Topic.find(2).written_on.usec @@ -301,13 +300,11 @@ class BasicsTest < ActiveRecord::TestCase end def test_initialize_with_invalid_attribute - begin - Topic.new({ "title" => "test", - "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"}) - rescue ActiveRecord::MultiparameterAssignmentErrors => ex - assert_equal(1, ex.errors.size) - assert_equal("last_read", ex.errors[0].attribute) - end + Topic.new({ "title" => "test", + "last_read(1i)" => "2005", "last_read(2i)" => "2", "last_read(3i)" => "31"}) + rescue ActiveRecord::MultiparameterAssignmentErrors => ex + assert_equal(1, ex.errors.size) + assert_equal("last_read", ex.errors[0].attribute) end def test_create_after_initialize_without_block @@ -472,7 +469,7 @@ class BasicsTest < ActiveRecord::TestCase Post.reset_table_name end - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + if current_adapter?(:MysqlAdapter, :Mysql2Adapter) def test_update_all_with_order_and_limit assert_equal 1, Topic.limit(1).order('id DESC').update_all(:content => 'bulk updated!') end @@ -594,7 +591,7 @@ class BasicsTest < ActiveRecord::TestCase post.reload assert_equal "cannot change this", post.title - post.update_attributes(:title => "try to change", :body => "changed") + post.update(title: "try to change", body: "changed") post.reload assert_equal "cannot change this", post.title assert_equal "changed", post.body @@ -1002,7 +999,7 @@ class BasicsTest < ActiveRecord::TestCase def test_reload_with_exclusive_scope dev = DeveloperCalledDavid.first - dev.update_attributes!( :name => "NotDavid" ) + dev.update!(name: "NotDavid" ) assert_equal dev, dev.reload end @@ -1484,7 +1481,7 @@ class BasicsTest < ActiveRecord::TestCase def test_column_types_typecast topic = Topic.first - refute_equal 't.lo', topic.author_name + assert_not_equal 't.lo', topic.author_name attrs = topic.attributes.dup attrs.delete 'id' diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 5cb7eabf0e..b7622705bf 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -8,6 +8,7 @@ require 'models/possession' require 'models/topic' require 'models/minivan' require 'models/speedometer' +require 'models/ship_part' Company.has_many :accounts @@ -33,8 +34,9 @@ class CalculationsTest < ActiveRecord::TestCase end def test_should_return_integer_average_if_db_returns_such - Account.connection.stubs :select_value => 3 - value = Account.average(:id) + ShipPart.delete_all + ShipPart.create!(:id => 3, :name => 'foo') + value = ShipPart.average(:id) assert_equal 3, value end @@ -416,34 +418,19 @@ class CalculationsTest < ActiveRecord::TestCase def test_maximum_with_not_auto_table_name_prefix_if_column_included Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)]) - # TODO: Investigate why PG isn't being typecast - if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:MysqlAdapter) - assert_equal "7", Company.includes(:contracts).maximum(:developer_id) - else - assert_equal 7, Company.includes(:contracts).maximum(:developer_id) - end + assert_equal 7, Company.includes(:contracts).maximum(:developer_id) end def test_minimum_with_not_auto_table_name_prefix_if_column_included Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)]) - # TODO: Investigate why PG isn't being typecast - if current_adapter?(:PostgreSQLAdapter) || current_adapter?(:MysqlAdapter) - assert_equal "7", Company.includes(:contracts).minimum(:developer_id) - else - assert_equal 7, Company.includes(:contracts).minimum(:developer_id) - end + assert_equal 7, Company.includes(:contracts).minimum(:developer_id) end def test_sum_with_not_auto_table_name_prefix_if_column_included Company.create!(:name => "test", :contracts => [Contract.new(:developer_id => 7)]) - # TODO: Investigate why PG isn't being typecast - if current_adapter?(:MysqlAdapter) || current_adapter?(:PostgreSQLAdapter) - assert_equal "7", Company.includes(:contracts).sum(:developer_id) - else - assert_equal 7, Company.includes(:contracts).sum(:developer_id) - end + assert_equal 7, Company.includes(:contracts).sum(:developer_id) end diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb index 2124c256fa..adbe51f430 100644 --- a/activerecord/test/cases/column_test.rb +++ b/activerecord/test/cases/column_test.rb @@ -1,4 +1,5 @@ require "cases/helper" +require 'models/company' module ActiveRecord module ConnectionAdapters @@ -40,13 +41,26 @@ module ActiveRecord def test_type_cast_non_integer_to_integer column = Column.new("field", nil, "integer") - assert_raises(NoMethodError) do - column.type_cast([]) - end + assert_nil column.type_cast([1,2]) + assert_nil column.type_cast({1 => 2}) + assert_nil column.type_cast((1..2)) + end - assert_raises(NoMethodError) do - column.type_cast(Object.new) - end + def test_type_cast_activerecord_to_integer + column = Column.new("field", nil, "integer") + firm = Firm.create(:name => 'Apple') + assert_nil column.type_cast(firm) + end + + def test_type_cast_object_without_to_i_to_integer + column = Column.new("field", nil, "integer") + assert_nil column.type_cast(Object.new) + end + + def test_type_cast_nan_and_infinity_to_integer + column = Column.new("field", nil, "integer") + assert_nil column.type_cast(Float::NAN) + assert_nil column.type_cast(1.0/0.0) end def test_type_cast_time diff --git a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb index 1eb9bf60e1..1fd64dd0af 100644 --- a/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb +++ b/activerecord/test/cases/connection_adapters/abstract_adapter_test.rb @@ -10,18 +10,18 @@ module ActiveRecord end def test_in_use? - refute adapter.in_use?, 'adapter is not in use' + assert_not adapter.in_use?, 'adapter is not in use' assert adapter.lease, 'lease adapter' assert adapter.in_use?, 'adapter is in use' end def test_lease_twice assert adapter.lease, 'should lease adapter' - refute adapter.lease, 'should not lease adapter' + assert_not adapter.lease, 'should not lease adapter' end def test_last_use - refute adapter.last_use + assert_not adapter.last_use adapter.lease assert adapter.last_use end @@ -30,7 +30,7 @@ module ActiveRecord assert adapter.lease, 'lease adapter' assert adapter.in_use?, 'adapter is in use' adapter.expire - refute adapter.in_use?, 'adapter is in use' + assert_not adapter.in_use?, 'adapter is in use' end def test_close @@ -44,7 +44,7 @@ module ActiveRecord # Close should put the adapter back in the pool adapter.close - refute adapter.in_use? + assert_not adapter.in_use? assert_equal adapter, pool.connection end diff --git a/activerecord/test/cases/connection_specification/resolver_test.rb b/activerecord/test/cases/connection_specification/resolver_test.rb index ee9818678d..52de0efe7f 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 current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :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 current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :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 current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) spec = resolve 'mysql://foo:123?encoding=utf8' assert_equal({ :adapter => "mysql", @@ -38,7 +38,7 @@ module ActiveRecord end def test_encoded_password - skip "only if mysql is available" unless current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + skip "only if mysql is available" unless current_adapter?(:MysqlAdapter, :Mysql2Adapter) password = 'am@z1ng_p@ssw0rd#!' encoded_password = URI.encode_www_form_component(password) spec = resolve "mysql://foo:#{encoded_password}@localhost/bar" diff --git a/activerecord/test/cases/defaults_test.rb b/activerecord/test/cases/defaults_test.rb index ed7eedaa27..e0cf4adf13 100644 --- a/activerecord/test/cases/defaults_test.rb +++ b/activerecord/test/cases/defaults_test.rb @@ -39,7 +39,7 @@ class DefaultTest < ActiveRecord::TestCase end end -if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) +if current_adapter?(:MysqlAdapter, :Mysql2Adapter) class DefaultsTestWithoutTransactionalFixtures < ActiveRecord::TestCase # ActiveRecord::Base#create! (and #save and other related methods) will # open a new transaction. When in transactional fixtures mode, this will diff --git a/activerecord/test/cases/deprecated_dynamic_methods_test.rb b/activerecord/test/cases/deprecated_dynamic_methods_test.rb index dde36e7f72..8e842d8758 100644 --- a/activerecord/test/cases/deprecated_dynamic_methods_test.rb +++ b/activerecord/test/cases/deprecated_dynamic_methods_test.rb @@ -1,7 +1,7 @@ # This file should be deleted when activerecord-deprecated_finders is removed as # a dependency. # -# It is kept for now as there is some fairly nuanced behaviour in the dynamic +# It is kept for now as there is some fairly nuanced behavior in the dynamic # finders so it is useful to keep this around to guard against regressions if # we need to change the code. @@ -568,9 +568,9 @@ class DynamicScopeTest < ActiveRecord::TestCase end def test_dynamic_scope_should_create_methods_after_hitting_method_missing - assert_blank @test_klass.methods.grep(/scoped_by_type/) + assert @test_klass.methods.grep(/scoped_by_type/).blank? @test_klass.scoped_by_type(nil) - assert_present @test_klass.methods.grep(/scoped_by_type/) + assert @test_klass.methods.grep(/scoped_by_type/).present? end def test_dynamic_scope_with_less_number_of_arguments diff --git a/activerecord/test/cases/dirty_test.rb b/activerecord/test/cases/dirty_test.rb index 55ee066cda..b9961a4420 100644 --- a/activerecord/test/cases/dirty_test.rb +++ b/activerecord/test/cases/dirty_test.rb @@ -517,7 +517,7 @@ class DirtyTest < ActiveRecord::TestCase assert !pirate.previous_changes.key?('created_on') pirate = Pirate.find_by_catchphrase("Thar She Blows!") - pirate.update_attributes(:catchphrase => "Ahoy!") + pirate.update(catchphrase: "Ahoy!") assert_equal 2, pirate.previous_changes.size assert_equal ["Thar She Blows!", "Ahoy!"], pirate.previous_changes['catchphrase'] diff --git a/activerecord/test/cases/explain_test.rb b/activerecord/test/cases/explain_test.rb index a7e5fdf709..aa2a6d7509 100644 --- a/activerecord/test/cases/explain_test.rb +++ b/activerecord/test/cases/explain_test.rb @@ -122,7 +122,7 @@ if ActiveRecord::Base.connection.supports_explain? base.expects(:collecting_sqls_for_explain).never base.logger.expects(:warn).never base.silence_auto_explain do - with_threshold(0) { Car.all } + with_threshold(0) { Car.all.to_a } end end diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index 7db7953313..a9fa107749 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -15,6 +15,18 @@ require 'models/toy' class FinderTest < ActiveRecord::TestCase fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers, :categories, :categorizations + def test_find_by_id_with_hash + assert_raises(ActiveRecord::StatementInvalid) do + Post.find_by_id(:limit => 1) + end + end + + def test_find_by_title_and_id_with_hash + assert_raises(ActiveRecord::StatementInvalid) do + Post.find_by_title_and_id('foo', :limit => 1) + end + end + def test_find assert_equal(topics(:first).title, Topic.find(1).title) end diff --git a/activerecord/test/cases/helper.rb b/activerecord/test/cases/helper.rb index 3a315d843b..5ffb32e809 100644 --- a/activerecord/test/cases/helper.rb +++ b/activerecord/test/cases/helper.rb @@ -2,8 +2,7 @@ require File.expand_path('../../../../load_paths', __FILE__) require 'config' -gem 'minitest' -require 'minitest/autorun' +require 'active_support/testing/autorun' require 'stringio' require 'active_record' diff --git a/activerecord/test/cases/locking_test.rb b/activerecord/test/cases/locking_test.rb index 2392516395..a0a3e6cb0d 100644 --- a/activerecord/test/cases/locking_test.rb +++ b/activerecord/test/cases/locking_test.rb @@ -207,7 +207,7 @@ class OptimisticLockingTest < ActiveRecord::TestCase s.reload assert_equal "unchangeable name", s.name - s.update_attributes(:name => "changed name") + s.update(name: "changed name") s.reload assert_equal "unchangeable name", s.name end diff --git a/activerecord/test/cases/log_subscriber_test.rb b/activerecord/test/cases/log_subscriber_test.rb index 345e83a102..57eac0c175 100644 --- a/activerecord/test/cases/log_subscriber_test.rb +++ b/activerecord/test/cases/log_subscriber_test.rb @@ -8,6 +8,19 @@ class LogSubscriberTest < ActiveRecord::TestCase include ActiveSupport::LogSubscriber::TestHelper include ActiveSupport::Logger::Severity + class TestDebugLogSubscriber < ActiveRecord::LogSubscriber + attr_reader :debugs + + def initialize + @debugs = [] + super + end + + def debug message + @debugs << message + end + end + fixtures :posts def setup @@ -30,30 +43,27 @@ class LogSubscriberTest < ActiveRecord::TestCase def test_schema_statements_are_ignored event = Struct.new(:duration, :payload) - logger = Class.new(ActiveRecord::LogSubscriber) { - attr_accessor :debugs - - def initialize - @debugs = [] - super - end - - def debug message - @debugs << message - end - }.new + logger = TestDebugLogSubscriber.new assert_equal 0, logger.debugs.length - logger.sql(event.new(0, { :sql => 'hi mom!' })) + logger.sql(event.new(0, sql: 'hi mom!')) assert_equal 1, logger.debugs.length - logger.sql(event.new(0, { :sql => 'hi mom!', :name => 'foo' })) + logger.sql(event.new(0, sql: 'hi mom!', name: 'foo')) assert_equal 2, logger.debugs.length - logger.sql(event.new(0, { :sql => 'hi mom!', :name => 'SCHEMA' })) + logger.sql(event.new(0, sql: 'hi mom!', name: 'SCHEMA')) assert_equal 2, logger.debugs.length end + def test_ignore_binds_payload_with_nil_column + event = Struct.new(:duration, :payload) + + logger = TestDebugLogSubscriber.new + logger.sql(event.new(0, sql: 'hi mom!', binds: [[nil, 1]])) + assert_equal 1, logger.debugs.length + end + def test_basic_query_logging Developer.all.load wait @@ -105,7 +115,7 @@ class LogSubscriberTest < ActiveRecord::TestCase def test_binary_data_is_not_logged skip if current_adapter?(:Mysql2Adapter) - Binary.create(:data => 'some binary data') + Binary.create(data: 'some binary data') wait assert_match(/<16 bytes of binary data>/, @logger.logged(:debug).join) end diff --git a/activerecord/test/cases/migration/change_schema_test.rb b/activerecord/test/cases/migration/change_schema_test.rb index 86451289e7..5ac4a16f33 100644 --- a/activerecord/test/cases/migration/change_schema_test.rb +++ b/activerecord/test/cases/migration/change_schema_test.rb @@ -50,7 +50,7 @@ module ActiveRecord def test_create_table_with_defaults # MySQL doesn't allow defaults on TEXT or BLOB columns. - mysql = current_adapter?(:MysqlAdapter) || current_adapter?(:Mysql2Adapter) + mysql = current_adapter?(:MysqlAdapter, :Mysql2Adapter) connection.create_table :testings do |t| t.column :one, :string, :default => "hello" @@ -99,7 +99,7 @@ module ActiveRecord assert_equal 'smallint', one.sql_type assert_equal 'integer', four.sql_type assert_equal 'bigint', eight.sql_type - elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter) assert_match 'int(11)', default.sql_type assert_match 'tinyint', one.sql_type assert_match 'int', four.sql_type @@ -293,7 +293,7 @@ module ActiveRecord end assert connection.column_exists?(:testings, :foo) - refute connection.column_exists?(:testings, :bar) + assert_not connection.column_exists?(:testings, :bar) end def test_column_exists_with_type @@ -303,10 +303,10 @@ module ActiveRecord end assert connection.column_exists?(:testings, :foo, :string) - refute connection.column_exists?(:testings, :foo, :integer) + assert_not connection.column_exists?(:testings, :foo, :integer) assert connection.column_exists?(:testings, :bar, :decimal) - refute connection.column_exists?(:testings, :bar, :integer) + assert_not connection.column_exists?(:testings, :bar, :integer) end def test_column_exists_with_definition @@ -318,13 +318,13 @@ module ActiveRecord end assert connection.column_exists?(:testings, :foo, :string, limit: 100) - refute connection.column_exists?(:testings, :foo, :string, limit: nil) + assert_not connection.column_exists?(:testings, :foo, :string, limit: nil) assert connection.column_exists?(:testings, :bar, :decimal, precision: 8, scale: 2) - refute connection.column_exists?(:testings, :bar, :decimal, precision: nil, scale: nil) + assert_not connection.column_exists?(:testings, :bar, :decimal, precision: nil, scale: nil) assert connection.column_exists?(:testings, :taggable_id, :integer, null: false) - refute connection.column_exists?(:testings, :taggable_id, :integer, null: true) + assert_not connection.column_exists?(:testings, :taggable_id, :integer, null: true) assert connection.column_exists?(:testings, :taggable_type, :string, default: 'Photo') - refute connection.column_exists?(:testings, :taggable_type, :string, default: nil) + assert_not connection.column_exists?(:testings, :taggable_type, :string, default: nil) end def test_column_exists_on_table_with_no_options_parameter_supplied diff --git a/activerecord/test/cases/migration/change_table_test.rb b/activerecord/test/cases/migration/change_table_test.rb index ac1ad176db..8065541bfe 100644 --- a/activerecord/test/cases/migration/change_table_test.rb +++ b/activerecord/test/cases/migration/change_table_test.rb @@ -1,4 +1,5 @@ require "cases/migration/helper" +require "minitest/mock" module ActiveRecord class Migration diff --git a/activerecord/test/cases/migration/column_attributes_test.rb b/activerecord/test/cases/migration/column_attributes_test.rb index b88db384a0..ec2926632c 100644 --- a/activerecord/test/cases/migration/column_attributes_test.rb +++ b/activerecord/test/cases/migration/column_attributes_test.rb @@ -16,7 +16,7 @@ module ActiveRecord end def test_add_remove_single_field_using_string_arguments - refute TestModel.column_methods_hash.key?(:last_name) + assert_not TestModel.column_methods_hash.key?(:last_name) add_column 'test_models', 'last_name', :string @@ -27,11 +27,11 @@ module ActiveRecord remove_column 'test_models', 'last_name' TestModel.reset_column_information - refute TestModel.column_methods_hash.key?(:last_name) + assert_not TestModel.column_methods_hash.key?(:last_name) end def test_add_remove_single_field_using_symbol_arguments - refute TestModel.column_methods_hash.key?(:last_name) + assert_not TestModel.column_methods_hash.key?(:last_name) add_column :test_models, :last_name, :string @@ -41,7 +41,7 @@ module ActiveRecord remove_column :test_models, :last_name TestModel.reset_column_information - refute TestModel.column_methods_hash.key?(:last_name) + assert_not TestModel.column_methods_hash.key?(:last_name) end def test_unabstracted_database_dependent_types diff --git a/activerecord/test/cases/migration/index_test.rb b/activerecord/test/cases/migration/index_test.rb index 0787414d8f..a41f2c10f0 100644 --- a/activerecord/test/cases/migration/index_test.rb +++ b/activerecord/test/cases/migration/index_test.rb @@ -35,7 +35,7 @@ module ActiveRecord connection.rename_index(table_name, 'old_idx', 'new_idx') # if the adapter doesn't support the indexes call, pick defaults that let the test pass - refute connection.index_name_exists?(table_name, 'old_idx', false) + assert_not connection.index_name_exists?(table_name, 'old_idx', false) assert connection.index_name_exists?(table_name, 'new_idx', true) end @@ -63,7 +63,7 @@ module ActiveRecord connection.add_index(table_name, "foo", :name => too_long_index_name) } - refute connection.index_name_exists?(table_name, too_long_index_name, false) + assert_not connection.index_name_exists?(table_name, too_long_index_name, false) connection.add_index(table_name, "foo", :name => good_index_name) assert connection.index_name_exists?(table_name, good_index_name, false) @@ -75,7 +75,7 @@ module ActiveRecord assert connection.index_exists?(table_name, :foo, :name => :symbol_index_name) connection.remove_index table_name, :name => :symbol_index_name - refute connection.index_exists?(table_name, :foo, :name => :symbol_index_name) + assert_not connection.index_exists?(table_name, :foo, :name => :symbol_index_name) end def test_index_exists diff --git a/activerecord/test/cases/migration/references_index_test.rb b/activerecord/test/cases/migration/references_index_test.rb index 264a99f9ce..3ff89524fe 100644 --- a/activerecord/test/cases/migration/references_index_test.rb +++ b/activerecord/test/cases/migration/references_index_test.rb @@ -29,7 +29,7 @@ module ActiveRecord t.references :foo end - refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) + assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) end def test_does_not_create_index_explicit @@ -37,7 +37,7 @@ module ActiveRecord t.references :foo, :index => false end - refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) + assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) end def test_creates_index_with_options @@ -75,7 +75,7 @@ module ActiveRecord t.references :foo end - refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) + assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) end def test_does_not_create_index_for_existing_table_explicit @@ -84,7 +84,7 @@ module ActiveRecord t.references :foo, :index => false end - refute connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) + assert_not connection.index_exists?(table_name, :foo_id, :name => :index_testings_on_foo_id) end def test_creates_polymorphic_index_for_existing_table diff --git a/activerecord/test/cases/migration/references_statements_test.rb b/activerecord/test/cases/migration/references_statements_test.rb index d8a6565d54..e9545f2cce 100644 --- a/activerecord/test/cases/migration/references_statements_test.rb +++ b/activerecord/test/cases/migration/references_statements_test.rb @@ -22,7 +22,7 @@ module ActiveRecord def test_does_not_create_reference_type_column add_reference table_name, :taggable - refute column_exists?(table_name, :taggable_type, :string) + assert_not column_exists?(table_name, :taggable_type, :string) end def test_creates_reference_type_column @@ -37,7 +37,7 @@ module ActiveRecord def test_does_not_create_reference_id_index add_reference table_name, :user - refute index_exists?(table_name, :user_id) + assert_not index_exists?(table_name, :user_id) end def test_creates_polymorphic_index @@ -57,19 +57,19 @@ module ActiveRecord def test_deletes_reference_id_column remove_reference table_name, :supplier - refute column_exists?(table_name, :supplier_id, :integer) + assert_not column_exists?(table_name, :supplier_id, :integer) end def test_deletes_reference_id_index remove_reference table_name, :supplier - refute index_exists?(table_name, :supplier_id) + assert_not index_exists?(table_name, :supplier_id) end def test_does_not_delete_reference_type_column with_polymorphic_column do remove_reference table_name, :supplier - refute column_exists?(table_name, :supplier_id, :integer) + assert_not column_exists?(table_name, :supplier_id, :integer) assert column_exists?(table_name, :supplier_type, :string) end end @@ -77,14 +77,14 @@ module ActiveRecord def test_deletes_reference_type_column with_polymorphic_column do remove_reference table_name, :supplier, polymorphic: true - refute column_exists?(table_name, :supplier_type, :string) + assert_not column_exists?(table_name, :supplier_type, :string) end end def test_deletes_polymorphic_index with_polymorphic_column do remove_reference table_name, :supplier, polymorphic: true - refute index_exists?(table_name, [:supplier_id, :supplier_type]) + assert_not index_exists?(table_name, [:supplier_id, :supplier_type]) end end @@ -95,7 +95,7 @@ module ActiveRecord def test_remove_belongs_to_alias remove_belongs_to table_name, :supplier - refute column_exists?(table_name, :supplier_id, :integer) + assert_not column_exists?(table_name, :supplier_id, :integer) end private diff --git a/activerecord/test/cases/migration/rename_column_test.rb b/activerecord/test/cases/migration/rename_column_test.rb index 318d61263a..8f6918d06a 100644 --- a/activerecord/test/cases/migration/rename_column_test.rb +++ b/activerecord/test/cases/migration/rename_column_test.rb @@ -84,16 +84,19 @@ module ActiveRecord add_column "test_models", :hat_name, :string add_index :test_models, :hat_name - # FIXME: we should test that the index goes away + assert_equal 1, connection.indexes('test_models').size rename_column "test_models", "hat_name", "name" + # FIXME: should we rename the index if it's name was autogenerated by rails? + assert_equal ['index_test_models_on_hat_name'], connection.indexes('test_models').map(&:name) end def test_remove_column_with_index add_column "test_models", :hat_name, :string add_index :test_models, :hat_name - # FIXME: we should test that the index goes away + assert_equal 1, connection.indexes('test_models').size remove_column("test_models", "hat_name") + assert_equal 0, connection.indexes('test_models').size end def test_remove_column_with_multi_column_index @@ -101,14 +104,25 @@ module ActiveRecord add_column "test_models", :hat_style, :string, :limit => 100 add_index "test_models", ["hat_style", "hat_size"], :unique => true - # FIXME: we should test that the index goes away + assert_equal 1, connection.indexes('test_models').size remove_column("test_models", "hat_size") + + # Every database and/or database adapter has their own behavior + # if it drops the multi-column index when any of the indexed columns dropped by remove_column. + if current_adapter?(:PostgreSQLAdapter, :OracleAdapter) + assert_equal [], connection.indexes('test_models').map(&:name) + else + assert_equal ['index_test_models_on_hat_style_and_hat_size'], connection.indexes('test_models').map(&:name) + end end - # FIXME: we need to test that these calls do something def test_change_type_of_not_null_column change_column "test_models", "updated_at", :datetime, :null => false change_column "test_models", "updated_at", :datetime, :null => false + + TestModel.reset_column_information + assert_equal false, TestModel.columns_hash['updated_at'].null + ensure change_column "test_models", "updated_at", :datetime, :null => true end @@ -119,7 +133,7 @@ module ActiveRecord change_column "test_models", "funny", :boolean, :null => false, :default => true TestModel.reset_column_information - refute TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point" + assert_not TestModel.columns_hash["funny"].null, "Column 'funny' must *not* allow nulls at this point" change_column "test_models", "funny", :boolean, :null => true TestModel.reset_column_information @@ -138,7 +152,7 @@ module ActiveRecord new_columns = connection.columns(TestModel.table_name) - refute new_columns.find { |c| c.name == 'age' and c.type == :integer } + assert_not new_columns.find { |c| c.name == 'age' and c.type == :integer } assert new_columns.find { |c| c.name == 'age' and c.type == :string } old_columns = connection.columns(TestModel.table_name) @@ -149,7 +163,7 @@ module ActiveRecord change_column :test_models, :approved, :boolean, :default => false new_columns = connection.columns(TestModel.table_name) - refute new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } + assert_not new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == true } assert new_columns.find { |c| c.name == 'approved' and c.type == :boolean and c.default == false } change_column :test_models, :approved, :boolean, :default => true end @@ -160,7 +174,7 @@ module ActiveRecord change_column "test_models", "contributor", :boolean, :default => nil TestModel.reset_column_information - refute TestModel.new.contributor? + assert_not TestModel.new.contributor? assert_nil TestModel.new.contributor end @@ -170,7 +184,7 @@ module ActiveRecord change_column "test_models", "administrator", :boolean, :default => false TestModel.reset_column_information - refute TestModel.new.administrator? + assert_not TestModel.new.administrator? end def test_change_column_with_custom_index_name diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index c155f29973..187c6e8447 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -24,7 +24,7 @@ class MigrationTest < ActiveRecord::TestCase def setup super - %w(reminders people_reminders prefix_reminders_suffix).each do |table| + %w(reminders people_reminders prefix_reminders_suffix p_things_s).each do |table| Reminder.connection.drop_table(table) rescue nil end Reminder.reset_column_information @@ -232,7 +232,7 @@ class MigrationTest < ActiveRecord::TestCase skip "not supported on #{ActiveRecord::Base.connection.class}" end - refute Person.column_methods_hash.include?(:last_name) + assert_not Person.column_methods_hash.include?(:last_name) migration = Struct.new(:name, :version) { def migrate(x); raise 'Something broke'; end @@ -245,7 +245,7 @@ class MigrationTest < ActiveRecord::TestCase assert_equal "An error has occurred, this and all later migrations canceled:\n\nSomething broke", e.message Person.reset_column_information - refute Person.column_methods_hash.include?(:last_name) + assert_not Person.column_methods_hash.include?(:last_name) end def test_schema_migrations_table_name diff --git a/activerecord/test/cases/migrator_test.rb b/activerecord/test/cases/migrator_test.rb index 199d0c584b..b5a69c4a92 100644 --- a/activerecord/test/cases/migrator_test.rb +++ b/activerecord/test/cases/migrator_test.rb @@ -29,6 +29,7 @@ module ActiveRecord def teardown super ActiveRecord::SchemaMigration.delete_all rescue nil + ActiveRecord::Migration.verbose = true end def test_migrator_with_duplicate_names @@ -121,11 +122,11 @@ module ActiveRecord ActiveRecord::Migrator.new(:up, pass_one).migrate assert pass_one.first.went_up - refute pass_one.first.went_down + assert_not pass_one.first.went_down pass_two = [Sensor.new('One', 1), Sensor.new('Three', 3)] ActiveRecord::Migrator.new(:up, pass_two).migrate - refute pass_two[0].went_up + assert_not pass_two[0].went_up assert pass_two[1].went_up assert pass_two.all? { |x| !x.went_down } @@ -135,7 +136,7 @@ module ActiveRecord ActiveRecord::Migrator.new(:down, pass_three).migrate assert pass_three[0].went_down - refute pass_three[1].went_down + assert_not pass_three[1].went_down assert pass_three[2].went_down end @@ -307,7 +308,7 @@ module ActiveRecord _, migrator = migrator_class(3) ActiveRecord::Base.connection.execute("DROP TABLE schema_migrations") - refute ActiveRecord::Base.connection.table_exists?('schema_migrations') + assert_not ActiveRecord::Base.connection.table_exists?('schema_migrations') migrator.migrate("valid", 1) assert ActiveRecord::Base.connection.table_exists?('schema_migrations') end diff --git a/activerecord/test/cases/nested_attributes_test.rb b/activerecord/test/cases/nested_attributes_test.rb index 3f08f9ea4d..94837341fc 100644 --- a/activerecord/test/cases/nested_attributes_test.rb +++ b/activerecord/test/cases/nested_attributes_test.rb @@ -79,10 +79,10 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase def test_should_disable_allow_destroy_by_default Pirate.accepts_nested_attributes_for :ship - pirate = Pirate.create!(:catchphrase => "Don' botharrr talkin' like one, savvy?") - ship = pirate.create_ship(:name => 'Nights Dirty Lightning') + pirate = Pirate.create!(catchphrase: "Don' botharrr talkin' like one, savvy?") + ship = pirate.create_ship(name: 'Nights Dirty Lightning') - pirate.update_attributes(:ship_attributes => { '_destroy' => true, :id => ship.id }) + pirate.update(ship_attributes: { '_destroy' => true, :id => ship.id }) assert_nothing_raised(ActiveRecord::RecordNotFound) { pirate.ship.reload } end @@ -125,33 +125,33 @@ class TestNestedAttributesInGeneral < ActiveRecord::TestCase def test_reject_if_with_a_proc_which_returns_true_always_for_has_one Pirate.accepts_nested_attributes_for :ship, :reject_if => proc {|attributes| true } - pirate = Pirate.new(:catchphrase => "Stop wastin' me time") - ship = pirate.create_ship(:name => 's1') - pirate.update_attributes({:ship_attributes => { :name => 's2', :id => ship.id } }) + pirate = Pirate.new(catchphrase: "Stop wastin' me time") + ship = pirate.create_ship(name: 's1') + pirate.update({ship_attributes: { name: 's2', id: ship.id } }) assert_equal 's1', ship.reload.name end def test_reject_if_with_a_proc_which_returns_true_always_for_has_many Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true } - man = Man.create(:name => "John") - interest = man.interests.create(:topic => 'photography') - man.update_attributes({:interests_attributes => { :topic => 'gardening', :id => interest.id } }) + man = Man.create(name: "John") + interest = man.interests.create(topic: 'photography') + man.update({interests_attributes: { topic: 'gardening', id: interest.id } }) assert_equal 'photography', interest.reload.topic end def test_destroy_works_independent_of_reject_if Man.accepts_nested_attributes_for :interests, :reject_if => proc {|attributes| true }, :allow_destroy => true - man = Man.create(:name => "Jon") - interest = man.interests.create(:topic => 'the ladies') - man.update_attributes({:interests_attributes => { :_destroy => "1", :id => interest.id } }) + man = Man.create(name: "Jon") + interest = man.interests.create(topic: 'the ladies') + man.update({interests_attributes: { _destroy: "1", id: interest.id } }) assert man.reload.interests.empty? end def test_has_many_association_updating_a_single_record Man.accepts_nested_attributes_for(:interests) - man = Man.create(:name => 'John') - interest = man.interests.create(:topic => 'photography') - man.update_attributes({:interests_attributes => {:topic => 'gardening', :id => interest.id}}) + man = Man.create(name: 'John') + interest = man.interests.create(topic: 'photography') + man.update({interests_attributes: {topic: 'gardening', id: interest.id}}) assert_equal 'gardening', interest.reload.topic end @@ -284,8 +284,8 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase @pirate.ship.destroy [1, '1', true, 'true'].each do |truth| - ship = @pirate.reload.create_ship(:name => 'Mister Pablo') - @pirate.update_attributes(:ship_attributes => { :id => ship.id, :_destroy => truth }) + ship = @pirate.reload.create_ship(name: 'Mister Pablo') + @pirate.update(ship_attributes: { id: ship.id, _destroy: truth }) assert_nil @pirate.reload.ship assert_raise(ActiveRecord::RecordNotFound) { Ship.find(ship.id) } @@ -294,7 +294,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy [nil, '0', 0, 'false', false].each do |not_truth| - @pirate.update_attributes(:ship_attributes => { :id => @pirate.ship.id, :_destroy => not_truth }) + @pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: not_truth }) assert_equal @ship, @pirate.reload.ship end @@ -303,7 +303,7 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false Pirate.accepts_nested_attributes_for :ship, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? } - @pirate.update_attributes(:ship_attributes => { :id => @pirate.ship.id, :_destroy => '1' }) + @pirate.update(ship_attributes: { id: @pirate.ship.id, _destroy: '1' }) assert_equal @ship, @pirate.reload.ship @@ -311,14 +311,14 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase end def test_should_also_work_with_a_HashWithIndifferentAccess - @pirate.ship_attributes = HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger') + @pirate.ship_attributes = ActiveSupport::HashWithIndifferentAccess.new(:id => @ship.id, :name => 'Davy Jones Gold Dagger') assert @pirate.ship.persisted? assert_equal 'Davy Jones Gold Dagger', @pirate.ship.name end - def test_should_work_with_update_attributes_as_well - @pirate.update_attributes({ :catchphrase => 'Arr', :ship_attributes => { :id => @ship.id, :name => 'Mister Pablo' } }) + def test_should_work_with_update_as_well + @pirate.update({ catchphrase: 'Arr', ship_attributes: { id: @ship.id, name: 'Mister Pablo' } }) @pirate.reload assert_equal 'Arr', @pirate.catchphrase @@ -342,22 +342,22 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase end def test_should_accept_update_only_option - @pirate.update_attributes(:update_only_ship_attributes => { :id => @pirate.ship.id, :name => 'Mayflower' }) + @pirate.update(update_only_ship_attributes: { id: @pirate.ship.id, name: 'Mayflower' }) end def test_should_create_new_model_when_nothing_is_there_and_update_only_is_true @ship.delete - @pirate.reload.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower' }) + @pirate.reload.update(update_only_ship_attributes: { name: 'Mayflower' }) assert_not_nil @pirate.ship end def test_should_update_existing_when_update_only_is_true_and_no_id_is_given @ship.delete - @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning') + @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning') - @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower' }) + @pirate.update(update_only_ship_attributes: { name: 'Mayflower' }) assert_equal 'Mayflower', @ship.reload.name assert_equal @ship, @pirate.reload.ship @@ -365,9 +365,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_update_existing_when_update_only_is_true_and_id_is_given @ship.delete - @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning') + @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning') - @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower', :id => @ship.id }) + @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id }) assert_equal 'Mayflower', @ship.reload.name assert_equal @ship, @pirate.reload.ship @@ -376,9 +376,9 @@ class TestNestedAttributesOnAHasOneAssociation < ActiveRecord::TestCase def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction Pirate.accepts_nested_attributes_for :update_only_ship, :update_only => true, :allow_destroy => true @ship.delete - @ship = @pirate.create_update_only_ship(:name => 'Nights Dirty Lightning') + @ship = @pirate.create_update_only_ship(name: 'Nights Dirty Lightning') - @pirate.update_attributes(:update_only_ship_attributes => { :name => 'Mayflower', :id => @ship.id, :_destroy => true }) + @pirate.update(update_only_ship_attributes: { name: 'Mayflower', id: @ship.id, _destroy: true }) assert_nil @pirate.reload.ship assert_raise(ActiveRecord::RecordNotFound) { Ship.find(@ship.id) } @@ -468,15 +468,15 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_destroy_an_existing_record_if_there_is_a_matching_id_and_destroy_is_truthy @ship.pirate.destroy [1, '1', true, 'true'].each do |truth| - pirate = @ship.reload.create_pirate(:catchphrase => 'Arr') - @ship.update_attributes(:pirate_attributes => { :id => pirate.id, :_destroy => truth }) + pirate = @ship.reload.create_pirate(catchphrase: 'Arr') + @ship.update(pirate_attributes: { id: pirate.id, _destroy: truth }) assert_raise(ActiveRecord::RecordNotFound) { pirate.reload } end end def test_should_unset_association_when_an_existing_record_is_destroyed original_pirate_id = @ship.pirate.id - @ship.update_attributes! pirate_attributes: { id: @ship.pirate.id, _destroy: true } + @ship.update! pirate_attributes: { id: @ship.pirate.id, _destroy: true } assert_empty Pirate.where(id: original_pirate_id) assert_nil @ship.pirate_id @@ -490,7 +490,7 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_not_destroy_an_existing_record_if_destroy_is_not_truthy [nil, '0', 0, 'false', false].each do |not_truth| - @ship.update_attributes(:pirate_attributes => { :id => @ship.pirate.id, :_destroy => not_truth }) + @ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: not_truth }) assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload } end end @@ -498,14 +498,14 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_not_destroy_an_existing_record_if_allow_destroy_is_false Ship.accepts_nested_attributes_for :pirate, :allow_destroy => false, :reject_if => proc { |attributes| attributes.empty? } - @ship.update_attributes(:pirate_attributes => { :id => @ship.pirate.id, :_destroy => '1' }) + @ship.update(pirate_attributes: { id: @ship.pirate.id, _destroy: '1' }) assert_nothing_raised(ActiveRecord::RecordNotFound) { @ship.pirate.reload } ensure Ship.accepts_nested_attributes_for :pirate, :allow_destroy => true, :reject_if => proc { |attributes| attributes.empty? } end - def test_should_work_with_update_attributes_as_well - @ship.update_attributes({ :name => 'Mister Pablo', :pirate_attributes => { :catchphrase => 'Arr' } }) + def test_should_work_with_update_as_well + @ship.update({ name: 'Mister Pablo', pirate_attributes: { catchphrase: 'Arr' } }) @ship.reload assert_equal 'Mister Pablo', @ship.name @@ -534,18 +534,18 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_update_existing_when_update_only_is_true_and_no_id_is_given @pirate.delete - @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye') + @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye') - @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr' }) + @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr' }) assert_equal 'Arr', @pirate.reload.catchphrase assert_equal @pirate, @ship.reload.update_only_pirate end def test_should_update_existing_when_update_only_is_true_and_id_is_given @pirate.delete - @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye') + @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye') - @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr', :id => @pirate.id }) + @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id }) assert_equal 'Arr', @pirate.reload.catchphrase assert_equal @pirate, @ship.reload.update_only_pirate @@ -554,9 +554,9 @@ class TestNestedAttributesOnABelongsToAssociation < ActiveRecord::TestCase def test_should_destroy_existing_when_update_only_is_true_and_id_is_given_and_is_marked_for_destruction Ship.accepts_nested_attributes_for :update_only_pirate, :update_only => true, :allow_destroy => true @pirate.delete - @pirate = @ship.create_update_only_pirate(:catchphrase => 'Aye') + @pirate = @ship.create_update_only_pirate(catchphrase: 'Aye') - @ship.update_attributes(:update_only_pirate_attributes => { :catchphrase => 'Arr', :id => @pirate.id, :_destroy => true }) + @ship.update(update_only_pirate_attributes: { catchphrase: 'Arr', id: @pirate.id, _destroy: true }) assert_raise(ActiveRecord::RecordNotFound) { @pirate.reload } @@ -582,7 +582,7 @@ module NestedAttributesOnACollectionAssociationTests def test_should_take_a_hash_with_string_keys_and_assign_the_attributes_to_the_associated_models @alternate_params[association_getter].stringify_keys! - @pirate.update_attributes @alternate_params + @pirate.update @alternate_params assert_equal ['Grace OMalley', 'Privateers Greed'], [@child_1.reload.name, @child_2.reload.name] end @@ -593,7 +593,7 @@ module NestedAttributesOnACollectionAssociationTests end def test_should_also_work_with_a_HashWithIndifferentAccess - @pirate.send(association_setter, HashWithIndifferentAccess.new('foo' => HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley'))) + @pirate.send(association_setter, ActiveSupport::HashWithIndifferentAccess.new('foo' => ActiveSupport::HashWithIndifferentAccess.new(:id => @child_1.id, :name => 'Grace OMalley'))) @pirate.save assert_equal 'Grace OMalley', @child_1.reload.name end @@ -628,10 +628,10 @@ module NestedAttributesOnACollectionAssociationTests def test_should_refresh_saved_records_when_not_overwriting_unsaved_updates @pirate.reload - record = @pirate.class.reflect_on_association(@association_name).klass.new(:name => 'Grace OMalley') + record = @pirate.class.reflect_on_association(@association_name).klass.new(name: 'Grace OMalley') @pirate.send(@association_name) << record record.save! - @pirate.send(@association_name).last.update_attributes!(:name => 'Polly') + @pirate.send(@association_name).last.update!(name: 'Polly') assert_equal 'Polly', @pirate.send(@association_name).send(:load_target).last.name end @@ -718,17 +718,17 @@ module NestedAttributesOnACollectionAssociationTests end end - def test_should_work_with_update_attributes_as_well - @pirate.update_attributes(:catchphrase => 'Arr', + def test_should_work_with_update_as_well + @pirate.update(catchphrase: 'Arr', association_getter => { 'foo' => { :id => @child_1.id, :name => 'Grace OMalley' }}) assert_equal 'Grace OMalley', @child_1.reload.name end def test_should_update_existing_records_and_add_new_ones_that_have_no_id - @alternate_params[association_getter]['baz'] = { :name => 'Buccaneers Servant' } + @alternate_params[association_getter]['baz'] = { name: 'Buccaneers Servant' } assert_difference('@pirate.send(@association_name).count', +1) do - @pirate.update_attributes @alternate_params + @pirate.update @alternate_params end assert_equal ['Grace OMalley', 'Privateers Greed', 'Buccaneers Servant'].to_set, @pirate.reload.send(@association_name).map(&:name).to_set end @@ -750,7 +750,7 @@ module NestedAttributesOnACollectionAssociationTests [nil, '', '0', 0, 'false', false].each do |false_variable| @alternate_params[association_getter]['foo']['_destroy'] = false_variable assert_no_difference('@pirate.send(@association_name).count') do - @pirate.update_attributes(@alternate_params) + @pirate.update(@alternate_params) end end end @@ -814,7 +814,7 @@ module NestedAttributesOnACollectionAssociationTests man = Man.create(name: 'John') interest = man.interests.create(topic: 'bar', zine_id: 0) assert interest.save - assert !man.update_attributes({interests_attributes: { id: interest.id, zine_id: 'foo' }}) + assert !man.update({interests_attributes: { id: interest.id, zine_id: 'foo' }}) end end @@ -945,18 +945,18 @@ class TestNestedAttributesWithNonStandardPrimaryKeys < ActiveRecord::TestCase end def test_should_update_existing_records_with_non_standard_primary_key - @owner.update_attributes(@params) + @owner.update(@params) assert_equal ['Foo', 'Bar'], @owner.pets.map(&:name) end - def test_attr_accessor_of_child_should_be_value_provided_during_update_attributes + def test_attr_accessor_of_child_should_be_value_provided_during_update @owner = owners(:ashley) @pet1 = pets(:chew) attributes = {:pets_attributes => { "1"=> { :id => @pet1.id, :name => "Foo2", :current_user => "John", :_destroy=>true }}} - @owner.update_attributes(attributes) + @owner.update(attributes) assert_equal 'John', Pet.after_destroy_output end diff --git a/activerecord/test/cases/persistence_test.rb b/activerecord/test/cases/persistence_test.rb index 9e0423ab52..b936cca875 100644 --- a/activerecord/test/cases/persistence_test.rb +++ b/activerecord/test/cases/persistence_test.rb @@ -16,7 +16,6 @@ require 'models/person' require 'models/pet' require 'models/toy' require 'rexml/document' -require 'active_support/core_ext/exception' class PersistencesTest < ActiveRecord::TestCase @@ -243,7 +242,7 @@ class PersistencesTest < ActiveRecord::TestCase assert_equal "David", topic2.author_name end - def test_update + def test_update_object topic = Topic.new topic.title = "Another New Topic" topic.written_on = "2003-12-12 23:23:00" @@ -365,7 +364,7 @@ class PersistencesTest < ActiveRecord::TestCase client.delete assert client.frozen? assert_kind_of Firm, client.firm - assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" } + assert_raise(RuntimeError) { client.name = "something else" } end def test_destroy_new_record @@ -379,7 +378,7 @@ class PersistencesTest < ActiveRecord::TestCase client.destroy assert client.frozen? assert_kind_of Firm, client.firm - assert_raise(ActiveSupport::FrozenObjectError) { client.name = "something else" } + assert_raise(RuntimeError) { client.name = "something else" } end def test_update_attribute @@ -392,7 +391,7 @@ class PersistencesTest < ActiveRecord::TestCase end def test_update_attribute_does_not_choke_on_nil - assert Topic.find(1).update_attributes(nil) + assert Topic.find(1).update(nil) end def test_update_attribute_for_readonly_attribute @@ -548,7 +547,7 @@ class PersistencesTest < ActiveRecord::TestCase def test_update_columns_should_not_leave_the_object_dirty topic = Topic.find(1) - topic.update_attributes({ "content" => "Have a nice day", :author_name => "Jose" }) + topic.update({ "content" => "Have a nice day", :author_name => "Jose" }) topic.reload topic.update_columns({ content: "You too", "author_name" => "Sebastian" }) @@ -632,6 +631,22 @@ class PersistencesTest < ActiveRecord::TestCase assert developer.update_columns(name: 'Will'), 'did not update record due to default scope' end + def test_update + topic = Topic.find(1) + assert !topic.approved? + assert_equal "The First Topic", topic.title + + topic.update("approved" => true, "title" => "The First Topic Updated") + topic.reload + assert topic.approved? + assert_equal "The First Topic Updated", topic.title + + topic.update(approved: false, title: "The First Topic") + topic.reload + assert !topic.approved? + assert_equal "The First Topic", topic.title + end + def test_update_attributes topic = Topic.find(1) assert !topic.approved? @@ -642,12 +657,33 @@ class PersistencesTest < ActiveRecord::TestCase assert topic.approved? assert_equal "The First Topic Updated", topic.title - topic.update_attributes(:approved => false, :title => "The First Topic") + topic.update_attributes(approved: false, title: "The First Topic") topic.reload assert !topic.approved? assert_equal "The First Topic", topic.title end + def test_update! + Reply.validates_presence_of(:title) + reply = Reply.find(2) + assert_equal "The Second Topic of the day", reply.title + assert_equal "Have a nice day", reply.content + + reply.update!("title" => "The Second Topic of the day updated", "content" => "Have a nice evening") + reply.reload + assert_equal "The Second Topic of the day updated", reply.title + assert_equal "Have a nice evening", reply.content + + reply.update!(title: "The Second Topic of the day", content: "Have a nice day") + reply.reload + assert_equal "The Second Topic of the day", reply.title + assert_equal "Have a nice day", reply.content + + assert_raise(ActiveRecord::RecordInvalid) { reply.update!(title: nil, content: "Have a nice evening") } + ensure + Reply.reset_callbacks(:validate) + end + def test_update_attributes! Reply.validates_presence_of(:title) reply = Reply.find(2) @@ -659,12 +695,12 @@ class PersistencesTest < ActiveRecord::TestCase assert_equal "The Second Topic of the day updated", reply.title assert_equal "Have a nice evening", reply.content - reply.update_attributes!(:title => "The Second Topic of the day", :content => "Have a nice day") + reply.update_attributes!(title: "The Second Topic of the day", content: "Have a nice day") reply.reload assert_equal "The Second Topic of the day", reply.title assert_equal "Have a nice day", reply.content - assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(:title => nil, :content => "Have a nice evening") } + assert_raise(ActiveRecord::RecordInvalid) { reply.update_attributes!(title: nil, content: "Have a nice evening") } ensure Reply.reset_callbacks(:validate) end diff --git a/activerecord/test/cases/primary_keys_test.rb b/activerecord/test/cases/primary_keys_test.rb index bf8aacc363..8e5379cb1f 100644 --- a/activerecord/test/cases/primary_keys_test.rb +++ b/activerecord/test/cases/primary_keys_test.rb @@ -201,10 +201,10 @@ class PrimaryKeyWithNoConnectionTest < ActiveRecord::TestCase end end -if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) +if current_adapter?(:MysqlAdapter, :Mysql2Adapter) class PrimaryKeyWithAnsiQuotesTest < ActiveRecord::TestCase self.use_transactional_fixtures = false - + def test_primaery_key_method_with_ansi_quotes con = ActiveRecord::Base.connection con.execute("SET SESSION sql_mode='ANSI_QUOTES'") @@ -212,7 +212,7 @@ if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) ensure con.reconnect! end - + end end diff --git a/activerecord/test/cases/query_cache_test.rb b/activerecord/test/cases/query_cache_test.rb index 4ff481e6a5..136fda664c 100644 --- a/activerecord/test/cases/query_cache_test.rb +++ b/activerecord/test/cases/query_cache_test.rb @@ -167,7 +167,7 @@ class QueryCacheTest < ActiveRecord::TestCase # Oracle adapter returns count() as Fixnum or Float if current_adapter?(:OracleAdapter) assert_kind_of Numeric, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") - elsif current_adapter?(:SQLite3Adapter) || current_adapter?(:Mysql2Adapter) + elsif current_adapter?(:SQLite3Adapter, :Mysql2Adapter) # Future versions of the sqlite3 adapter will return numeric assert_instance_of Fixnum, Task.connection.select_value("SELECT count(*) AS count_all FROM tasks") diff --git a/activerecord/test/cases/relation/where_test.rb b/activerecord/test/cases/relation/where_test.rb index 297e865308..f69a248491 100644 --- a/activerecord/test/cases/relation/where_test.rb +++ b/activerecord/test/cases/relation/where_test.rb @@ -82,6 +82,10 @@ module ActiveRecord assert_equal 0, Post.where(:posts => {}).count end + def test_where_with_table_name_and_empty_array + assert_equal 0, Post.where(:id => []).count + end + def test_where_with_empty_hash_and_no_foreign_key assert_equal 0, Edge.where(:sink => {}).count end diff --git a/activerecord/test/cases/relation_scoping_test.rb b/activerecord/test/cases/relation_scoping_test.rb index d318dab1e1..78fb91d321 100644 --- a/activerecord/test/cases/relation_scoping_test.rb +++ b/activerecord/test/cases/relation_scoping_test.rb @@ -227,7 +227,7 @@ class NestedRelationScopingTest < ActiveRecord::TestCase def test_nested_exclusive_scope_for_create comment = Comment.create_with(:body => "Hey guys, nested scopes are broken. Please fix!").scoping do Comment.unscoped.create_with(:post_id => 1).scoping do - assert_blank Comment.new.body + assert Comment.new.body.blank? Comment.create :body => "Hey guys" end end diff --git a/activerecord/test/cases/relations_test.rb b/activerecord/test/cases/relations_test.rb index 0cd838c0b0..3a499a2025 100644 --- a/activerecord/test/cases/relations_test.rb +++ b/activerecord/test/cases/relations_test.rb @@ -509,7 +509,7 @@ class RelationTest < ActiveRecord::TestCase def test_find_in_empty_array authors = Author.all.where(:id => []) - assert_blank authors.to_a + assert authors.to_a.blank? end def test_where_with_ar_object @@ -723,7 +723,7 @@ class RelationTest < ActiveRecord::TestCase def test_relation_merging_with_locks devs = Developer.lock.where("salary >= 80000").order("id DESC").merge(Developer.limit(2)) - assert_present devs.locked + assert devs.locked.present? end def test_relation_merging_with_preload diff --git a/activerecord/test/cases/schema_dumper_test.rb b/activerecord/test/cases/schema_dumper_test.rb index 7ff0044bd4..cae12e0e3a 100644 --- a/activerecord/test/cases/schema_dumper_test.rb +++ b/activerecord/test/cases/schema_dumper_test.rb @@ -112,7 +112,7 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r{c_int_4.*}, output assert_no_match %r{c_int_4.*limit:}, output - elsif current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + elsif current_adapter?(:MysqlAdapter, :Mysql2Adapter) assert_match %r{c_int_1.*limit: 1}, output assert_match %r{c_int_2.*limit: 2}, output assert_match %r{c_int_3.*limit: 3}, output @@ -197,7 +197,7 @@ class SchemaDumperTest < ActiveRecord::TestCase assert_match %r(primary_key: "movieid"), match[1], "non-standard primary key not preserved" end - if current_adapter?(:MysqlAdapter) or current_adapter?(:Mysql2Adapter) + if current_adapter?(:MysqlAdapter, :Mysql2Adapter) def test_schema_dump_should_not_add_default_value_for_mysql_text_field output = standard_dump assert_match %r{t.text\s+"body",\s+null: false$}, output @@ -280,6 +280,13 @@ class SchemaDumperTest < ActiveRecord::TestCase end end + def test_schema_dump_includes_ltrees_shorthand_definition + output = standard_dump + if %r{create_table "postgresql_ltrees"} =~ output + assert_match %r[t.ltree "path"], output + end + end + def test_schema_dump_includes_arrays_shorthand_definition output = standard_dump if %r{create_table "postgresql_arrays"} =~ output diff --git a/activerecord/test/cases/store_test.rb b/activerecord/test/cases/store_test.rb index 562ca8d9ff..43bf285ba9 100644 --- a/activerecord/test/cases/store_test.rb +++ b/activerecord/test/cases/store_test.rb @@ -67,9 +67,9 @@ class StoreTest < ActiveRecord::TestCase end test "preserve store attributes data in HashWithIndifferentAccess format without any conversion" do - @john.json_data = HashWithIndifferentAccess.new(:height => 'tall', 'weight' => 'heavy') + @john.json_data = ActiveSupport::HashWithIndifferentAccess.new(:height => 'tall', 'weight' => 'heavy') @john.height = 'low' - assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess) + assert_equal true, @john.json_data.instance_of?(ActiveSupport::HashWithIndifferentAccess) assert_equal 'low', @john.json_data[:height] assert_equal 'low', @john.json_data['height'] assert_equal 'heavy', @john.json_data[:weight] @@ -95,7 +95,7 @@ class StoreTest < ActiveRecord::TestCase test "convert store attributes from any format other than Hash or HashWithIndifferent access losing the data" do @john.json_data = "somedata" @john.height = 'low' - assert_equal true, @john.json_data.instance_of?(HashWithIndifferentAccess) + assert_equal true, @john.json_data.instance_of?(ActiveSupport::HashWithIndifferentAccess) assert_equal 'low', @john.json_data[:height] assert_equal 'low', @john.json_data['height'] assert_equal false, @john.json_data.delete_if { |k, v| k == 'height' }.any? @@ -143,5 +143,4 @@ class StoreTest < ActiveRecord::TestCase assert_raise(NoMethodError) { @john.stored_attributes = Hash.new } assert_raise(NoMethodError) { @john.stored_attributes } end - end diff --git a/activerecord/test/cases/transaction_isolation_test.rb b/activerecord/test/cases/transaction_isolation_test.rb index a396da6645..4f1cb99b68 100644 --- a/activerecord/test/cases/transaction_isolation_test.rb +++ b/activerecord/test/cases/transaction_isolation_test.rb @@ -77,7 +77,7 @@ class TransactionIsolationTest < ActiveRecord::TestCase Tag.transaction(isolation: :repeatable_read) do tag.reload - Tag2.find(tag.id).update_attributes(name: 'emily') + Tag2.find(tag.id).update(name: 'emily') tag.reload assert_equal 'jon', tag.name diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index fdca10f4fb..bcbc48b38a 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -15,7 +15,7 @@ class TransactionTest < ActiveRecord::TestCase end def test_raise_after_destroy - refute @first.frozen? + assert_not @first.frozen? assert_raises(RuntimeError) { Topic.transaction do @@ -26,7 +26,7 @@ class TransactionTest < ActiveRecord::TestCase } assert @first.reload - refute @first.frozen? + assert_not @first.frozen? end def test_successful @@ -117,21 +117,21 @@ class TransactionTest < ActiveRecord::TestCase assert !Topic.find(1).approved? end - def test_update_attributes_should_rollback_on_failure + def test_update_should_rollback_on_failure author = Author.find(1) posts_count = author.posts.size assert posts_count > 0 - status = author.update_attributes(:name => nil, :post_ids => []) + status = author.update(name: nil, post_ids: []) assert !status assert_equal posts_count, author.posts(true).size end - def test_update_attributes_should_rollback_on_failure! + def test_update_should_rollback_on_failure! author = Author.find(1) posts_count = author.posts.size assert posts_count > 0 assert_raise(ActiveRecord::RecordInvalid) do - author.update_attributes!(:name => nil, :post_ids => []) + author.update!(name: nil, post_ids: []) end assert_equal posts_count, author.posts(true).size end diff --git a/activerecord/test/models/reference.rb b/activerecord/test/models/reference.rb index 1636c118a2..c2f9068f57 100644 --- a/activerecord/test/models/reference.rb +++ b/activerecord/test/models/reference.rb @@ -11,7 +11,7 @@ class Reference < ActiveRecord::Base def make_comments if self.class.make_comments - person.update_attributes :comments => "Reference destroyed" + person.update comments: "Reference destroyed" end end end diff --git a/activerecord/test/models/reply.rb b/activerecord/test/models/reply.rb index 079e325aad..c88262580e 100644 --- a/activerecord/test/models/reply.rb +++ b/activerecord/test/models/reply.rb @@ -1,8 +1,6 @@ require 'models/topic' class Reply < Topic - scope :base, -> { scoped } - belongs_to :topic, :foreign_key => "parent_id", :counter_cache => true belongs_to :topic_with_primary_key, :class_name => "Topic", :primary_key => "title", :foreign_key => "parent_title", :counter_cache => "replies_count" has_many :replies, :class_name => "SillyReply", :dependent => :destroy, :foreign_key => "parent_id" diff --git a/activerecord/test/schema/postgresql_specific_schema.rb b/activerecord/test/schema/postgresql_specific_schema.rb index 96fef3a831..ae13f2cd8a 100644 --- a/activerecord/test/schema/postgresql_specific_schema.rb +++ b/activerecord/test/schema/postgresql_specific_schema.rb @@ -1,6 +1,6 @@ ActiveRecord::Schema.define do - %w(postgresql_tsvectors postgresql_hstores postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings postgresql_uuids + %w(postgresql_tsvectors postgresql_hstores postgresql_arrays postgresql_moneys postgresql_numbers postgresql_times postgresql_network_addresses postgresql_bit_strings postgresql_uuids postgresql_ltrees postgresql_oids postgresql_xml_data_type defaults geometrics postgresql_timestamp_with_zones postgresql_partitioned_table postgresql_partitioned_table_parent postgresql_json_data_type postgresql_intrange_data_type).each do |table_name| execute "DROP TABLE IF EXISTS #{quote_table_name table_name}" end @@ -89,6 +89,15 @@ _SQL _SQL end + if 't' == select_value("select 'ltree'=ANY(select typname from pg_type)") + execute <<_SQL + CREATE TABLE postgresql_ltrees ( + id SERIAL PRIMARY KEY, + path ltree + ); +_SQL + end + if 't' == select_value("select 'json'=ANY(select typname from pg_type)") execute <<_SQL CREATE TABLE postgresql_json_data_type ( |