aboutsummaryrefslogtreecommitdiffstats
path: root/activerecord/lib/active_record
diff options
context:
space:
mode:
authorwycats <wycats@gmail.com>2010-04-26 23:32:30 -0700
committerwycats <wycats@gmail.com>2010-04-26 23:32:30 -0700
commit91963e9e33eb5a28297323f1346aeb8b643e9d65 (patch)
tree0452dbaf63110fb5a19c958da50d4677dee11333 /activerecord/lib/active_record
parentd5d717161d853d8d7240da59b41a879bdac6e982 (diff)
parentc1d73270717f30498f8f4d55d6695509107c2834 (diff)
downloadrails-91963e9e33eb5a28297323f1346aeb8b643e9d65.tar.gz
rails-91963e9e33eb5a28297323f1346aeb8b643e9d65.tar.bz2
rails-91963e9e33eb5a28297323f1346aeb8b643e9d65.zip
Merge branch 'master' of github.com:rails/rails
Diffstat (limited to 'activerecord/lib/active_record')
-rwxr-xr-xactiverecord/lib/active_record/base.rb3
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/quoting.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb157
-rw-r--r--activerecord/lib/active_record/fixtures.rb16
-rw-r--r--activerecord/lib/active_record/railties/databases.rake4
-rw-r--r--activerecord/lib/active_record/serializers/xml_serializer.rb11
6 files changed, 38 insertions, 163 deletions
diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb
index fd24dcddc3..2d7cfad80d 100755
--- a/activerecord/lib/active_record/base.rb
+++ b/activerecord/lib/active_record/base.rb
@@ -1844,8 +1844,7 @@ module ActiveRecord #:nodoc:
# user.is_admin? # => true
def attributes=(new_attributes, guard_protected_attributes = true)
return if new_attributes.nil?
- attributes = new_attributes.dup
- attributes.stringify_keys!
+ attributes = new_attributes.stringify_keys
multi_parameter_attributes = []
attributes = remove_attributes_protected_from_mass_assignment(attributes) if guard_protected_attributes
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
index 8649f96498..d7b5bf8e31 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/quoting.rb
@@ -13,12 +13,12 @@ module ActiveRecord
when String, ActiveSupport::Multibyte::Chars
value = value.to_s
if column && column.type == :binary && column.class.respond_to?(:string_to_binary)
- "#{quoted_string_prefix}'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode)
+ "'#{quote_string(column.class.string_to_binary(value))}'" # ' (for ruby-mode)
elsif column && [:integer, :float].include?(column.type)
value = column.type == :integer ? value.to_i : value.to_f
value.to_s
else
- "#{quoted_string_prefix}'#{quote_string(value)}'" # ' (for ruby-mode)
+ "'#{quote_string(value)}'" # ' (for ruby-mode)
end
when NilClass then "NULL"
when TrueClass then (column && column.type == :integer ? '1' : quoted_true)
@@ -30,7 +30,7 @@ module ActiveRecord
if value.acts_like?(:date) || value.acts_like?(:time)
"'#{quoted_date(value)}'"
else
- "#{quoted_string_prefix}'#{quote_string(value.to_yaml)}'"
+ "'#{quote_string(value.to_yaml)}'"
end
end
end
@@ -67,10 +67,6 @@ module ActiveRecord
value
end.to_s(:db)
end
-
- def quoted_string_prefix
- ''
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
index ceb1adc9e0..74fed4ad62 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -2,26 +2,12 @@ require 'active_record/connection_adapters/abstract_adapter'
require 'active_support/core_ext/kernel/requires'
require 'active_support/core_ext/object/blank'
-begin
- require_library_or_gem 'pg'
-rescue LoadError => e
- begin
- require_library_or_gem 'postgres'
- class PGresult
- alias_method :nfields, :num_fields unless self.method_defined?(:nfields)
- alias_method :ntuples, :num_tuples unless self.method_defined?(:ntuples)
- alias_method :ftype, :type unless self.method_defined?(:ftype)
- alias_method :cmd_tuples, :cmdtuples unless self.method_defined?(:cmd_tuples)
- end
- rescue LoadError
- raise e
- end
-end
-
module ActiveRecord
class Base
# Establishes a connection to the database that's used by all Active Record objects
def self.postgresql_connection(config) # :nodoc:
+ require 'pg'
+
config = config.symbolize_keys
host = config[:host]
port = config[:port] || 5432
@@ -277,20 +263,12 @@ module ActiveRecord
true
end
- # Does PostgreSQL support standard conforming strings?
- def supports_standard_conforming_strings?
- # Temporarily set the client message level above error to prevent unintentional
- # error messages in the logs when working on a PostgreSQL database server that
- # does not support standard conforming strings.
- client_min_messages_old = client_min_messages
- self.client_min_messages = 'panic'
-
- # postgres-pr does not raise an exception when client_min_messages is set higher
- # than error and "SHOW standard_conforming_strings" fails, but returns an empty
- # PGresult instead.
- has_support = query('SHOW standard_conforming_strings')[0][0] rescue false
- self.client_min_messages = client_min_messages_old
- has_support
+ # Enable standard-conforming strings if available.
+ def set_standard_conforming_strings
+ old, self.client_min_messages = client_min_messages, 'panic'
+ execute('SET standard_conforming_strings = on') rescue nil
+ ensure
+ self.client_min_messages = old
end
def supports_insert_with_returning?
@@ -314,85 +292,23 @@ module ActiveRecord
# QUOTING ==================================================
# Escapes binary strings for bytea input to the database.
- def escape_bytea(original_value)
- if @connection.respond_to?(:escape_bytea)
- self.class.instance_eval do
- define_method(:escape_bytea) do |value|
- @connection.escape_bytea(value) if value
- end
- end
- elsif PGconn.respond_to?(:escape_bytea)
- self.class.instance_eval do
- define_method(:escape_bytea) do |value|
- PGconn.escape_bytea(value) if value
- end
- end
- else
- self.class.instance_eval do
- define_method(:escape_bytea) do |value|
- if value
- result = ''
- value.each_byte { |c| result << sprintf('\\\\%03o', c) }
- result
- end
- end
- end
- end
- escape_bytea(original_value)
+ def escape_bytea(value)
+ @connection.escape_bytea(value) if value
end
# Unescapes bytea output from a database to the binary string it represents.
# NOTE: This is NOT an inverse of escape_bytea! This is only to be used
# on escaped binary output from database drive.
- def unescape_bytea(original_value)
- # In each case, check if the value actually is escaped PostgreSQL bytea output
- # or an unescaped Active Record attribute that was just written.
- if PGconn.respond_to?(:unescape_bytea)
- self.class.instance_eval do
- define_method(:unescape_bytea) do |value|
- if value =~ /\\\d{3}/
- PGconn.unescape_bytea(value)
- else
- value
- end
- end
- end
- else
- self.class.instance_eval do
- define_method(:unescape_bytea) do |value|
- if value =~ /\\\d{3}/
- result = ''
- i, max = 0, value.size
- while i < max
- char = value[i]
- if char == ?\\
- if value[i+1] == ?\\
- char = ?\\
- i += 1
- else
- char = value[i+1..i+3].oct
- i += 3
- end
- end
- result << char
- i += 1
- end
- result
- else
- value
- end
- end
- end
- end
- unescape_bytea(original_value)
+ def unescape_bytea(value)
+ @connection.unescape_bytea(value) if value
end
# Quotes PostgreSQL-specific data types for SQL input.
def quote(value, column = nil) #:nodoc:
if value.kind_of?(String) && column && column.type == :binary
- "#{quoted_string_prefix}'#{escape_bytea(value)}'"
+ "'#{escape_bytea(value)}'"
elsif value.kind_of?(String) && column && column.sql_type == 'xml'
- "xml E'#{quote_string(value)}'"
+ "xml '#{quote_string(value)}'"
elsif value.kind_of?(Numeric) && column && column.sql_type == 'money'
# Not truly string input, so doesn't require (or allow) escape string syntax.
"'#{value.to_s}'"
@@ -408,28 +324,9 @@ module ActiveRecord
end
end
- # Quotes strings for use in SQL input in the postgres driver for better performance.
- def quote_string(original_value) #:nodoc:
- if @connection.respond_to?(:escape)
- self.class.instance_eval do
- define_method(:quote_string) do |s|
- @connection.escape(s)
- end
- end
- elsif PGconn.respond_to?(:escape)
- self.class.instance_eval do
- define_method(:quote_string) do |s|
- PGconn.escape(s)
- end
- end
- else
- # There are some incorrectly compiled postgres drivers out there
- # that don't define PGconn.escape.
- self.class.instance_eval do
- remove_method(:quote_string)
- end
- end
- quote_string(original_value)
+ # Quotes strings for use in SQL input.
+ def quote_string(s) #:nodoc:
+ @connection.escape(s)
end
# Checks the following cases:
@@ -1005,22 +902,11 @@ module ActiveRecord
# Ignore async_exec and async_query when using postgres-pr.
@async = @config[:allow_concurrency] && @connection.respond_to?(:async_exec)
- # Use escape string syntax if available. We cannot do this lazily when encountering
- # the first string, because that could then break any transactions in progress.
- # See: http://www.postgresql.org/docs/current/static/runtime-config-compatible.html
- # If PostgreSQL doesn't know the standard_conforming_strings parameter then it doesn't
- # support escape string syntax. Don't override the inherited quoted_string_prefix.
- if supports_standard_conforming_strings?
- self.class.instance_eval do
- define_method(:quoted_string_prefix) { 'E' }
- end
- end
-
# Money type has a fixed precision of 10 in PostgreSQL 8.2 and below, and as of
# PostgreSQL 8.3 it has a fixed precision of 19. PostgreSQLColumn.extract_precision
# should know about this but can't detect it there, so deal with it here.
- PostgreSQLColumn.money_precision =
- (postgresql_version >= 80300) ? 19 : 10
+ PostgreSQLColumn.money_precision = (postgresql_version >= 80300) ? 19 : 10
+
configure_connection
end
@@ -1036,7 +922,10 @@ module ActiveRecord
end
self.client_min_messages = @config[:min_messages] if @config[:min_messages]
self.schema_search_path = @config[:schema_search_path] || @config[:schema_order]
-
+
+ # Use standard-conforming strings if available so we don't have to do the E'...' dance.
+ set_standard_conforming_strings
+
# If using ActiveRecord's time zone support configure the connection to return
# TIMESTAMP WITH ZONE types in UTC.
execute("SET time zone 'UTC'") if ActiveRecord::Base.default_timezone == :utc
diff --git a/activerecord/lib/active_record/fixtures.rb b/activerecord/lib/active_record/fixtures.rb
index 22f0e60083..0bc49c1daa 100644
--- a/activerecord/lib/active_record/fixtures.rb
+++ b/activerecord/lib/active_record/fixtures.rb
@@ -3,8 +3,9 @@ require 'yaml'
require 'csv'
require 'zlib'
require 'active_support/dependencies'
-require 'active_support/core_ext/logger'
+require 'active_support/core_ext/array/wrap'
require 'active_support/core_ext/object/blank'
+require 'active_support/core_ext/logger'
if RUBY_VERSION < '1.9'
module YAML #:nodoc:
@@ -492,6 +493,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
def self.create_fixtures(fixtures_directory, table_names, class_names = {})
table_names = [table_names].flatten.map { |n| n.to_s }
+ table_names.each { |n| class_names[n.tr('/', '_').to_sym] = n.classify if n.include?('/') }
connection = block_given? ? yield : ActiveRecord::Base.connection
table_names_to_fetch = table_names.reject { |table_name| fixture_is_cached?(connection, table_name) }
@@ -502,7 +504,7 @@ class Fixtures < (RUBY_VERSION < '1.9' ? YAML::Omap : Hash)
fixtures_map = {}
fixtures = table_names_to_fetch.map do |table_name|
- fixtures_map[table_name] = Fixtures.new(connection, File.split(table_name.to_s).last, class_names[table_name.to_sym], File.join(fixtures_directory, table_name.to_s))
+ fixtures_map[table_name] = Fixtures.new(connection, table_name.tr('/', '_'), class_names[table_name.tr('/', '_').to_sym], File.join(fixtures_directory, table_name))
end
all_loaded_fixtures.update(fixtures_map)
@@ -836,8 +838,8 @@ module ActiveRecord
def fixtures(*table_names)
if table_names.first == :all
- table_names = Dir["#{fixture_path}/*.yml"] + Dir["#{fixture_path}/*.csv"]
- table_names.map! { |f| File.basename(f).split('.')[0..-2].join('.') }
+ table_names = Dir["#{fixture_path}/**/*.{yml,csv}"]
+ table_names.map! { |f| f[(fixture_path.size + 1)..-5] }
else
table_names = table_names.flatten.map { |n| n.to_s }
end
@@ -868,9 +870,9 @@ module ActiveRecord
end
def setup_fixture_accessors(table_names = nil)
- table_names = [table_names] if table_names && !table_names.respond_to?(:each)
- (table_names || fixture_table_names).each do |table_name|
- table_name = table_name.to_s.tr('.', '_')
+ table_names = Array.wrap(table_names || fixture_table_names)
+ table_names.each do |table_name|
+ table_name = table_name.to_s.tr('./', '_')
define_method(table_name) do |*fixtures|
force_reload = fixtures.pop if fixtures.last == true || fixtures.last == :reload
diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake
index 2b53afc68b..cb7eade0ab 100644
--- a/activerecord/lib/active_record/railties/databases.rake
+++ b/activerecord/lib/active_record/railties/databases.rake
@@ -258,8 +258,8 @@ namespace :db do
base_dir = ENV['FIXTURES_PATH'] ? File.join(Rails.root, ENV['FIXTURES_PATH']) : File.join(Rails.root, 'test', 'fixtures')
fixtures_dir = ENV['FIXTURES_DIR'] ? File.join(base_dir, ENV['FIXTURES_DIR']) : base_dir
- (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir.glob(File.join(fixtures_dir, '*.{yml,csv}'))).each do |fixture_file|
- Fixtures.create_fixtures(File.dirname(fixture_file), File.basename(fixture_file, '.*'))
+ (ENV['FIXTURES'] ? ENV['FIXTURES'].split(/,/).map {|f| File.join(fixtures_dir, f) } : Dir["#{fixtures_dir}/**/*.{yml,csv}"]).each do |fixture_file|
+ Fixtures.create_fixtures(fixtures_dir, fixture_file[(fixtures_dir.size + 1)..-5])
end
end
diff --git a/activerecord/lib/active_record/serializers/xml_serializer.rb b/activerecord/lib/active_record/serializers/xml_serializer.rb
index 2e85959b1e..255b03433d 100644
--- a/activerecord/lib/active_record/serializers/xml_serializer.rb
+++ b/activerecord/lib/active_record/serializers/xml_serializer.rb
@@ -182,17 +182,6 @@ module ActiveRecord #:nodoc:
options[:except] |= Array.wrap(@serializable.class.inheritance_column)
end
- def serializable_attributes
- serializable_attribute_names.collect { |name| Attribute.new(name, @serializable) }
- end
-
- def serializable_method_attributes
- Array.wrap(options[:methods]).inject([]) do |method_attributes, name|
- method_attributes << MethodAttribute.new(name.to_s, @serializable) if @serializable.respond_to?(name.to_s)
- method_attributes
- end
- end
-
def add_associations(association, records, opts)
if records.is_a?(Enumerable)
tag = reformat_name(association.to_s)