From e911ed1f0f1633b0ae1b5146805eee6388b1f02f Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 2 Nov 2010 01:42:47 +0000 Subject: Ensure save always updates timestamps when serialized attributes are present --- activerecord/lib/active_record/attribute_methods/dirty.rb | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 439880c1fa..78a941b5d4 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -41,6 +41,10 @@ module ActiveRecord end end + def changed? + super || (attributes.keys & self.class.serialized_attributes.keys).present? + end + private # Wrap write_attribute to remember original attribute value. def write_attribute(attr, value) -- cgit v1.2.3 From 18b6aa65389cd10d62dc0005e632a3a2d474dec4 Mon Sep 17 00:00:00 2001 From: Pratik Naik Date: Tue, 2 Nov 2010 01:45:30 +0000 Subject: Make should_record_timestamps? serialization aware rather than object#changed? --- activerecord/lib/active_record/attribute_methods/dirty.rb | 4 ---- activerecord/lib/active_record/timestamp.rb | 2 +- 2 files changed, 1 insertion(+), 5 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/attribute_methods/dirty.rb b/activerecord/lib/active_record/attribute_methods/dirty.rb index 78a941b5d4..439880c1fa 100644 --- a/activerecord/lib/active_record/attribute_methods/dirty.rb +++ b/activerecord/lib/active_record/attribute_methods/dirty.rb @@ -41,10 +41,6 @@ module ActiveRecord end end - def changed? - super || (attributes.keys & self.class.serialized_attributes.keys).present? - end - private # Wrap write_attribute to remember original attribute value. def write_attribute(attr, value) diff --git a/activerecord/lib/active_record/timestamp.rb b/activerecord/lib/active_record/timestamp.rb index a7583f06cc..230adf6b2b 100644 --- a/activerecord/lib/active_record/timestamp.rb +++ b/activerecord/lib/active_record/timestamp.rb @@ -61,7 +61,7 @@ module ActiveRecord end def should_record_timestamps? - record_timestamps && (!partial_updates? || changed?) + record_timestamps && (!partial_updates? || changed? || (attributes.keys & self.class.serialized_attributes.keys).present?) end def timestamp_attributes_for_update_in_model -- cgit v1.2.3 From 710dcf826a073720b817389fe1b7013fb87be659 Mon Sep 17 00:00:00 2001 From: sblackstone Date: Wed, 3 Nov 2010 14:12:28 -0400 Subject: Association Proxy should not undefine the default respond_to_missing --- activerecord/lib/active_record/associations/association_proxy.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations/association_proxy.rb b/activerecord/lib/active_record/associations/association_proxy.rb index 0c12c3737d..ac2aa46edf 100644 --- a/activerecord/lib/active_record/associations/association_proxy.rb +++ b/activerecord/lib/active_record/associations/association_proxy.rb @@ -53,7 +53,7 @@ module ActiveRecord alias_method :proxy_respond_to?, :respond_to? alias_method :proxy_extend, :extend delegate :to_param, :to => :proxy_target - instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|proxy_/ } + instance_methods.each { |m| undef_method m unless m.to_s =~ /^(?:nil\?|send|object_id|to_a)$|^__|^respond_to_missing|proxy_/ } def initialize(owner, reflection) @owner, @reflection = owner, reflection -- cgit v1.2.3 From 9a08517c8dad9824bc24c1c9874343d3d70b5360 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 10:08:38 -0700 Subject: converted exec to exec_query for sqlite --- .../abstract/database_statements.rb | 2 +- .../connection_adapters/sqlite_adapter.rb | 22 +++++++++++----------- 2 files changed, 12 insertions(+), 12 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb index 6178130c00..ee9a0af35c 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb @@ -50,7 +50,7 @@ module ActiveRecord # Executes +sql+ statement in the context of this connection using # +binds+ as the bind substitutes. +name+ is logged along with # the executed +sql+ statement. - def exec(sql, name = 'SQL', binds = []) + def exec_query(sql, name = 'SQL', binds = []) end # Returns the last auto-generated ID from the affected table. diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index fc4d84a4f2..d76fc4103e 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -143,7 +143,7 @@ module ActiveRecord # DATABASE STATEMENTS ====================================== - def exec(sql, name = nil, binds = []) + def exec_query(sql, name = nil, binds = []) log(sql, name) do # Don't cache statements without bind values @@ -186,7 +186,7 @@ module ActiveRecord alias :create :insert_sql def select_rows(sql, name = nil) - exec(sql, name).rows + exec_query(sql, name).rows end def begin_db_transaction #:nodoc: @@ -210,7 +210,7 @@ module ActiveRecord WHERE type = 'table' AND NOT name = 'sqlite_sequence' SQL - exec(sql, name).map do |row| + exec_query(sql, name).map do |row| row['name'] end end @@ -222,12 +222,12 @@ module ActiveRecord end def indexes(table_name, name = nil) #:nodoc: - exec("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row| + exec_query("PRAGMA index_list(#{quote_table_name(table_name)})", name).map do |row| IndexDefinition.new( table_name, row['name'], row['unique'] != 0, - exec("PRAGMA index_info('#{row['name']}')").map { |col| + exec_query("PRAGMA index_info('#{row['name']}')").map { |col| col['name'] }) end @@ -241,11 +241,11 @@ module ActiveRecord end def remove_index!(table_name, index_name) #:nodoc: - exec "DROP INDEX #{quote_column_name(index_name)}" + exec_query "DROP INDEX #{quote_column_name(index_name)}" end def rename_table(name, new_name) - exec "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}" + exec_query "ALTER TABLE #{quote_table_name(name)} RENAME TO #{quote_table_name(new_name)}" end # See: http://www.sqlite.org/lang_altertable.html @@ -282,7 +282,7 @@ module ActiveRecord def change_column_null(table_name, column_name, null, default = nil) unless null || default.nil? - exec("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") + exec_query("UPDATE #{quote_table_name(table_name)} SET #{quote_column_name(column_name)}=#{quote(default)} WHERE #{quote_column_name(column_name)} IS NULL") end alter_table(table_name) do |definition| definition[column_name].null = null @@ -314,7 +314,7 @@ module ActiveRecord protected def select(sql, name = nil, binds = []) #:nodoc: - result = exec(sql, name, binds) + result = exec_query(sql, name, binds) columns = result.columns.map { |column| column.sub(/^"?\w+"?\./, '') } @@ -399,11 +399,11 @@ module ActiveRecord quoted_columns = columns.map { |col| quote_column_name(col) } * ',' quoted_to = quote_table_name(to) - exec("SELECT * FROM #{quote_table_name(from)}").each do |row| + exec_query("SELECT * FROM #{quote_table_name(from)}").each do |row| sql = "INSERT INTO #{quoted_to} (#{quoted_columns}) VALUES (" sql << columns.map {|col| quote row[column_mappings[col]]} * ', ' sql << ')' - exec sql + exec_query sql end end -- cgit v1.2.3 From 0f45f2366945a19e1413d15608b917e1b7987fa5 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 10:15:33 -0700 Subject: renaming exec in the PG adapter --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (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 58c0f85dc2..426360b470 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -398,7 +398,7 @@ module ActiveRecord # Set the authorized user for this session def session_auth=(user) clear_cache! - exec "SET SESSION AUTHORIZATION #{user}" + exec_query "SET SESSION AUTHORIZATION #{user}" end # REFERENTIAL INTEGRITY ==================================== @@ -532,7 +532,7 @@ module ActiveRecord Arel.sql("$#{current_values.length + 1}") end - def exec(sql, name = 'SQL', binds = []) + def exec_query(sql, name = 'SQL', binds = []) return exec_no_cache(sql, name) if binds.empty? log(sql, name) do @@ -1040,7 +1040,7 @@ module ActiveRecord # Executes a SELECT query and returns the results, performing any data type # conversions that are required to be performed here instead of in PostgreSQLColumn. def select(sql, name = nil, binds = []) - exec(sql, name, binds).to_a + exec_query(sql, name, binds).to_a end def select_raw(sql, name = nil) -- cgit v1.2.3 From d5e45931a0f3d36515d6048fd9cb13f641018571 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 10:21:14 -0700 Subject: renaming exec in the mysql adapter --- activerecord/lib/active_record/connection_adapters/mysql_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb index 7d47d06ae1..ce2352486b 100644 --- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb @@ -326,7 +326,7 @@ module ActiveRecord @statements.clear end - def exec(sql, name = 'SQL', binds = []) + def exec_query(sql, name = 'SQL', binds = []) log(sql, name) do result = nil @@ -708,7 +708,7 @@ module ActiveRecord def select(sql, name = nil, binds = []) @connection.query_with_result = true - rows = exec(sql, name, binds).to_a + rows = exec_query(sql, name, binds).to_a @connection.more_results && @connection.next_result # invoking stored procedures with CLIENT_MULTI_RESULTS requires this to tidy up else connection will be dropped rows end -- cgit v1.2.3 From 3146aa68fd03ea4392b45f1c8771675a9c850471 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Nov 2010 20:48:02 -0200 Subject: Fixes queries using limits and punctuation in order, removes order("col1, col2") usage in favor of order(["col1", "col2"}) [#4597 state:committed] --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 6 +++--- activerecord/lib/active_record/relation/finder_methods.rb | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) (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 426360b470..942ea9b297 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -932,12 +932,12 @@ module ActiveRecord # requires that the ORDER BY include the distinct column. # # distinct("posts.id", "posts.created_at desc") - def distinct(columns, order_by) #:nodoc: - return "DISTINCT #{columns}" if order_by.blank? + def distinct(columns, orders) #:nodoc: + return "DISTINCT #{columns}" if orders.empty? # Construct a clean list of column names from the ORDER BY clause, removing # any ASC/DESC modifiers - order_columns = order_by.split(',').collect { |s| s.split.first } + order_columns = orders.collect { |s| s.split.first } order_columns.delete_if { |c| c.blank? } order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" } diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index fe1ef2e2e3..ab9f10b380 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -222,7 +222,7 @@ module ActiveRecord end def construct_limited_ids_condition(relation) - orders = relation.order_values.join(", ") + orders = relation.order_values values = @klass.connection.distinct("#{@klass.connection.quote_table_name @klass.table_name}.#{@klass.primary_key}", orders) ids_array = relation.select(values).collect {|row| row[@klass.primary_key]} -- cgit v1.2.3 From 00261a187ef55c284156ef22b31909ffbe51b0f2 Mon Sep 17 00:00:00 2001 From: Santiago Pastorino Date: Thu, 4 Nov 2010 21:11:33 -0200 Subject: Avoid warning: shadowing outer local variable --- .../lib/active_record/connection_adapters/postgresql_adapter.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (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 942ea9b297..e7fb8524ce 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -714,8 +714,8 @@ module ActiveRecord # Returns the list of all column definitions for a table. def columns(table_name, name = nil) # Limit, precision, and scale are all handled by the superclass. - column_definitions(table_name).collect do |name, type, default, notnull| - PostgreSQLColumn.new(name, default, type, notnull == 'f') + column_definitions(table_name).collect do |column_name, type, default, notnull| + PostgreSQLColumn.new(column_name, default, type, notnull == 'f') end end -- cgit v1.2.3 From 06d518a32398a4dc7564f45aa19575ea7fa702da Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 11:48:40 -0700 Subject: stop recursively calling exists? --- activerecord/lib/active_record/relation/finder_methods.rb | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (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 ab9f10b380..e9e9c85122 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -171,14 +171,16 @@ module ActiveRecord def exists?(id = nil) id = id.id if ActiveRecord::Base === id + relation = select(primary_key).limit(1) + case id when Array, Hash - where(id).exists? + relation = relation.where(id) else - relation = select(primary_key).limit(1) relation = relation.where(primary_key.eq(id)) if id - relation.first ? true : false end + + relation.first ? true : false end protected -- cgit v1.2.3 From a79e1de90a6062926a8ec11870702923eb691944 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 16:27:39 -0700 Subject: reduce method calls to the join base object --- activerecord/lib/active_record/associations.rb | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index dc466eafc2..3d754af5b3 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1874,12 +1874,14 @@ module ActiveRecord end def instantiate(rows) - rows.each_with_index do |row, i| - primary_id = join_base.record_id(row) + primary_key = join_base.aliased_primary_key + + rows.each_with_index do |model, i| + primary_id = model[primary_key] unless @base_records_hash[primary_id] - @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(row)) + @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(model)) end - construct(@base_records_hash[primary_id], @associations, join_associations.dup, row) + construct(@base_records_hash[primary_id], @associations, join_associations.dup, model) end remove_duplicate_results!(join_base.active_record, @base_records_in_order, @associations) return @base_records_in_order -- cgit v1.2.3 From d89d70236177a074b8357b6104248c86c30c2502 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 16:30:38 -0700 Subject: index is not used, so removing it --- activerecord/lib/active_record/associations.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 3d754af5b3..680810f031 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1876,7 +1876,7 @@ module ActiveRecord def instantiate(rows) primary_key = join_base.aliased_primary_key - rows.each_with_index do |model, i| + rows.each do |model| primary_id = model[primary_key] unless @base_records_hash[primary_id] @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(model)) -- cgit v1.2.3 From c43d909ee28484c5e7d7d84b1228e10212d20737 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 16:56:41 -0700 Subject: simplify instantiate in the join parts object --- activerecord/lib/active_record/associations.rb | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 680810f031..0fc8740dce 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1839,8 +1839,6 @@ module ActiveRecord @join_parts = [JoinBase.new(base, joins)] @associations = {} @reflections = [] - @base_records_hash = {} - @base_records_in_order = [] @table_aliases = Hash.new(0) @table_aliases[base.table_name] = 1 build(associations) @@ -1875,16 +1873,17 @@ module ActiveRecord def instantiate(rows) primary_key = join_base.aliased_primary_key + base_records_hash = {} rows.each do |model| primary_id = model[primary_key] - unless @base_records_hash[primary_id] - @base_records_in_order << (@base_records_hash[primary_id] = join_base.instantiate(model)) - end - construct(@base_records_hash[primary_id], @associations, join_associations.dup, model) + base_records_hash[primary_id] ||= join_base.instantiate(model) + construct(base_records_hash[primary_id], @associations, join_associations.dup, model) end - remove_duplicate_results!(join_base.active_record, @base_records_in_order, @associations) - return @base_records_in_order + + records = base_records_hash.values + remove_duplicate_results!(join_base.active_record, records, @associations) + records end def remove_duplicate_results!(base, records, associations) -- cgit v1.2.3 From 39a80567918af298b39898d78062e7a8fb5da601 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Fri, 5 Nov 2010 17:08:56 -0700 Subject: only call to_s on the association variable once --- activerecord/lib/active_record/associations.rb | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 0fc8740dce..8d415cdfdf 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1983,10 +1983,13 @@ module ActiveRecord def construct(parent, associations, join_parts, row) case associations when Symbol, String + associations = associations.to_s + join_part = join_parts.detect { |j| - j.reflection.name.to_s == associations.to_s && + j.reflection.name.to_s == associations && j.parent_table_name == parent.class.table_name } - raise(ConfigurationError, "No such association") if join_part.nil? + + raise(ConfigurationError, "No such association") unless join_part join_parts.delete(join_part) construct_association(parent, join_part, row) -- cgit v1.2.3 From c11102d4f80267e3774985329ea93e7368e8684f Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sat, 6 Nov 2010 14:32:41 -0700 Subject: make sure we keep parent records in order --- activerecord/lib/active_record/associations.rb | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index 8d415cdfdf..aad0cbb895 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1873,15 +1873,15 @@ module ActiveRecord def instantiate(rows) primary_key = join_base.aliased_primary_key - base_records_hash = {} + parents = {} - rows.each do |model| + records = rows.map { |model| primary_id = model[primary_key] - base_records_hash[primary_id] ||= join_base.instantiate(model) - construct(base_records_hash[primary_id], @associations, join_associations.dup, model) - end + parent = parents[primary_id] ||= join_base.instantiate(model) + construct(parent, @associations, join_associations.dup, model) + parent + }.uniq - records = base_records_hash.values remove_duplicate_results!(join_base.active_record, records, @associations) records end -- cgit v1.2.3 From 1acc086278c974d7a3cdb0459cd65f73641abe33 Mon Sep 17 00:00:00 2001 From: Aaron Patterson Date: Sat, 6 Nov 2010 18:20:02 -0700 Subject: reduce duplication in assiciations #construct() --- activerecord/lib/active_record/associations.rb | 12 +++--------- 1 file changed, 3 insertions(+), 9 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/associations.rb b/activerecord/lib/active_record/associations.rb index aad0cbb895..c84673e6a6 100644 --- a/activerecord/lib/active_record/associations.rb +++ b/activerecord/lib/active_record/associations.rb @@ -1983,10 +1983,10 @@ module ActiveRecord def construct(parent, associations, join_parts, row) case associations when Symbol, String - associations = associations.to_s + name = associations.to_s join_part = join_parts.detect { |j| - j.reflection.name.to_s == associations && + j.reflection.name.to_s == name && j.parent_table_name == parent.class.table_name } raise(ConfigurationError, "No such association") unless join_part @@ -1999,13 +1999,7 @@ module ActiveRecord end when Hash associations.sort_by { |k,_| k.to_s }.each do |name, assoc| - join_part = join_parts.detect{ |j| - j.reflection.name.to_s == name.to_s && - j.parent_table_name == parent.class.table_name } - raise(ConfigurationError, "No such association") if join_part.nil? - - association = construct_association(parent, join_part, row) - join_parts.delete(join_part) + association = construct(parent, name, join_parts, row) construct(association, assoc, join_parts, row) if association end else -- cgit v1.2.3 From 6709078eb1f61a1f8d54fcd82e9a07e96383ec8a Mon Sep 17 00:00:00 2001 From: Raimonds Simanovskis Date: Sun, 7 Nov 2010 09:54:43 -0200 Subject: use column names as order by complex function parameters, fix for postgresql adapter to correctly remove ASC/DESC Signed-off-by: Santiago Pastorino --- .../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 e7fb8524ce..ccc5085b84 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -937,7 +937,7 @@ module ActiveRecord # Construct a clean list of column names from the ORDER BY clause, removing # any ASC/DESC modifiers - order_columns = orders.collect { |s| s.split.first } + order_columns = orders.collect { |s| s =~ /^(.+)\s+(ASC|DESC)\s*$/i ? $1 : s } order_columns.delete_if { |c| c.blank? } order_columns = order_columns.zip((0...order_columns.size).to_a).map { |s,i| "#{s} AS alias_#{i}" } -- cgit v1.2.3 From 3d6eea0221f0092cb3c3270c2a9bdf31745d1b2d Mon Sep 17 00:00:00 2001 From: Michael Koziarski Date: Mon, 8 Nov 2010 10:16:40 +1300 Subject: Update the validates_uniqueness_of documentation to tell you to use a unique index. The other options mentioned were not good ideas and disclaimed as such in the documentation. --- .../lib/active_record/validations/uniqueness.rb | 42 +++++++++------------- 1 file changed, 17 insertions(+), 25 deletions(-) (limited to 'activerecord/lib') diff --git a/activerecord/lib/active_record/validations/uniqueness.rb b/activerecord/lib/active_record/validations/uniqueness.rb index cb1d2ae421..a25558bd80 100644 --- a/activerecord/lib/active_record/validations/uniqueness.rb +++ b/activerecord/lib/active_record/validations/uniqueness.rb @@ -154,33 +154,25 @@ module ActiveRecord # | # title! # # This could even happen if you use transactions with the 'serializable' - # isolation level. There are several ways to get around this problem: + # isolation level. The best way to work around this problem is to add a unique + # index to the database table using + # ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the + # rare case that a race condition occurs, the database will guarantee + # the field's uniqueness. # - # - By locking the database table before validating, and unlocking it after - # saving. However, table locking is very expensive, and thus not - # recommended. - # - By locking a lock file before validating, and unlocking it after saving. - # This does not work if you've scaled your Rails application across - # multiple web servers (because they cannot share lock files, or cannot - # do that efficiently), and thus not recommended. - # - Creating a unique index on the field, by using - # ActiveRecord::ConnectionAdapters::SchemaStatements#add_index. In the - # rare case that a race condition occurs, the database will guarantee - # the field's uniqueness. + # When the database catches such a duplicate insertion, + # ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid + # exception. You can either choose to let this error propagate (which + # will result in the default Rails exception page being shown), or you + # can catch it and restart the transaction (e.g. by telling the user + # that the title already exists, and asking him to re-enter the title). + # This technique is also known as optimistic concurrency control: + # http://en.wikipedia.org/wiki/Optimistic_concurrency_control # - # When the database catches such a duplicate insertion, - # ActiveRecord::Base#save will raise an ActiveRecord::StatementInvalid - # exception. You can either choose to let this error propagate (which - # will result in the default Rails exception page being shown), or you - # can catch it and restart the transaction (e.g. by telling the user - # that the title already exists, and asking him to re-enter the title). - # This technique is also known as optimistic concurrency control: - # http://en.wikipedia.org/wiki/Optimistic_concurrency_control - # - # Active Record currently provides no way to distinguish unique - # index constraint errors from other types of database errors, so you - # will have to parse the (database-specific) exception message to detect - # such a case. + # Active Record currently provides no way to distinguish unique + # index constraint errors from other types of database errors, so you + # will have to parse the (database-specific) exception message to detect + # such a case. # def validates_uniqueness_of(*attr_names) validates_with UniquenessValidator, _merge_attributes(attr_names) -- cgit v1.2.3