From f74a5616e89f03e13a025401475ac1101bb159ae Mon Sep 17 00:00:00 2001 From: Alan Kennedy Date: Sun, 25 Nov 2012 21:01:27 +0000 Subject: Save has_one associations only if record has changes Prevents save related callbacks such as `after_commit` being triggered when `has_one` objects are already persisted and have no changes. --- activerecord/lib/active_record/autosave_association.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/autosave_association.rb b/activerecord/lib/active_record/autosave_association.rb index e9622ca0c1..e9e35f4e21 100644 --- a/activerecord/lib/active_record/autosave_association.rb +++ b/activerecord/lib/active_record/autosave_association.rb @@ -377,14 +377,15 @@ module ActiveRecord def save_has_one_association(reflection) association = association_instance_get(reflection.name) record = association && association.load_target + if record && !record.destroyed? autosave = reflection.options[:autosave] if autosave && record.marked_for_destruction? record.destroy - else + elsif autosave != false key = reflection.options[:primary_key] ? send(reflection.options[:primary_key]) : id - if autosave != false && (autosave || new_record? || record_changed?(reflection, record, key)) + if (autosave && record.changed_for_autosave?) || new_record? || record_changed?(reflection, record, key) unless reflection.through_reflection record[reflection.foreign_key] = key -- cgit v1.2.3 From 501ae92a32285528c8bbdcf2af422eadb6a63c0e Mon Sep 17 00:00:00 2001 From: Ryuta Kamizono Date: Tue, 26 Nov 2013 04:59:18 +0900 Subject: Only use BINARY for mysql case sensitive uniqueness check when column has a case insensitive collation. --- .../lib/active_record/connection_adapters/abstract_adapter.rb | 5 +++++ .../active_record/connection_adapters/abstract_mysql_adapter.rb | 8 ++++++++ activerecord/lib/active_record/validations/uniqueness.rb | 3 +-- 3 files changed, 14 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb index 8aa1ce5c04..21829b4932 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb @@ -334,6 +334,11 @@ module ActiveRecord node end + def case_sensitive_comparison(table, attribute, column, value) + value = case_sensitive_modifier(value) unless value.nil? + table[attribute].eq(value) + end + def case_insensitive_comparison(table, attribute, column, value) table[attribute].lower.eq(table.lower(value)) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index dcbc3466b2..b17ac5ebf6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -585,6 +585,14 @@ module ActiveRecord Arel::Nodes::Bin.new(node) end + def case_sensitive_comparison(table, attribute, column, value) + if column.case_sensitive? + table[attribute].eq(value) + else + super + end + end + def case_insensitive_comparison(table, attribute, column, value) if column.case_sensitive? super diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 38f37f5c8a..412c0cc18a 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -59,8 +59,7 @@ module ActiveRecord # will use SQL LOWER function before comparison, unless it detects a case insensitive collation klass.connection.case_insensitive_comparison(table, attribute, column, value) else - value = klass.connection.case_sensitive_modifier(value) unless value.nil? - table[attribute].eq(value) + klass.connection.case_sensitive_comparison(table, attribute, column, value) end end -- cgit v1.2.3 From 6e53d92498ada27cea6c7bae85708fcf5579223c Mon Sep 17 00:00:00 2001 From: TheMonster Date: Wed, 26 Feb 2014 03:24:44 +0200 Subject: Fix a bug affecting validations of enum attributes This fixes a bug where any enum attribute of a model would be evaluated always as 0 when calling the database on validations. This fix converts the value of the enum attribute to its integer value rather than the string before building the relation as the bug occured when the string finally gets converted to integer using string.to_i which converts it to 0. [Vilius Luneckas, Ahmed AbouElhamayed] --- activerecord/lib/active_record/validations/uniqueness.rb | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 7ebe9dfec0..49b0f73219 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -13,6 +13,7 @@ module ActiveRecord def validate_each(record, attribute, value) finder_class = find_finder_class_for(record) table = finder_class.arel_table + value = map_enum_attribute(finder_class,attribute,value) value = deserialize_attribute(record, attribute, value) relation = build_relation(finder_class, table, attribute, value) @@ -91,6 +92,12 @@ module ActiveRecord value = coder.dump value if value && coder value end + + def map_enum_attribute(klass,attribute,value) + mapping = klass.enum_mapping_for(attribute.to_s) + value = mapping[value] if value && mapping + value + end end module ClassMethods -- cgit v1.2.3 From d1e7cd14c29f1ef45f2f36e79cd99eb580036991 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Fri, 28 Feb 2014 09:49:52 +0100 Subject: `includes` uses SQL parsing when String joins are involved. This is a partial revert of 22b3481ba2aa55fad1f9a5db94072312b345fb55. The current implementation of `references_eager_loaded_tables?` needs to know every table involved in the query. With the current API this is not possible without SQL parsing. While a2dab46cae35a06fd5c5500037177492a047c252 deprecated SQL parsing for `includes`. It did not issue deprecation warnings when String joins are involved. This resulted in a breaking change after the deprecated behavior was removed (22b3481ba2aa55fad1f9a5db94072312b345fb55). We will need to rethink the usage of `includes`, `preload` and `eager_load` but for now, this brings back the old *working* behavior. --- activerecord/lib/active_record/relation.rb | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index fb213dc6f7..9eaba4a655 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -617,7 +617,9 @@ module ActiveRecord def references_eager_loaded_tables? joined_tables = arel.join_sources.map do |join| - unless join.is_a?(Arel::Nodes::StringJoin) + if join.is_a?(Arel::Nodes::StringJoin) + tables_in_string(join.left) + else [join.left.table_name, join.left.table_alias] end end @@ -629,5 +631,12 @@ module ActiveRecord (references_values - joined_tables).any? end + + def tables_in_string(string) + return [] if string.blank? + # always convert table names to downcase as in Oracle quoted table names are in uppercase + # ignore raw_sql_ that is used by Oracle adapter as alias for limit/offset subqueries + string.scan(/([a-zA-Z_][.\w]+).?\./).flatten.map{ |s| s.downcase }.uniq - ['raw_sql_'] + end end end -- cgit v1.2.3 From 16f96238ba59fd81017b1402eb665e55c5dd4ba5 Mon Sep 17 00:00:00 2001 From: Kuldeep Aggarwal Date: Sat, 1 Mar 2014 00:51:35 +0530 Subject: [ci skip] correct select examples and doc, ref [522c0fd] --- activerecord/lib/active_record/relation/query_methods.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 5d38f0dce8..d88858611c 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -202,7 +202,7 @@ module ActiveRecord # fields are retrieved: # # Model.select(:field) - # # => [#] + # # => [#] # # Although in the above example it looks as though this method returns an # array, it actually returns a relation object and can have other query @@ -211,12 +211,12 @@ module ActiveRecord # The argument to the method can also be an array of fields. # # Model.select(:field, :other_field, :and_one_more) - # # => [#] + # # => [#] # # You can also use one or more strings, which will be used unchanged as SELECT fields. # # Model.select('field AS field_one', 'other_field AS field_two') - # # => [#] + # # => [#] # # If an alias was specified, it will be accessible from the resulting objects: # @@ -224,7 +224,7 @@ module ActiveRecord # # => "value" # # Accessing attributes of an object that do not have fields retrieved by a select - # will throw ActiveModel::MissingAttributeError: + # except +id+ will throw ActiveModel::MissingAttributeError: # # Model.select(:field).first.other_field # # => ActiveModel::MissingAttributeError: missing attribute: other_field -- cgit v1.2.3 From 774160b9ad6908435bf3485e7ac98633deff76c6 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Fri, 28 Feb 2014 17:00:38 -0500 Subject: Remove unnecessary db call when replacing. When replacing a has_many association with the same one, there is no need to do a round-trip to the db to create/and drop a new transaction. [fixes #14220] --- activerecord/lib/active_record/associations/collection_association.rb | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb index 270871c866..9a2900843e 100644 --- a/activerecord/lib/active_record/associations/collection_association.rb +++ b/activerecord/lib/active_record/associations/collection_association.rb @@ -359,7 +359,9 @@ module ActiveRecord if owner.new_record? replace_records(other_array, original_target) else - transaction { replace_records(other_array, original_target) } + if other_array != original_target + transaction { replace_records(other_array, original_target) } + end end end -- cgit v1.2.3 From 398b4de011e5bbfd10408ed591e92f192cb37327 Mon Sep 17 00:00:00 2001 From: Vipul A M Date: Mon, 3 Mar 2014 02:35:42 +0530 Subject: Fix warnings due to: - unused variable in PG Adapter. - Ambiguous argument warning from range_test for use - to + Infinity range without brackets. --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index d1fb132b60..9f18fdd3e5 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -822,7 +822,7 @@ module ActiveRecord # populate range types ranges.find_all { |row| type_map.key? row['rngsubtype'].to_i }.each do |row| subtype = type_map[row['rngsubtype'].to_i] - range = OID::Range.new type_map[row['rngsubtype'].to_i] + range = OID::Range.new subtype type_map[row['oid'].to_i] = range end end -- cgit v1.2.3 From 3413b88a3d6b2b022dfb57e42565446b1e024314 Mon Sep 17 00:00:00 2001 From: Erik Michaels-Ober Date: Mon, 3 Mar 2014 19:23:22 -0800 Subject: Replace map.flatten with flat_map in activerecord --- activerecord/lib/active_record/associations.rb | 4 ++-- .../lib/active_record/associations/preloader/through_association.rb | 2 +- .../lib/active_record/connection_adapters/abstract_mysql_adapter.rb | 4 ++-- 3 files changed, 5 insertions(+), 5 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 53f7591226..f725356cd9 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -530,8 +530,8 @@ module ActiveRecord # end # # @firm = Firm.first - # @firm.clients.collect { |c| c.invoices }.flatten # select all invoices for all clients of the firm - # @firm.invoices # selects all invoices by going through the Client join model + # @firm.clients.flat_map { |c| c.invoices } # select all invoices for all clients of the firm + # @firm.invoices # selects all invoices by going through the Client join model # # Similarly you can go through a +has_one+ association on the join model: # diff --git a/activerecord/lib/active_record/associations/preloader/through_association.rb b/activerecord/lib/active_record/associations/preloader/through_association.rb index 2a8530af62..70e97432e4 100644 --- a/activerecord/lib/active_record/associations/preloader/through_association.rb +++ b/activerecord/lib/active_record/associations/preloader/through_association.rb @@ -23,7 +23,7 @@ module ActiveRecord reset_association owners, through_reflection.name - middle_records = through_records.map { |(_,rec)| rec }.flatten + middle_records = through_records.flat_map { |(_,rec)| rec } preloaders = preloader.preload(middle_records, source_reflection.name, 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 23edc8b955..baac9522b6 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -459,7 +459,7 @@ module ActiveRecord end def bulk_change_table(table_name, operations) #:nodoc: - sqls = operations.map do |command, args| + sqls = operations.flat_map do |command, args| table, arguments = args.shift, args method = :"#{command}_sql" @@ -468,7 +468,7 @@ module ActiveRecord else raise "Unknown method called : #{method}(#{arguments.inspect})" end - end.flatten.join(", ") + end.join(", ") execute("ALTER TABLE #{quote_table_name(table_name)} #{sqls}") end -- cgit v1.2.3 From f317cc8bc007978d7b135ddd1acdd7e3d1e582a3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Schu=CC=88rrer?= Date: Mon, 3 Mar 2014 17:44:55 +0100 Subject: Make exists? use bound values. When we build a query with an inline value that is a numeric (e.g. because it's out of range for an int4) PostgreSQL doesn't use an index on the column, since it's now comparing numerics and not int4s. This leads to a _very_ slow query. When we use bound parameters instead of inline values PostgreSQL raises numeric_value_out_of_range since no automatic coercion happens. --- activerecord/lib/active_record/relation/finder_methods.rb | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index 7099bdd285..1ba7fc47c0 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -292,7 +292,12 @@ module ActiveRecord when Array, Hash relation = relation.where(conditions) else - relation = relation.where(table[primary_key].eq(conditions)) if conditions != :none + if conditions != :none + column = columns_hash[primary_key] + substitute = connection.substitute_at(column, bind_values.length) + relation = where(table[primary_key].eq(substitute)) + relation.bind_values += [[column, conditions]] + end end connection.select_value(relation, "#{name} Exists", relation.bind_values) ? true : false -- cgit v1.2.3 From 5c55aafd38f45ac019573f98438ffdbdc8c580f9 Mon Sep 17 00:00:00 2001 From: Dieter Komendera Date: Mon, 9 Dec 2013 18:52:36 +0100 Subject: Add Enum type to postgresql adapter's oids to prevent unknown OID warnings. --- .../lib/active_record/connection_adapters/postgresql/oid.rb | 6 ++++++ .../lib/active_record/connection_adapters/postgresql_adapter.rb | 6 ++++++ 2 files changed, 12 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index e7df073627..697915f3e9 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -229,6 +229,12 @@ This is not reliable and will be removed in the future. end end + class Enum < Type + def type_cast(value) + value.to_s + end + end + class Hstore < Type def type_cast_for_write(value) ConnectionAdapters::PostgreSQLColumn.hstore_to_string value diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 9f18fdd3e5..a56ef91d07 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -801,6 +801,12 @@ module ActiveRecord leaves, nodes = nodes.partition { |row| row['typelem'] == '0' } arrays, nodes = nodes.partition { |row| row['typinput'] == 'array_in' } + # populate the enum types + enums, leaves = leaves.partition { |row| row['typinput'] == 'enum_in' } + enums.each do |row| + type_map[row['oid'].to_i] = OID::Enum.new + end + # populate the base types leaves.find_all { |row| OID.registered_type? row['typname'] }.each do |row| type_map[row['oid'].to_i] = OID::NAMES[row['typname']] -- cgit v1.2.3 From acbd7ab22e5d9179487bd98110234c54535036c4 Mon Sep 17 00:00:00 2001 From: Marcelo Casiraghi Date: Thu, 23 May 2013 00:17:15 -0300 Subject: Allow string hash values on AR order method This behavior has almost no performance impact: String not allowed 66.910000 0.030000 66.940000 ( 67.024976) String allowed 69.360000 0.030000 69.390000 ( 69.503096) Benchmarked with http://git.io/Y0YuRw. --- activerecord/lib/active_record/relation/query_methods.rb | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index d88858611c..a22849f4a6 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1030,10 +1030,13 @@ module ActiveRecord arel.order(*orders) unless orders.empty? end + VALID_DIRECTIONS = [:asc, :desc, 'asc', 'desc'] # :nodoc: + def validate_order_args(args) args.grep(Hash) do |h| - unless (h.values - [:asc, :desc]).empty? - raise ArgumentError, 'Direction should be :asc or :desc' + h.values.map(&:downcase).each do |value| + raise ArgumentError, "Direction '#{value}' is invalid. Valid " \ + "directions are asc and desc." unless VALID_DIRECTIONS.include?(value) end end end @@ -1055,7 +1058,7 @@ module ActiveRecord when Hash arg.map { |field, dir| field = klass.attribute_alias(field) if klass.attribute_alias?(field) - table[field].send(dir) + table[field].send(dir.downcase) } else arg -- cgit v1.2.3 From f6aeb8b1a3687c8523e4a56309fe3736011b2935 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Wed, 5 Mar 2014 10:24:13 +0100 Subject: we only need to support `asc` and `ASC`. No need for mixed cases. #14263 This is a result of the discussion at https://github.com/rails/rails/pull/14263/files#r10291489 --- .../lib/active_record/relation/query_methods.rb | 27 +++++++++++----------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index a22849f4a6..f694a901f4 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -275,15 +275,6 @@ module ActiveRecord # Allows to specify an order attribute: # - # User.order('name') - # => SELECT "users".* FROM "users" ORDER BY name - # - # User.order('name DESC') - # => SELECT "users".* FROM "users" ORDER BY name DESC - # - # User.order('name DESC, email') - # => SELECT "users".* FROM "users" ORDER BY name DESC, email - # # User.order(:name) # => SELECT "users".* FROM "users" ORDER BY "users"."name" ASC # @@ -292,6 +283,15 @@ module ActiveRecord # # User.order(:name, email: :desc) # => SELECT "users".* FROM "users" ORDER BY "users"."name" ASC, "users"."email" DESC + # + # User.order('name') + # => SELECT "users".* FROM "users" ORDER BY name + # + # User.order('name DESC') + # => SELECT "users".* FROM "users" ORDER BY name DESC + # + # User.order('name DESC, email') + # => SELECT "users".* FROM "users" ORDER BY name DESC, email def order(*args) check_if_method_has_arguments!(:order, args) spawn.order!(*args) @@ -1030,13 +1030,14 @@ module ActiveRecord arel.order(*orders) unless orders.empty? end - VALID_DIRECTIONS = [:asc, :desc, 'asc', 'desc'] # :nodoc: + VALID_DIRECTIONS = [:asc, :desc, :ASC, :DESC, + 'asc', 'desc', 'ASC', 'DESC'] # :nodoc: def validate_order_args(args) args.grep(Hash) do |h| - h.values.map(&:downcase).each do |value| - raise ArgumentError, "Direction '#{value}' is invalid. Valid " \ - "directions are asc and desc." unless VALID_DIRECTIONS.include?(value) + h.values.each do |value| + raise ArgumentError, "Direction \"#{value}\" is invalid. Valid " \ + "directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value) end end end -- cgit v1.2.3 From b74eed58b228b49c5298cf0df9c6890d0b8a4ab5 Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Wed, 5 Mar 2014 10:45:37 +0100 Subject: get rid of intermediate arrays. origin: https://github.com/rails/rails/commit/f6aeb8b1a3687c8523e4a56309fe3736011b2935#commitcomment-5569649 --- activerecord/lib/active_record/relation/query_methods.rb | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index f694a901f4..8c005a7222 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -1034,8 +1034,9 @@ module ActiveRecord 'asc', 'desc', 'ASC', 'DESC'] # :nodoc: def validate_order_args(args) - args.grep(Hash) do |h| - h.values.each do |value| + args.each do |arg| + next unless arg.is_a?(Hash) + arg.each do |_key, value| raise ArgumentError, "Direction \"#{value}\" is invalid. Valid " \ "directions are: #{VALID_DIRECTIONS.inspect}" unless VALID_DIRECTIONS.include?(value) end -- cgit v1.2.3 From 2dd2fcf89673afbcf95240ecebaf34826a195164 Mon Sep 17 00:00:00 2001 From: Prem Sichanugrist Date: Tue, 18 Feb 2014 16:13:23 -0500 Subject: Introduce `Rails.gem_version` This method return `Gem::Version.new(Rails.version)`, suggesting a more reliable way to perform version comparison. Example: Rails.version #=> "4.1.2" Rails.gem_version #=> # Rails.version > "4.1.10" #=> false Rails.gem_version > Gem::Version.new("4.1.10") #=> true Gem::Requirement.new("~> 4.1.2") =~ Rails.gem_version #=> true This was originally introduced as `.version` by @charliesome in #8501 but got reverted in #10002 since it was not backward compatible. Also, updating template for `rake update_versions`. --- activerecord/lib/active_record/gem_version.rb | 15 +++++++++++++++ activerecord/lib/active_record/version.rb | 11 ++++------- 2 files changed, 19 insertions(+), 7 deletions(-) create mode 100644 activerecord/lib/active_record/gem_version.rb (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/gem_version.rb b/activerecord/lib/active_record/gem_version.rb new file mode 100644 index 0000000000..4a7aace460 --- /dev/null +++ b/activerecord/lib/active_record/gem_version.rb @@ -0,0 +1,15 @@ +module ActiveRecord + # Returns the version of the currently loaded ActiveRecord as a Gem::Version + def self.gem_version + Gem::Version.new VERSION::STRING + end + + module VERSION + MAJOR = 4 + MINOR = 2 + TINY = 0 + PRE = "alpha" + + STRING = [MAJOR, MINOR, TINY, PRE].compact.join(".") + end +end diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb index 5eb7f7e205..cf76a13b44 100644 --- a/activerecord/lib/active_record/version.rb +++ b/activerecord/lib/active_record/version.rb @@ -1,11 +1,8 @@ +require_relative 'gem_version' + module ActiveRecord - # Returns the version of the currently loaded ActiveRecord as a Gem::Version + # Returns the version of the currently loaded ActiveRecord as a Gem::Version def self.version - Gem::Version.new "4.2.0.alpha" - end - - module VERSION #:nodoc: - MAJOR, MINOR, TINY, PRE = ActiveRecord.version.segments - STRING = ActiveRecord.version.to_s + gem_version end end -- cgit v1.2.3 From 24434880d91ceae15e68fdd90b466ec29627388a Mon Sep 17 00:00:00 2001 From: dmathieu <42@dmathieu.com> Date: Fri, 7 Mar 2014 14:52:44 +0100 Subject: unscope doesn't remove only the default_scope, but all of them. [ci-skip] Closes rails/rails#14294 --- activerecord/lib/active_record/scoping/default.rb | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index 01fec31544..da01464eb5 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -11,7 +11,7 @@ module ActiveRecord end module ClassMethods - # Returns a scope for the model without the +default_scope+. + # Returns a scope for the model without the previously set scopes. # # class Post < ActiveRecord::Base # def self.default_scope @@ -19,11 +19,12 @@ module ActiveRecord # end # end # - # Post.all # Fires "SELECT * FROM posts WHERE published = true" - # Post.unscoped.all # Fires "SELECT * FROM posts" + # Post.all # Fires "SELECT * FROM posts WHERE published = true" + # Post.unscoped.all # Fires "SELECT * FROM posts" + # Post.where(published: false).unscoped.app # Fires "SELECT * FROM posts" # # This method also accepts a block. All queries inside the block will - # not use the +default_scope+: + # not use the previously set scopes. # # Post.unscoped { # Post.limit(10) # Fires "SELECT * FROM posts LIMIT 10" -- cgit v1.2.3 From 3f1699a780de5cd0c3433bc3427cc43f08f77040 Mon Sep 17 00:00:00 2001 From: dmathieu <42@dmathieu.com> Date: Fri, 7 Mar 2014 15:06:20 +0100 Subject: fix typo app -> all Thank you @bquorning --- activerecord/lib/active_record/scoping/default.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/scoping/default.rb b/activerecord/lib/active_record/scoping/default.rb index da01464eb5..73ab3b39aa 100644 --- a/activerecord/lib/active_record/scoping/default.rb +++ b/activerecord/lib/active_record/scoping/default.rb @@ -21,7 +21,7 @@ module ActiveRecord # # Post.all # Fires "SELECT * FROM posts WHERE published = true" # Post.unscoped.all # Fires "SELECT * FROM posts" - # Post.where(published: false).unscoped.app # Fires "SELECT * FROM posts" + # Post.where(published: false).unscoped.all # Fires "SELECT * FROM posts" # # This method also accepts a block. All queries inside the block will # not use the previously set scopes. -- cgit v1.2.3 From 0e5fb0ba9cccf511745e14f3eb6e9f408a1a827c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rafael=20Mendon=C3=A7a=20Fran=C3=A7a?= Date: Mon, 10 Mar 2014 10:08:00 -0300 Subject: Whitespaces --- activerecord/lib/active_record/validations/uniqueness.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index 49b0f73219..82c2b9439b 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -13,7 +13,7 @@ module ActiveRecord def validate_each(record, attribute, value) finder_class = find_finder_class_for(record) table = finder_class.arel_table - value = map_enum_attribute(finder_class,attribute,value) + value = map_enum_attribute(finder_class, attribute, value) value = deserialize_attribute(record, attribute, value) relation = build_relation(finder_class, table, attribute, value) @@ -93,7 +93,7 @@ module ActiveRecord value end - def map_enum_attribute(klass,attribute,value) + def map_enum_attribute(klass, attribute, value) mapping = klass.enum_mapping_for(attribute.to_s) value = mapping[value] if value && mapping value -- cgit v1.2.3 From e5f15a83656f6d005dab40a30fb9f7fa2cf65d77 Mon Sep 17 00:00:00 2001 From: Arthur Neves Date: Mon, 10 Mar 2014 11:37:33 -0400 Subject: Fixes STI when 2+ levels deep. PR #14052 Added a regression where it was only looking for methods in one level up, So when the method was defined in a 2+ levels up the inheritance chain, the method was not found as defined. --- activerecord/lib/active_record/attribute_methods.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_methods.rb b/activerecord/lib/active_record/attribute_methods.rb index 57ceec2fc5..ea48a13ea8 100644 --- a/activerecord/lib/active_record/attribute_methods.rb +++ b/activerecord/lib/active_record/attribute_methods.rb @@ -105,9 +105,9 @@ module ActiveRecord super else # If B < A and A defines its own attribute method, then we don't want to overwrite that. - defined = method_defined_within?(method_name, superclass) && - superclass.instance_method(method_name).owner != superclass.generated_attribute_methods - defined || super + defined = method_defined_within?(method_name, superclass, superclass.generated_attribute_methods) + base_defined = Base.method_defined?(method_name) || Base.private_method_defined?(method_name) + defined && !base_defined || super end end -- cgit v1.2.3 From b3e0da3062f809599fb4da9f9a29ed45aebd1ff6 Mon Sep 17 00:00:00 2001 From: lsylvester Date: Tue, 11 Mar 2014 08:10:25 +1100 Subject: register OID for PostgreSQL citex datatype [Troy Kruthoff & Lachlan Sylvester] citext makes it possible to use AR Hash finders for case-insensitive matching as sql UPPER/LOWER functions are not needed. --- .../lib/active_record/connection_adapters/postgresql/oid.rb | 1 + .../lib/active_record/connection_adapters/postgresql_adapter.rb | 9 ++++++++- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb index 697915f3e9..5d32aaed50 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb @@ -375,6 +375,7 @@ This is not reliable and will be removed in the future. register_type 'circle', OID::Text.new register_type 'hstore', OID::Hstore.new register_type 'json', OID::Json.new + register_type 'citext', OID::Text.new register_type 'ltree', OID::Text.new register_type 'cidr', OID::Cidr.new diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index a56ef91d07..f7b053aec6 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -215,6 +215,8 @@ module ActiveRecord # Character types when /^(?:character varying|bpchar)(?:\(\d+\))?$/ :string + when /^citext(?:\(\d+\))?$/ + :citext # Binary data types when 'bytea' :binary @@ -393,6 +395,10 @@ module ActiveRecord column name, type, options end + def citext(name, options = {}) + column(name, 'citext', options) + end + def column(name, type = nil, options = {}) super column = self[name] @@ -441,7 +447,8 @@ module ActiveRecord macaddr: { name: "macaddr" }, uuid: { name: "uuid" }, json: { name: "json" }, - ltree: { name: "ltree" } + ltree: { name: "ltree" }, + citext: { name: "citext" } } include Quoting -- cgit v1.2.3 From 3f5339f48e3ce3eb40eb51fb1b686914a719a26a Mon Sep 17 00:00:00 2001 From: Yves Senn Date: Tue, 11 Mar 2014 08:27:59 +0100 Subject: `change_table` supports `citext`. Follow up to #12523. --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index f7b053aec6..e5f7913c70 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -355,6 +355,10 @@ module ActiveRecord def json(name, options = {}) column(name, 'json', options) end + + def citext(name, options = {}) + column(name, 'citext', options) + end end class TableDefinition < ActiveRecord::ConnectionAdapters::TableDefinition -- cgit v1.2.3 From df5a38fc6aeb8dfaa816fcbe0efb3fe4de169833 Mon Sep 17 00:00:00 2001 From: Tatsuhiko Miyagawa Date: Mon, 12 Nov 2012 13:48:50 -0800 Subject: MySQL 5.6 and later supports microsecond precision in datetime. You might want to branch it to include this only for 5.6, but passing these values to < 5.6 doesn't cause issues either. --- .../lib/active_record/connection_adapters/mysql2_adapter.rb | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb index b07b0cb826..2b5049f5a5 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql2_adapter.rb @@ -83,6 +83,14 @@ module ActiveRecord @connection.escape(string) end + def quoted_date(value) + if value.acts_like?(:time) && value.respond_to?(:usec) + "#{super}.#{sprintf("%06d", value.usec)}" + else + super + end + end + # CONNECTION MANAGEMENT ==================================== def active? -- cgit v1.2.3 From 40847a7831a2bccaeb04b796c5534418d8b3c334 Mon Sep 17 00:00:00 2001 From: Mohamed Wael Khobalatte Date: Wed, 12 Mar 2014 16:57:45 +0100 Subject: Enhance docs for update_attribute [ci-skip] --- activerecord/lib/active_record/persistence.rb | 2 ++ 1 file changed, 2 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb index 203928fb3f..4e63206cf4 100644 --- a/activerecord/lib/active_record/persistence.rb +++ b/activerecord/lib/active_record/persistence.rb @@ -214,6 +214,8 @@ module ActiveRecord # # This method raises an +ActiveRecord::ActiveRecordError+ if the # attribute is marked as readonly. + # + # See also +update_column+. def update_attribute(name, value) name = name.to_s verify_readonly_attribute(name) -- cgit v1.2.3 From 15720df1808b249bae91e5600d6f0676990a7de0 Mon Sep 17 00:00:00 2001 From: Julian Simioni Date: Wed, 12 Mar 2014 15:24:02 -0700 Subject: Use Sqlite3 adapter in examples Two bits of example code use sqlite as an adapter, which doesn't exist. Using the code verbatim will raise a LoadError exception: ActiveRecord::Base.establish_connection( "adapter" => "sqlite", "database" => "db.sqlite" ) # => LoadError: Could not load 'active_record/connection_adapters/sqlite_adapter'... Considering this is code a lot of people new to Rails might be running, it's especially confusing. Closes #14367 [ci skip] --- activerecord/lib/active_record/connection_handling.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_handling.rb b/activerecord/lib/active_record/connection_handling.rb index 4ba4e09777..bbb866cedf 100644 --- a/activerecord/lib/active_record/connection_handling.rb +++ b/activerecord/lib/active_record/connection_handling.rb @@ -18,14 +18,14 @@ module ActiveRecord # Example for SQLite database: # # ActiveRecord::Base.establish_connection( - # adapter: "sqlite", + # adapter: "sqlite3", # database: "path/to/dbfile" # ) # # Also accepts keys as strings (for parsing from YAML for example): # # ActiveRecord::Base.establish_connection( - # "adapter" => "sqlite", + # "adapter" => "sqlite3", # "database" => "path/to/dbfile" # ) # -- cgit v1.2.3 From e88da370f190cabd1e9750c5b3531735950ab415 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Thu, 13 Mar 2014 10:55:52 -0700 Subject: make tests pass on Ruby 2.2 Apparently we've been using a buggy feature for the past 6 years: https://bugs.ruby-lang.org/issues/9593 --- .../lib/active_record/associations/has_many_association.rb | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations/has_many_association.rb b/activerecord/lib/active_record/associations/has_many_association.rb index 6457182195..3e4b7902c0 100644 --- a/activerecord/lib/active_record/associations/has_many_association.rb +++ b/activerecord/lib/active_record/associations/has_many_association.rb @@ -71,15 +71,15 @@ module ActiveRecord [association_scope.limit_value, count].compact.min end - def has_cached_counter?(reflection = reflection) + def has_cached_counter?(reflection = reflection()) owner.attribute_present?(cached_counter_attribute_name(reflection)) end - def cached_counter_attribute_name(reflection = reflection) + def cached_counter_attribute_name(reflection = reflection()) options[:counter_cache] || "#{reflection.name}_count" end - def update_counter(difference, reflection = reflection) + def update_counter(difference, reflection = reflection()) if has_cached_counter?(reflection) counter = cached_counter_attribute_name(reflection) owner.class.update_counters(owner.id, counter => difference) @@ -98,7 +98,7 @@ module ActiveRecord # it will be decremented twice. # # Hence this method. - def inverse_updates_counter_cache?(reflection = reflection) + def inverse_updates_counter_cache?(reflection = reflection()) counter_name = cached_counter_attribute_name(reflection) reflection.klass.reflect_on_all_associations(:belongs_to).any? { |inverse_reflection| inverse_reflection.counter_cache_column == counter_name -- cgit v1.2.3