aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
Diffstat (limited to 'activerecord/lib/active_record')
-rw-r--r--activerecord/lib/active_record/attribute_set.rb12
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/cast.rb43
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb36
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb28
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb2
-rw-r--r--activerecord/lib/active_record/core.rb8
-rw-r--r--activerecord/lib/active_record/counter_cache.rb2
-rw-r--r--activerecord/lib/active_record/inheritance.rb8
-rw-r--r--activerecord/lib/active_record/migration.rb13
-rw-r--r--activerecord/lib/active_record/persistence.rb1
-rw-r--r--activerecord/lib/active_record/relation/calculations.rb2
-rw-r--r--activerecord/lib/active_record/tasks/database_tasks.rb2
-rw-r--r--activerecord/lib/active_record/tasks/sqlite_database_tasks.rb6
-rw-r--r--activerecord/lib/active_record/type/string.rb8
15 files changed, 76 insertions, 96 deletions
diff --git a/activerecord/lib/active_record/attribute_set.rb b/activerecord/lib/active_record/attribute_set.rb
index 8a964fb03c..64df6f6358 100644
--- a/activerecord/lib/active_record/attribute_set.rb
+++ b/activerecord/lib/active_record/attribute_set.rb
@@ -52,6 +52,18 @@ module ActiveRecord
super
end
+ def reset(key)
+ if include?(key)
+ write_from_database(key, nil)
+ end
+ end
+
+ def ensure_initialized(key)
+ unless self[key].initialized?
+ write_from_database(key, nil)
+ end
+ end
+
protected
attr_reader :attributes
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
index c916c0795d..5b3e88fb08 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
@@ -2,54 +2,11 @@ module ActiveRecord
module ConnectionAdapters
module PostgreSQL
module Cast # :nodoc:
- def hstore_to_string(object) # :nodoc:
- if Hash === object
- string = object.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
- string
- else
- object
- end
- end
-
- def string_to_hstore(string) # :nodoc:
- if string.nil?
- nil
- elsif String === string
- Hash[string.scan(HstorePair).map { |k, v|
- v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
- k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
- [k, v]
- }]
- else
- string
- end
- end
-
def range_to_string(object) # :nodoc:
from = object.begin.respond_to?(:infinite?) && object.begin.infinite? ? '' : object.begin
to = object.end.respond_to?(:infinite?) && object.end.infinite? ? '' : object.end
"[#{from},#{to}#{object.exclude_end? ? ')' : ']'}"
end
-
- private
-
- HstorePair = begin
- quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
- unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
- /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
- end
-
- def escape_hstore(value)
- if value.nil?
- 'NULL'
- else
- if value == ""
- '""'
- else
- '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
- end
- end
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb
index 26c5d3d78f..78ef94b912 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/float.rb
@@ -7,6 +7,7 @@ module ActiveRecord
def cast_value(value)
case value
+ when ::Float then value
when 'Infinity' then ::Float::INFINITY
when '-Infinity' then -::Float::INFINITY
when 'NaN' then ::Float::NAN
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
index 57b20477df..be4525c94f 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid/hstore.rb
@@ -10,16 +10,48 @@ module ActiveRecord
end
def type_cast_from_database(value)
- ConnectionAdapters::PostgreSQLColumn.string_to_hstore(value)
+ if value.is_a?(::String)
+ ::Hash[value.scan(HstorePair).map { |k, v|
+ v = v.upcase == 'NULL' ? nil : v.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
+ k = k.gsub(/\A"(.*)"\Z/m,'\1').gsub(/\\(.)/, '\1')
+ [k, v]
+ }]
+ else
+ value
+ end
end
def type_cast_for_database(value)
- ConnectionAdapters::PostgreSQLColumn.hstore_to_string(value)
+ if value.is_a?(::Hash)
+ value.map { |k, v| "#{escape_hstore(k)}=>#{escape_hstore(v)}" }.join(', ')
+ else
+ value
+ end
end
def accessor
ActiveRecord::Store::StringKeyedHashAccessor
end
+
+ private
+
+ HstorePair = begin
+ quoted_string = /"[^"\\]*(?:\\.[^"\\]*)*"/
+ unquoted_string = /(?:\\.|[^\s,])[^\s=,\\]*(?:\\.[^\s=,\\]*|=[^,>])*/
+ /(#{quoted_string}|#{unquoted_string})\s*=>\s*(#{quoted_string}|#{unquoted_string})/
+ end
+
+ def escape_hstore(value)
+ if value.nil?
+ 'NULL'
+ else
+ if value == ""
+ '""'
+ else
+ '"%s"' % value.to_s.gsub(/(["\\])/, '\\\\\1')
+ end
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index f9541b437a..39b36731cd 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -23,37 +23,24 @@ module ActiveRecord
case value
when Range
if /range$/ =~ sql_type
- "'#{PostgreSQLColumn.range_to_string(value)}'::#{sql_type}"
+ escaped = quote_string(PostgreSQLColumn.range_to_string(value))
+ "'#{escaped}'::#{sql_type}"
else
super
end
- when Hash
- case sql_type
- when 'hstore' then super(PostgreSQLColumn.hstore_to_string(value), column)
- else super
- end
when Float
- if value.infinite? && column.type == :datetime
- "'#{value.to_s.downcase}'"
- elsif value.infinite? || value.nan?
+ if value.infinite? || value.nan?
"'#{value.to_s}'"
else
super
end
- when Numeric
- if sql_type == 'money' || [:string, :text].include?(column.type)
- # Not truly string input, so doesn't require (or allow) escape string syntax.
- "'#{value}'"
- else
- super
- end
when String
case sql_type
when 'xml' then "xml '#{quote_string(value)}'"
when /^bit/
case value
- when /^[01]*$/ then "B'#{value}'" # Bit-string notation
- when /^[0-9A-F]*$/i then "X'#{value}'" # Hexadecimal notation
+ when /\A[01]*\Z/ then "B'#{value}'" # Bit-string notation
+ when /\A[0-9A-F]*\Z/i then "X'#{value}'" # Hexadecimal notation
end
else
super
@@ -79,11 +66,6 @@ module ActiveRecord
else
super
end
- when Hash
- case column.sql_type
- when 'hstore' then PostgreSQLColumn.hstore_to_string(value)
- else super
- end
else
super
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index a164758640..8e31e165b1 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -569,7 +569,7 @@ module ActiveRecord
end
def exec_no_cache(sql, name, binds)
- log(sql, name, binds) { @connection.async_exec(sql) }
+ log(sql, name, binds) { @connection.async_exec(sql, []) }
end
def exec_cache(sql, name, binds)
diff --git a/activerecord/lib/active_record/core.rb b/activerecord/lib/active_record/core.rb
index 224112b559..b11c4f804f 100644
--- a/activerecord/lib/active_record/core.rb
+++ b/activerecord/lib/active_record/core.rb
@@ -315,9 +315,8 @@ module ActiveRecord
##
def initialize_dup(other) # :nodoc:
- pk = self.class.primary_key
@attributes = @attributes.dup
- @attributes.write_from_database(pk, nil)
+ @attributes.reset(self.class.primary_key)
run_callbacks(:initialize) unless _initialize_callbacks.empty?
@@ -515,10 +514,7 @@ module ActiveRecord
end
def init_internals
- pk = self.class.primary_key
- if pk && !@attributes.include?(pk)
- @attributes.write_from_database(pk, nil)
- end
+ @attributes.ensure_initialized(self.class.primary_key)
@aggregation_cache = {}
@association_cache = {}
diff --git a/activerecord/lib/active_record/counter_cache.rb b/activerecord/lib/active_record/counter_cache.rb
index 05c4b13016..a33c7c64a7 100644
--- a/activerecord/lib/active_record/counter_cache.rb
+++ b/activerecord/lib/active_record/counter_cache.rb
@@ -38,7 +38,7 @@ module ActiveRecord
counter_name = reflection.counter_cache_column
stmt = unscoped.where(arel_table[primary_key].eq(object.id)).arel.compile_update({
- arel_table[counter_name] => object.send(counter_association).count
+ arel_table[counter_name] => object.send(counter_association).count(:all)
}, primary_key)
connection.update stmt
end
diff --git a/activerecord/lib/active_record/inheritance.rb b/activerecord/lib/active_record/inheritance.rb
index 5c2f1215d2..f6c265a6d6 100644
--- a/activerecord/lib/active_record/inheritance.rb
+++ b/activerecord/lib/active_record/inheritance.rb
@@ -16,14 +16,14 @@ module ActiveRecord
# the companies table with type = "Firm". You can then fetch this row again using
# <tt>Company.where(name: '37signals').first</tt> and it will return a Firm object.
#
- # Be aware that because the type column is an attribute on the record every new
+ # Be aware that because the type column is an attribute on the record every new
# subclass will instantly be marked as dirty and the type column will be included
- # in the list of changed attributes on the record. This is different from non
+ # in the list of changed attributes on the record. This is different from non
# STI classes:
#
# Company.new.changed? # => false
- # Firm.new.changed? # => true
- # Firm.new.changes # => {"type"=>["","Firm"]}
+ # Firm.new.changed? # => true
+ # Firm.new.changes # => {"type"=>["","Firm"]}
#
# If you don't have a type column defined in your table, single-table inheritance won't
# be triggered. In that case, it'll work just like normal subclasses with no special magic
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index 12eaf36156..e94b6ae9eb 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -366,22 +366,27 @@ module ActiveRecord
# This class is used to verify that all migrations have been run before
# loading a web page if config.active_record.migration_error is set to :page_load
class CheckPending
- def initialize(app, connection = Base.connection)
+ def initialize(app)
@app = app
- @connection = connection
@last_check = 0
end
def call(env)
- if @connection.supports_migrations?
+ if connection.supports_migrations?
mtime = ActiveRecord::Migrator.last_migration.mtime.to_i
if @last_check < mtime
- ActiveRecord::Migration.check_pending!(@connection)
+ ActiveRecord::Migration.check_pending!(connection)
@last_check = mtime
end
end
@app.call(env)
end
+
+ private
+
+ def connection
+ ActiveRecord::Base.connection
+ end
end
class << self
diff --git a/activerecord/lib/active_record/persistence.rb b/activerecord/lib/active_record/persistence.rb
index ee634d7bb3..96e44c2f59 100644
--- a/activerecord/lib/active_record/persistence.rb
+++ b/activerecord/lib/active_record/persistence.rb
@@ -396,6 +396,7 @@ module ActiveRecord
end
@attributes = fresh_object.instance_variable_get('@attributes')
+ @new_record = false
self
end
diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb
index b4ae204813..90e99957f6 100644
--- a/activerecord/lib/active_record/relation/calculations.rb
+++ b/activerecord/lib/active_record/relation/calculations.rb
@@ -34,7 +34,7 @@ module ActiveRecord
# # => counts the number of different age values
#
# Note: not all valid +select+ expressions are valid +count+ expressions. The specifics differ
- # between databases. In invalid cases, an error from the databsae is thrown.
+ # between databases. In invalid cases, an error from the database is thrown.
def count(column_name = nil, options = {})
# TODO: Remove options argument as soon we remove support to
# activerecord-deprecated_finders.
diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb
index 4727469420..9bc23b5ec7 100644
--- a/activerecord/lib/active_record/tasks/database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/database_tasks.rb
@@ -176,12 +176,10 @@ module ActiveRecord
when :ruby
file ||= File.join(db_dir, "schema.rb")
check_schema_file(file)
- purge(current_config)
load(file)
when :sql
file ||= File.join(db_dir, "structure.sql")
check_schema_file(file)
- purge(current_config)
structure_load(current_config, file)
else
raise ArgumentError, "unknown format #{format.inspect}"
diff --git a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
index 9ab64d0325..5688931db2 100644
--- a/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
+++ b/activerecord/lib/active_record/tasks/sqlite_database_tasks.rb
@@ -21,11 +21,7 @@ module ActiveRecord
FileUtils.rm(file) if File.exist?(file)
end
-
- def purge
- drop
- create
- end
+ alias :purge :drop
def charset
connection.encoding
diff --git a/activerecord/lib/active_record/type/string.rb b/activerecord/lib/active_record/type/string.rb
index 14b03dcb2d..8cc533bc41 100644
--- a/activerecord/lib/active_record/type/string.rb
+++ b/activerecord/lib/active_record/type/string.rb
@@ -16,10 +16,10 @@ module ActiveRecord
end
def type_cast_for_database(value)
- if value.is_a?(::String)
- ::String.new(value)
- else
- super
+ case value
+ when ::Numeric then value.to_s
+ when ::String then ::String.new(value)
+ else super
end
end