aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--actionview/lib/action_view/template/resolver.rb2
-rw-r--r--activemodel/lib/active_model/secure_password.rb1
-rw-r--r--activerecord/CHANGELOG.md10
-rw-r--r--activerecord/Rakefile145
-rw-r--r--activerecord/lib/active_record/aggregations.rb8
-rw-r--r--activerecord/lib/active_record/associations/collection_association.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb19
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_adapter.rb38
-rw-r--r--activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb26
-rw-r--r--activerecord/lib/active_record/connection_adapters/column.rb41
-rw-r--r--activerecord/lib/active_record/connection_adapters/mysql_adapter.rb1
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/cast.rb2
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/column.rb5
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/oid.rb24
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb10
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb6
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb19
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql/utils.rb25
-rw-r--r--activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb18
-rw-r--r--activerecord/lib/active_record/connection_adapters/type.rb20
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/binary.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/boolean.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/date_time.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/decimal.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/float.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/integer.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/string.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/text.rb13
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/time.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/timestamp.rb11
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/type_map.rb50
-rw-r--r--activerecord/lib/active_record/connection_adapters/type/value.rb1
-rw-r--r--activerecord/lib/active_record/migration.rb2
-rw-r--r--activerecord/test/cases/adapters/mysql/quoting_test.rb4
-rw-r--r--activerecord/test/cases/adapters/postgresql/composite_test.rb1
-rw-r--r--activerecord/test/cases/adapters/postgresql/extension_migration_test.rb65
-rw-r--r--activerecord/test/cases/adapters/postgresql/schema_test.rb15
-rw-r--r--activerecord/test/cases/adapters/postgresql/utils_test.rb20
-rw-r--r--activerecord/test/cases/adapters/sqlite3/quoting_test.rb12
-rw-r--r--activerecord/test/cases/base_test.rb8
-rw-r--r--activerecord/test/cases/column_definition_test.rb44
-rw-r--r--activerecord/test/cases/column_test.rb34
-rw-r--r--activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb61
-rw-r--r--activerecord/test/cases/connection_adapters/type/type_map_test.rb102
-rw-r--r--activerecord/test/cases/connection_adapters/type_lookup_test.rb100
-rw-r--r--activerecord/test/cases/migration/columns_test.rb10
-rw-r--r--activerecord/test/models/developer.rb6
-rwxr-xr-xci/travis.rb2
-rw-r--r--guides/source/active_record_postgresql.md21
-rw-r--r--guides/source/api_documentation_guidelines.md13
-rw-r--r--guides/source/contributing_to_ruby_on_rails.md8
-rw-r--r--guides/source/development_dependencies_install.md4
-rw-r--r--guides/source/layout.html.erb1
55 files changed, 846 insertions, 287 deletions
diff --git a/actionview/lib/action_view/template/resolver.rb b/actionview/lib/action_view/template/resolver.rb
index 189086132e..d29d020c17 100644
--- a/actionview/lib/action_view/template/resolver.rb
+++ b/actionview/lib/action_view/template/resolver.rb
@@ -196,7 +196,7 @@ module ActionView
}
end
- if File.const_defined? :FNM_EXTGLOB
+ if RUBY_VERSION >= '2.2.0'
def find_template_paths(query)
Dir[query].reject { |filename|
File.directory?(filename) ||
diff --git a/activemodel/lib/active_model/secure_password.rb b/activemodel/lib/active_model/secure_password.rb
index 826e89bf9d..0c3ed9e8ca 100644
--- a/activemodel/lib/active_model/secure_password.rb
+++ b/activemodel/lib/active_model/secure_password.rb
@@ -68,6 +68,7 @@ module ActiveModel
validates_confirmation_of :password, if: ->{ password.present? }
end
+ # This code is necessary as long as the protected_attributes gem is supported.
if respond_to?(:attributes_protected_by_default)
def self.attributes_protected_by_default #:nodoc:
super + ['password_digest']
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md
index 8630c82906..cf85ec637a 100644
--- a/activerecord/CHANGELOG.md
+++ b/activerecord/CHANGELOG.md
@@ -1,3 +1,13 @@
+* Fix bug that added `table_name_prefix` and `table_name_suffix` to
+ extension names in PostgreSQL when migrating.
+
+ *Joao Carlos*
+
+* The `:index` option in migrations, which previously was only available for
+ `references`, now works with any column types.
+
+ *Marc Schütz*
+
* Add support for counter name to be passed as parameter on `CounterCache::ClassMethods#reset_counters`.
*jnormore*
diff --git a/activerecord/Rakefile b/activerecord/Rakefile
index 01ca4c82f2..7769966a22 100644
--- a/activerecord/Rakefile
+++ b/activerecord/Rakefile
@@ -38,33 +38,36 @@ namespace :test do
end
end
+desc 'Build MySQL and PostgreSQL test databases'
namespace :db do
- desc 'Build MySQL and PostgreSQL test databases'
- task create: ['mysql:build_databases', 'postgresql:build_databases']
- desc 'Drop MySQL and PostgreSQL test databases'
- task drop: ['mysql:drop_databases', 'postgresql:drop_databases']
+ task :create => ['db:mysql:build', 'db:postgresql:build']
+ task :drop => ['db:mysql:drop', 'db:postgresql:drop']
end
%w( mysql mysql2 postgresql sqlite3 sqlite3_mem db2 oracle jdbcmysql jdbcpostgresql jdbcsqlite3 jdbcderby jdbch2 jdbchsqldb ).each do |adapter|
- Rake::TestTask.new("test_#{adapter}") { |t|
- adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
- t.libs << 'test'
- t.test_files = (Dir.glob( "test/cases/**/*_test.rb" ).reject {
- |x| x =~ /\/adapters\//
- } + Dir.glob("test/cases/adapters/#{adapter_short}/**/*_test.rb")).sort
-
- t.warning = true
- t.verbose = true
- }
-
- task "isolated_test_#{adapter}" do
- adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
- puts [adapter, adapter_short].inspect
- (Dir["test/cases/**/*_test.rb"].reject {
- |x| x =~ /\/adapters\//
- } + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).all? do |file|
- sh(Gem.ruby, '-w' ,"-Itest", file)
- end or raise "Failures"
+ namespace :test do
+ Rake::TestTask.new(adapter => "#{adapter}:env") { |t|
+ adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
+ t.libs << 'test'
+ t.test_files = (Dir.glob( "test/cases/**/*_test.rb" ).reject {
+ |x| x =~ /\/adapters\//
+ } + Dir.glob("test/cases/adapters/#{adapter_short}/**/*_test.rb")).sort
+
+ t.warning = true
+ t.verbose = true
+ }
+
+ namespace :isolated do
+ task adapter => "#{adapter}:env" do
+ adapter_short = adapter == 'db2' ? adapter : adapter[/^[a-z0-9]+/]
+ puts [adapter, adapter_short].inspect
+ (Dir["test/cases/**/*_test.rb"].reject {
+ |x| x =~ /\/adapters\//
+ } + Dir["test/cases/adapters/#{adapter_short}/**/*_test.rb"]).all? do |file|
+ sh(Gem.ruby, '-w' ,"-Itest", file)
+ end or raise "Failures"
+ end
+ end
end
namespace adapter do
@@ -76,8 +79,8 @@ end
end
# Make sure the adapter test evaluates the env setting task
- task "test_#{adapter}" => "#{adapter}:env"
- task "isolated_test_#{adapter}" => "#{adapter}:env"
+ task "test_#{adapter}" => ["#{adapter}:env", "test:#{adapter}"]
+ task "isolated_test_#{adapter}" => ["#{adapter}:env", "test:isolated:#{adapter}"]
end
rule '.sqlite3' do |t|
@@ -89,63 +92,58 @@ task :test_sqlite3 => [
'test/fixtures/fixture_database_2.sqlite3'
]
-namespace :mysql do
- desc 'Build the MySQL test databases'
- task :build_databases do
- config = ARTest.config['connections']['mysql']
- %x( mysql --user=#{config['arunit']['username']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
- %x( mysql --user=#{config['arunit2']['username']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
- end
-
- desc 'Drop the MySQL test databases'
- task :drop_databases do
- config = ARTest.config['connections']['mysql']
- %x( mysqladmin --user=#{config['arunit']['username']} -f drop #{config['arunit']['database']} )
- %x( mysqladmin --user=#{config['arunit2']['username']} -f drop #{config['arunit2']['database']} )
- end
+namespace :db do
+ namespace :mysql do
+ desc 'Build the MySQL test databases'
+ task :build do
+ config = ARTest.config['connections']['mysql']
+ %x( mysql --user=#{config['arunit']['username']} -e "create DATABASE #{config['arunit']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
+ %x( mysql --user=#{config['arunit2']['username']} -e "create DATABASE #{config['arunit2']['database']} DEFAULT CHARACTER SET utf8 DEFAULT COLLATE utf8_unicode_ci ")
+ end
- desc 'Rebuild the MySQL test databases'
- task :rebuild_databases => [:drop_databases, :build_databases]
-end
+ desc 'Drop the MySQL test databases'
+ task :drop do
+ config = ARTest.config['connections']['mysql']
+ %x( mysqladmin --user=#{config['arunit']['username']} -f drop #{config['arunit']['database']} )
+ %x( mysqladmin --user=#{config['arunit2']['username']} -f drop #{config['arunit2']['database']} )
+ end
-task :build_mysql_databases => 'mysql:build_databases'
-task :drop_mysql_databases => 'mysql:drop_databases'
-task :rebuild_mysql_databases => 'mysql:rebuild_databases'
+ desc 'Rebuild the MySQL test databases'
+ task :rebuild => [:drop, :build]
+ end
+ namespace :postgresql do
+ desc 'Build the PostgreSQL test databases'
+ task :build do
+ config = ARTest.config['connections']['postgresql']
+ %x( createdb -E UTF8 -T template0 #{config['arunit']['database']} )
+ %x( createdb -E UTF8 -T template0 #{config['arunit2']['database']} )
-namespace :postgresql do
- desc 'Build the PostgreSQL test databases'
- task :build_databases do
- config = ARTest.config['connections']['postgresql']
- %x( createdb -E UTF8 -T template0 #{config['arunit']['database']} )
- %x( createdb -E UTF8 -T template0 #{config['arunit2']['database']} )
+ # prepare hstore
+ if %x( createdb --version ).strip.gsub(/(.*)(\d\.\d\.\d)$/, "\\2") < "9.1.0"
+ puts "Please prepare hstore data type. See http://www.postgresql.org/docs/9.0/static/hstore.html"
+ end
+ end
- # notify about preparing hstore
- if %x( createdb --version ).strip.gsub(/(.*)(\d\.\d\.\d)$/, "\\2") < "9.1.0"
- puts "Please prepare hstore data type. See http://www.postgresql.org/docs/9.0/static/hstore.html"
+ desc 'Drop the PostgreSQL test databases'
+ task :drop do
+ config = ARTest.config['connections']['postgresql']
+ %x( dropdb #{config['arunit']['database']} )
+ %x( dropdb #{config['arunit2']['database']} )
end
- end
- desc 'Drop the PostgreSQL test databases'
- task :drop_databases do
- config = ARTest.config['connections']['postgresql']
- %x( dropdb #{config['arunit']['database']} )
- %x( dropdb #{config['arunit2']['database']} )
+ desc 'Rebuild the PostgreSQL test databases'
+ task :rebuild => [:drop, :build]
end
-
- desc 'Rebuild the PostgreSQL test databases'
- task :rebuild_databases => [:drop_databases, :build_databases]
end
-task :build_postgresql_databases => 'postgresql:build_databases'
-task :drop_postgresql_databases => 'postgresql:drop_databases'
-task :rebuild_postgresql_databases => 'postgresql:rebuild_databases'
-
+task :build_mysql_databases => 'db:mysql:build'
+task :drop_mysql_databases => 'db:mysql:drop'
+task :rebuild_mysql_databases => 'db:mysql:rebuild'
-spec = eval(File.read('activerecord.gemspec'))
-Gem::PackageTask.new(spec) do |p|
- p.gem_spec = spec
-end
+task :build_postgresql_databases => 'db:postgresql:build'
+task :drop_postgresql_databases => 'db:postgresql:drop'
+task :rebuild_postgresql_databases => 'db:postgresql:rebuild'
task :lines do
lines, codelines, total_lines, total_codelines = 0, 0, 0, 0
@@ -171,6 +169,11 @@ task :lines do
puts "Total: Lines #{total_lines}, LOC #{total_codelines}"
end
+spec = eval(File.read('activerecord.gemspec'))
+
+Gem::PackageTask.new(spec) do |p|
+ p.gem_spec = spec
+end
# Publishing ------------------------------------------------------
diff --git a/activerecord/lib/active_record/aggregations.rb b/activerecord/lib/active_record/aggregations.rb
index 0d5313956b..45c275a017 100644
--- a/activerecord/lib/active_record/aggregations.rb
+++ b/activerecord/lib/active_record/aggregations.rb
@@ -230,8 +230,8 @@ module ActiveRecord
private
def reader_method(name, class_name, mapping, allow_nil, constructor)
define_method(name) do
- if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? {|pair| !read_attribute(pair.first).nil? })
- attrs = mapping.collect {|pair| read_attribute(pair.first)}
+ if @aggregation_cache[name].nil? && (!allow_nil || mapping.any? {|key, _| !read_attribute(key).nil? })
+ attrs = mapping.collect {|key, _| read_attribute(key)}
object = constructor.respond_to?(:call) ?
constructor.call(*attrs) :
class_name.constantize.send(constructor, *attrs)
@@ -249,10 +249,10 @@ module ActiveRecord
end
if part.nil? && allow_nil
- mapping.each { |pair| self[pair.first] = nil }
+ mapping.each { |key, _| self[key] = nil }
@aggregation_cache[name] = nil
else
- mapping.each { |pair| self[pair.first] = part.send(pair.last) }
+ mapping.each { |key, value| self[key] = part.send(value) }
@aggregation_cache[name] = part.freeze
end
end
diff --git a/activerecord/lib/active_record/associations/collection_association.rb b/activerecord/lib/active_record/associations/collection_association.rb
index caf4e612f9..c5f7bcae7d 100644
--- a/activerecord/lib/active_record/associations/collection_association.rb
+++ b/activerecord/lib/active_record/associations/collection_association.rb
@@ -244,6 +244,7 @@ module ActiveRecord
# are actually removed from the database, that depends precisely on
# +delete_records+. They are in any case removed from the collection.
def delete(*records)
+ return if records.empty?
_options = records.extract_options!
dependent = _options[:dependent] || options[:dependent]
@@ -257,6 +258,7 @@ module ActiveRecord
# Note that this method removes records from the database ignoring the
# +:dependent+ option.
def destroy(*records)
+ return if records.empty?
records = find(records) if records.any? { |record| record.kind_of?(Fixnum) || record.kind_of?(String) }
delete_or_destroy(records, :destroy)
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
index 2eaaffd08e..f54fcc4040 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract/schema_definitions.rb
@@ -99,6 +99,8 @@ module ActiveRecord
# Specifies the precision for a <tt>:decimal</tt> column.
# * <tt>:scale</tt> -
# Specifies the scale for a <tt>:decimal</tt> column.
+ # * <tt>:index</tt> -
+ # Create an index for the column. Can be either <tt>true</tt> or an options hash.
#
# For clarity's sake: the precision is the number of significant digits,
# while the scale is the number of digits that can be stored following
@@ -163,18 +165,21 @@ module ActiveRecord
# What can be written like this with the regular calls to column:
#
# create_table :products do |t|
- # t.column :shop_id, :integer
- # t.column :creator_id, :integer
- # t.column :name, :string, default: "Untitled"
- # t.column :value, :string, default: "Untitled"
- # t.column :created_at, :datetime
- # t.column :updated_at, :datetime
+ # t.column :shop_id, :integer
+ # t.column :creator_id, :integer
+ # t.column :item_number, :string
+ # t.column :name, :string, default: "Untitled"
+ # t.column :value, :string, default: "Untitled"
+ # t.column :created_at, :datetime
+ # t.column :updated_at, :datetime
# end
+ # add_index :products, :item_number
#
# can also be written as follows using the short-hand:
#
# create_table :products do |t|
# t.integer :shop_id, :creator_id
+ # t.string :item_number, index: true
# t.string :name, :value, default: "Untitled"
# t.timestamps
# end
@@ -210,6 +215,8 @@ module ActiveRecord
raise ArgumentError, "you can't redefine the primary key column '#{name}'. To define a custom primary key, pass { id: false } to create_table."
end
+ index_options = options.delete(:index)
+ index(name, index_options.is_a?(Hash) ? index_options : {}) if index_options
@columns_hash[name] = new_column_definition(name, type, options)
self
end
diff --git a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
index d9c939689f..8a7a869eec 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb
@@ -361,10 +361,46 @@ module ActiveRecord
pool.checkin self
end
+ def type_map # :nodoc:
+ @type_map ||= Type::TypeMap.new.tap do |mapping|
+ initialize_type_map(mapping)
+ end
+ end
+
protected
def lookup_cast_type(sql_type) # :nodoc:
- Type::Value.new
+ type_map.lookup(sql_type)
+ end
+
+ def initialize_type_map(m) # :nodoc:
+ m.register_type %r(boolean)i, Type::Boolean.new
+ m.register_type %r(char)i, Type::String.new
+ m.register_type %r(binary)i, Type::Binary.new
+ m.alias_type %r(blob)i, 'binary'
+ m.register_type %r(text)i, Type::Text.new
+ m.alias_type %r(clob)i, 'text'
+ m.register_type %r(date)i, Type::Date.new
+ m.register_type %r(time)i, Type::Time.new
+ m.register_type %r(timestamp)i, Type::Timestamp.new
+ m.register_type %r(datetime)i, Type::DateTime.new
+ m.alias_type %r(numeric)i, 'decimal'
+ m.alias_type %r(number)i, 'decimal'
+ m.register_type %r(float)i, Type::Float.new
+ m.alias_type %r(double)i, 'float'
+ m.register_type %r(int)i, Type::Integer.new
+ m.register_type(%r(decimal)i) do |sql_type|
+ if Type.extract_scale(sql_type) == 0
+ Type::Integer.new
+ else
+ Type::Decimal.new
+ end
+ end
+ end
+
+ def reload_type_map # :nodoc:
+ type_map.clear
+ initialize_type_map(type_map)
end
def translate_exception_class(e, sql)
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 7074f69583..5eb2e86d48 100644
--- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb
@@ -97,18 +97,6 @@ module ActiveRecord
private
- def simplified_type(field_type)
- return :boolean if adapter.emulate_booleans && field_type.downcase.index("tinyint(1)")
-
- case field_type
- when /enum/i, /set/i then :string
- when /year/i then :integer
- when /bit/i then :binary
- else
- super
- end
- end
-
def extract_limit(sql_type)
case sql_type
when /^enum\((.+)\)/i
@@ -318,6 +306,11 @@ module ActiveRecord
# DATABASE STATEMENTS ======================================
+ def clear_cache!
+ super
+ reload_type_map
+ end
+
# Executes the SQL statement in the context of this connection.
def execute(sql, name = nil)
log(sql, name) { @connection.query(sql) }
@@ -645,6 +638,15 @@ module ActiveRecord
protected
+ def initialize_type_map(m)
+ super
+ m.alias_type %r(tinyint\(1\))i, 'boolean' if emulate_booleans
+ m.alias_type %r(enum)i, 'varchar'
+ m.alias_type %r(set)i, 'varchar'
+ m.alias_type %r(year)i, 'integer'
+ m.alias_type %r(bit)i, 'binary'
+ end
+
# MySQL is too stupid to create a temporary table for use subquery, so we have
# to give it some prompting in the form of a subsubquery. Ugh!
def subquery_for(key, select)
diff --git a/activerecord/lib/active_record/connection_adapters/column.rb b/activerecord/lib/active_record/connection_adapters/column.rb
index 3bab325e42..0087c20b88 100644
--- a/activerecord/lib/active_record/connection_adapters/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/column.rb
@@ -13,11 +13,13 @@ module ActiveRecord
ISO_DATETIME = /\A(\d{4})-(\d\d)-(\d\d) (\d\d):(\d\d):(\d\d)(\.\d+)?\z/
end
- attr_reader :name, :default, :type, :limit, :null, :sql_type, :precision, :scale, :default_function
+ attr_reader :name, :default, :cast_type, :limit, :null, :sql_type, :precision, :scale, :default_function
attr_accessor :primary, :coder
alias :encoded? :coder
+ delegate :type, to: :cast_type
+
# Instantiates a new column in the table.
#
# +name+ is the column's name, such as <tt>supplier_id</tt> in <tt>supplier_id int(11)</tt>.
@@ -35,7 +37,6 @@ module ActiveRecord
@limit = extract_limit(sql_type)
@precision = extract_precision(sql_type)
@scale = extract_scale(sql_type)
- @type = simplified_type(sql_type)
@default = extract_default(default)
@default_function = nil
@primary = nil
@@ -256,6 +257,8 @@ module ActiveRecord
end
private
+ delegate :extract_scale, to: Type
+
def extract_limit(sql_type)
$1.to_i if sql_type =~ /\((.*)\)/
end
@@ -263,40 +266,6 @@ module ActiveRecord
def extract_precision(sql_type)
$2.to_i if sql_type =~ /^(numeric|decimal|number)\((\d+)(,\d+)?\)/i
end
-
- def extract_scale(sql_type)
- case sql_type
- when /^(numeric|decimal|number)\((\d+)\)/i then 0
- when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then $4.to_i
- end
- end
-
- def simplified_type(field_type)
- case field_type
- when /int/i
- :integer
- when /float|double/i
- :float
- when /decimal|numeric|number/i
- extract_scale(field_type) == 0 ? :integer : :decimal
- when /datetime/i
- :datetime
- when /timestamp/i
- :timestamp
- when /time/i
- :time
- when /date/i
- :date
- when /clob/i, /text/i
- :text
- when /blob/i, /binary/i
- :binary
- when /char/i
- :string
- when /boolean/i
- :boolean
- end
- end
end
end
# :startdoc:
diff --git a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
index 69e2b0ab2b..bf09bfe217 100644
--- a/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/mysql_adapter.rb
@@ -223,6 +223,7 @@ module ActiveRecord
# Clears the prepared statements cache.
def clear_cache!
+ super
@statements.clear
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb b/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb
index 743bf68fe6..1b74c039ce 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/array_parser.rb
@@ -1,7 +1,7 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
- module ArrayParser
+ module ArrayParser # :nodoc:
DOUBLE_QUOTE = '"'
BACKSLASH = "\\"
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
index b612602216..a14381acb6 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/cast.rb
@@ -1,7 +1,7 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
- module Cast
+ module Cast # :nodoc:
def point_to_string(point) # :nodoc:
"(#{point[0]},#{point[1]})"
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
index 77fdebbbc9..1dd8acc257 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/column.rb
@@ -165,11 +165,6 @@ module ActiveRecord
super
end
end
-
- # Maps PostgreSQL-specific data types to logical Rails types.
- def simplified_type(field_type)
- @oid_type.simplified_type(field_type) || super
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
index cf6a375704..90bf6c6d1a 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/oid.rb
@@ -1,11 +1,8 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
- module OID
- class Type
- def type; end
- def simplified_type(sql_type); type end
-
+ module OID # :nodoc:
+ class Type < Type::Value
def infinity(options = {})
::Float::INFINITY * (options[:negative] ? -1 : 1)
end
@@ -136,11 +133,11 @@ module ActiveRecord
end
class Range < Type
- attr_reader :subtype
- def simplified_type(sql_type); sql_type.to_sym end
+ attr_reader :subtype, :type
- def initialize(subtype)
+ def initialize(subtype, type)
@subtype = subtype
+ @type = type
end
def extract_bounds(value)
@@ -204,11 +201,8 @@ This is not reliable and will be removed in the future.
end
end
- class Timestamp < Type
- def type; :timestamp; end
- def simplified_type(sql_type)
- :datetime
- end
+ class DateTime < Type
+ def type; :datetime; end
def type_cast(value)
return if value.nil?
@@ -415,7 +409,7 @@ This is not reliable and will be removed in the future.
def register_range_type(row)
if subtype = @store[row['rngsubtype'].to_i]
- register row['oid'], OID::Range.new(subtype)
+ register row['oid'], OID::Range.new(subtype, row['typname'].to_sym)
end
end
@@ -483,7 +477,7 @@ This is not reliable and will be removed in the future.
register_type 'bool', OID::Boolean.new
register_type 'bit', OID::Bit.new
alias_type 'varbit', 'bit'
- register_type 'timestamp', OID::Timestamp.new
+ register_type 'timestamp', OID::DateTime.new
alias_type 'timestamptz', 'timestamp'
register_type 'date', OID::Date.new
register_type 'time', OID::Time.new
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
index 0883b02a35..ad12298013 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/quoting.rb
@@ -150,13 +150,11 @@ module ActiveRecord
# - "schema.name".table_name
# - "schema.name"."table.name"
def quote_table_name(name)
- schema, name_part = extract_pg_identifier_from_name(name.to_s)
-
- unless name_part
- quote_column_name(schema)
+ schema, table = Utils.extract_schema_and_table(name.to_s)
+ if schema
+ "#{quote_column_name(schema)}.#{quote_column_name(table)}"
else
- table_name, name_part = extract_pg_identifier_from_name(name_part)
- "#{quote_column_name(schema)}.#{quote_column_name(table_name)}"
+ quote_column_name(table)
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb b/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
index 98dcf441ff..52b307c432 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/referential_integrity.rb
@@ -1,12 +1,12 @@
module ActiveRecord
module ConnectionAdapters
module PostgreSQL
- module ReferentialIntegrity
- def supports_disable_referential_integrity? #:nodoc:
+ module ReferentialIntegrity # :nodoc:
+ def supports_disable_referential_integrity? # :nodoc:
true
end
- def disable_referential_integrity #:nodoc:
+ def disable_referential_integrity # :nodoc:
if supports_disable_referential_integrity?
begin
execute(tables.collect { |name| "ALTER TABLE #{quote_table_name(name)} DISABLE TRIGGER ALL" }.join(";"))
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
index dd983562fb..539ba38c4a 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/schema_statements.rb
@@ -97,7 +97,7 @@ module ActiveRecord
# If the schema is not specified as part of +name+ then it will only find tables within
# the current schema search path (regardless of permissions to access tables in other schemas)
def table_exists?(name)
- schema, table = extract_schema_and_table(name.to_s)
+ schema, table = Utils.extract_schema_and_table(name.to_s)
return false unless table
exec_query(<<-SQL, 'SCHEMA').rows.first[0].to_i > 0
@@ -488,23 +488,6 @@ module ActiveRecord
[super, *order_columns].join(', ')
end
-
- private
-
- # Returns an array of <tt>[schema_name, table_name]</tt> extracted from +name+.
- # +schema_name+ is nil if not specified in +name+.
- # +schema_name+ and +table_name+ exclude surrounding quotes (regardless of whether provided in +name+)
- # +name+ supports the range of schema/table references understood by PostgreSQL, for example:
- #
- # * <tt>table_name</tt>
- # * <tt>"table.name"</tt>
- # * <tt>schema_name.table_name</tt>
- # * <tt>schema_name."table.name"</tt>
- # * <tt>"schema.name"."table name"</tt>
- def extract_schema_and_table(name)
- table, schema = name.scan(/[^".\s]+|"[^"]*"/)[0..1].collect{|m| m.gsub(/(^"|"$)/,'') }.reverse
- [schema, table]
- end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb
new file mode 100644
index 0000000000..60ffd3a114
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/postgresql/utils.rb
@@ -0,0 +1,25 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module PostgreSQL
+ module Utils # :nodoc:
+ extend self
+
+ # Returns an array of <tt>[schema_name, table_name]</tt> extracted from +name+.
+ # +schema_name+ is nil if not specified in +name+.
+ # +schema_name+ and +table_name+ exclude surrounding quotes (regardless of whether provided in +name+)
+ # +name+ supports the range of schema/table references understood by PostgreSQL, for example:
+ #
+ # * <tt>table_name</tt>
+ # * <tt>"table.name"</tt>
+ # * <tt>schema_name.table_name</tt>
+ # * <tt>schema_name."table.name"</tt>
+ # * <tt>"schema_name".table_name</tt>
+ # * <tt>"schema.name"."table name"</tt>
+ def extract_schema_and_table(name)
+ table, schema = name.scan(/[^".\s]+|"[^"]*"/)[0..1].collect{|m| m.gsub(/(^"|"$)/,'') }.reverse
+ [schema, table]
+ end
+ 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 23b91be0f3..59e157744f 100644
--- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
+++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb
@@ -1,6 +1,7 @@
require 'active_record/connection_adapters/abstract_adapter'
require 'active_record/connection_adapters/statement_pool'
+require 'active_record/connection_adapters/postgresql/utils'
require 'active_record/connection_adapters/postgresql/column'
require 'active_record/connection_adapters/postgresql/oid'
require 'active_record/connection_adapters/postgresql/quoting'
@@ -538,10 +539,6 @@ module ActiveRecord
private
- def type_map
- @type_map
- end
-
def get_oid_type(oid, fmod, column_name)
if !type_map.key?(oid)
initialize_type_map(type_map, [oid])
@@ -553,11 +550,6 @@ module ActiveRecord
}
end
- def reload_type_map
- type_map.clear
- initialize_type_map(type_map)
- end
-
def initialize_type_map(type_map, oids = nil)
if supports_ranges?
query = <<-SQL
@@ -740,7 +732,7 @@ module ActiveRecord
# Query implementation notes:
# - format_type includes the column size constraint, e.g. varchar(50)
# - ::regclass is a function that gives the id for a table name
- def column_definitions(table_name) #:nodoc:
+ def column_definitions(table_name) # :nodoc:
exec_query(<<-end_sql, 'SCHEMA').rows
SELECT a.attname, format_type(a.atttypid, a.atttypmod),
pg_get_expr(d.adbin, d.adrelid), a.attnotnull, a.atttypid, a.atttypmod
@@ -752,7 +744,7 @@ module ActiveRecord
end_sql
end
- def extract_pg_identifier_from_name(name)
+ def extract_pg_identifier_from_name(name) # :nodoc:
match_data = name.start_with?('"') ? name.match(/\"([^\"]+)\"/) : name.match(/([^\.]+)/)
if match_data
@@ -762,12 +754,12 @@ module ActiveRecord
end
end
- def extract_table_ref_from_insert_sql(sql)
+ def extract_table_ref_from_insert_sql(sql) # :nodoc:
sql[/into\s+([^\(]*).*values\s*\(/im]
$1.strip if $1
end
- def create_table_definition(name, temporary, options, as = nil)
+ def create_table_definition(name, temporary, options, as = nil) # :nodoc:
TableDefinition.new native_database_types, name, temporary, options, as
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type.rb b/activerecord/lib/active_record/connection_adapters/type.rb
index 1b27377cde..34b1e9e39e 100644
--- a/activerecord/lib/active_record/connection_adapters/type.rb
+++ b/activerecord/lib/active_record/connection_adapters/type.rb
@@ -1,8 +1,28 @@
require 'active_record/connection_adapters/type/value'
+require 'active_record/connection_adapters/type/binary'
+require 'active_record/connection_adapters/type/boolean'
+require 'active_record/connection_adapters/type/date'
+require 'active_record/connection_adapters/type/date_time'
+require 'active_record/connection_adapters/type/decimal'
+require 'active_record/connection_adapters/type/float'
+require 'active_record/connection_adapters/type/integer'
+require 'active_record/connection_adapters/type/string'
+require 'active_record/connection_adapters/type/text'
+require 'active_record/connection_adapters/type/time'
+require 'active_record/connection_adapters/type/timestamp'
+require 'active_record/connection_adapters/type/type_map'
module ActiveRecord
module ConnectionAdapters
module Type # :nodoc:
+ class << self
+ def extract_scale(sql_type)
+ case sql_type
+ when /^(numeric|decimal|number)\((\d+)\)/i then 0
+ when /^(numeric|decimal|number)\((\d+)(,(\d+))\)/i then $4.to_i
+ end
+ end
+ end
end
end
end
diff --git a/activerecord/lib/active_record/connection_adapters/type/binary.rb b/activerecord/lib/active_record/connection_adapters/type/binary.rb
new file mode 100644
index 0000000000..168d824d3d
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/binary.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Binary < Value # :nodoc:
+ def type
+ :binary
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/boolean.rb b/activerecord/lib/active_record/connection_adapters/type/boolean.rb
new file mode 100644
index 0000000000..938d227632
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/boolean.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Boolean < Value # :nodoc:
+ def type
+ :boolean
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/date.rb b/activerecord/lib/active_record/connection_adapters/type/date.rb
new file mode 100644
index 0000000000..1632f3c8f4
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/date.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Date < Value # :nodoc:
+ def type
+ :date
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/date_time.rb b/activerecord/lib/active_record/connection_adapters/type/date_time.rb
new file mode 100644
index 0000000000..1d7d3cfbbf
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/date_time.rb
@@ -0,0 +1,13 @@
+require 'active_record/connection_adapters/type/timestamp'
+
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class DateTime < Timestamp # :nodoc:
+ def type
+ :datetime
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/decimal.rb b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
new file mode 100644
index 0000000000..5b39ea9e2f
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/decimal.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Decimal < Value # :nodoc:
+ def type
+ :decimal
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/float.rb b/activerecord/lib/active_record/connection_adapters/type/float.rb
new file mode 100644
index 0000000000..089169e7c9
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/float.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Float < Value # :nodoc:
+ def type
+ :float
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/integer.rb b/activerecord/lib/active_record/connection_adapters/type/integer.rb
new file mode 100644
index 0000000000..5510a11bd4
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/integer.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Integer < Value # :nodoc:
+ def type
+ :integer
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/string.rb b/activerecord/lib/active_record/connection_adapters/type/string.rb
new file mode 100644
index 0000000000..0feb4299f5
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/string.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class String < Value # :nodoc:
+ def type
+ :string
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/text.rb b/activerecord/lib/active_record/connection_adapters/type/text.rb
new file mode 100644
index 0000000000..ee5842a3fc
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/text.rb
@@ -0,0 +1,13 @@
+require 'active_record/connection_adapters/type/string'
+
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Text < String # :nodoc:
+ def type
+ :text
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/time.rb b/activerecord/lib/active_record/connection_adapters/type/time.rb
new file mode 100644
index 0000000000..a3a687a8ad
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/time.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Time < Value # :nodoc:
+ def type
+ :time
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/timestamp.rb b/activerecord/lib/active_record/connection_adapters/type/timestamp.rb
new file mode 100644
index 0000000000..92bf0a1954
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/timestamp.rb
@@ -0,0 +1,11 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class Timestamp < Value # :nodoc:
+ def type
+ :timestamp
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/type_map.rb b/activerecord/lib/active_record/connection_adapters/type/type_map.rb
new file mode 100644
index 0000000000..d89171a820
--- /dev/null
+++ b/activerecord/lib/active_record/connection_adapters/type/type_map.rb
@@ -0,0 +1,50 @@
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class TypeMap # :nodoc:
+ def initialize
+ @mapping = {}
+ end
+
+ def lookup(lookup_key)
+ matching_pair = @mapping.reverse_each.detect do |key, _|
+ key === lookup_key
+ end
+
+ if matching_pair
+ matching_pair.last.call(lookup_key)
+ else
+ default_value
+ end
+ end
+
+ def register_type(key, value = nil, &block)
+ raise ::ArgumentError unless value || block
+
+ if block
+ @mapping[key] = block
+ else
+ @mapping[key] = proc { value }
+ end
+ end
+
+ def alias_type(key, target_key)
+ register_type(key) do |sql_type|
+ metadata = sql_type[/\(.*\)/, 0]
+ lookup("#{target_key}#{metadata}")
+ end
+ end
+
+ def clear
+ @mapping.clear
+ end
+
+ private
+
+ def default_value
+ @default_value ||= Value.new
+ end
+ end
+ end
+ end
+end
diff --git a/activerecord/lib/active_record/connection_adapters/type/value.rb b/activerecord/lib/active_record/connection_adapters/type/value.rb
index 36f680050f..f7d7b9351b 100644
--- a/activerecord/lib/active_record/connection_adapters/type/value.rb
+++ b/activerecord/lib/active_record/connection_adapters/type/value.rb
@@ -2,6 +2,7 @@ module ActiveRecord
module ConnectionAdapters
module Type
class Value # :nodoc:
+ def type; end
end
end
end
diff --git a/activerecord/lib/active_record/migration.rb b/activerecord/lib/active_record/migration.rb
index fc579e5c0f..8fe32bcb6c 100644
--- a/activerecord/lib/active_record/migration.rb
+++ b/activerecord/lib/active_record/migration.rb
@@ -640,7 +640,7 @@ module ActiveRecord
say_with_time "#{method}(#{arg_list})" do
unless @connection.respond_to? :revert
- unless arguments.empty? || method == :execute
+ unless arguments.empty? || [:execute, :enable_extension, :disable_extension].include?(method)
arguments[0] = proper_table_name(arguments.first, table_name_options)
arguments[1] = proper_table_name(arguments.second, table_name_options) if method == :rename_table
end
diff --git a/activerecord/test/cases/adapters/mysql/quoting_test.rb b/activerecord/test/cases/adapters/mysql/quoting_test.rb
index f650e3fde8..d8a954efa8 100644
--- a/activerecord/test/cases/adapters/mysql/quoting_test.rb
+++ b/activerecord/test/cases/adapters/mysql/quoting_test.rb
@@ -9,13 +9,13 @@ module ActiveRecord
end
def test_type_cast_true
- c = Column.new(nil, 1, Type::Value.new, 'boolean')
+ c = Column.new(nil, 1, Type::Boolean.new)
assert_equal 1, @conn.type_cast(true, nil)
assert_equal 1, @conn.type_cast(true, c)
end
def test_type_cast_false
- c = Column.new(nil, 1, Type::Value.new, 'boolean')
+ c = Column.new(nil, 1, Type::Boolean.new)
assert_equal 0, @conn.type_cast(false, nil)
assert_equal 0, @conn.type_cast(false, c)
end
diff --git a/activerecord/test/cases/adapters/postgresql/composite_test.rb b/activerecord/test/cases/adapters/postgresql/composite_test.rb
index 68b9e6daf7..1e7071c136 100644
--- a/activerecord/test/cases/adapters/postgresql/composite_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/composite_test.rb
@@ -85,7 +85,6 @@ class PostgresqlCompositeWithCustomOIDTest < ActiveRecord::TestCase
class FullAddressType
def type; :full_address end
- def simplified_type(sql_type); type end
def type_cast(value)
if value =~ /\("?([^",]*)"?,"?([^",]*)"?\)/
diff --git a/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb
new file mode 100644
index 0000000000..91058f8681
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/extension_migration_test.rb
@@ -0,0 +1,65 @@
+require "cases/helper"
+require "active_record/base"
+require "active_record/connection_adapters/postgresql_adapter"
+
+class PostgresqlExtensionMigrationTest < ActiveRecord::TestCase
+ self.use_transactional_fixtures = false
+
+ class EnableHstore < ActiveRecord::Migration
+ def change
+ enable_extension "hstore"
+ end
+ end
+
+ class DisableHstore < ActiveRecord::Migration
+ def change
+ disable_extension "hstore"
+ end
+ end
+
+ def setup
+ super
+
+ @connection = ActiveRecord::Base.connection
+
+ unless @connection.supports_extensions?
+ return skip("no extension support")
+ end
+
+ @old_schema_migration_tabel_name = ActiveRecord::SchemaMigration.table_name
+ @old_tabel_name_prefix = ActiveRecord::Base.table_name_prefix
+ @old_tabel_name_suffix = ActiveRecord::Base.table_name_suffix
+
+ ActiveRecord::Base.table_name_prefix = "p_"
+ ActiveRecord::Base.table_name_suffix = "_s"
+ ActiveRecord::SchemaMigration.delete_all rescue nil
+ ActiveRecord::SchemaMigration.table_name = "p_schema_migrations_s"
+ ActiveRecord::Migration.verbose = false
+ end
+
+ def teardown
+ ActiveRecord::Base.table_name_prefix = @old_tabel_name_prefix
+ ActiveRecord::Base.table_name_suffix = @old_tabel_name_suffix
+ ActiveRecord::SchemaMigration.delete_all rescue nil
+ ActiveRecord::Migration.verbose = true
+ ActiveRecord::SchemaMigration.table_name = @old_schema_migration_tabel_name
+
+ super
+ end
+
+ def test_enable_extension_migration_ignores_prefix_and_suffix
+ @connection.disable_extension("hstore")
+
+ migrations = [EnableHstore.new(nil, 1)]
+ ActiveRecord::Migrator.new(:up, migrations).migrate
+ assert @connection.extension_enabled?("hstore"), "extension hstore should be enabled"
+ end
+
+ def test_disable_extension_migration_ignores_prefix_and_suffix
+ @connection.enable_extension("hstore")
+
+ migrations = [DisableHstore.new(nil, 1)]
+ ActiveRecord::Migrator.new(:up, migrations).migrate
+ assert_not @connection.extension_enabled?("hstore"), "extension hstore should not be enabled"
+ end
+end
diff --git a/activerecord/test/cases/adapters/postgresql/schema_test.rb b/activerecord/test/cases/adapters/postgresql/schema_test.rb
index 9d4d79c0c6..11ec7599a3 100644
--- a/activerecord/test/cases/adapters/postgresql/schema_test.rb
+++ b/activerecord/test/cases/adapters/postgresql/schema_test.rb
@@ -352,21 +352,6 @@ class SchemaTest < ActiveRecord::TestCase
end
end
- def test_extract_schema_and_table
- {
- %(table_name) => [nil,'table_name'],
- %("table.name") => [nil,'table.name'],
- %(schema.table_name) => %w{schema table_name},
- %("schema".table_name) => %w{schema table_name},
- %(schema."table_name") => %w{schema table_name},
- %("schema"."table_name") => %w{schema table_name},
- %("even spaces".table) => ['even spaces','table'],
- %(schema."table.name") => ['schema', 'table.name']
- }.each do |given, expect|
- assert_equal expect, @connection.send(:extract_schema_and_table, given)
- end
- end
-
private
def columns(table_name)
@connection.send(:column_definitions, table_name).map do |name, type, default|
diff --git a/activerecord/test/cases/adapters/postgresql/utils_test.rb b/activerecord/test/cases/adapters/postgresql/utils_test.rb
new file mode 100644
index 0000000000..e6d7868e9a
--- /dev/null
+++ b/activerecord/test/cases/adapters/postgresql/utils_test.rb
@@ -0,0 +1,20 @@
+require 'cases/helper'
+
+class PostgreSQLUtilsTest < ActiveSupport::TestCase
+ include ActiveRecord::ConnectionAdapters::PostgreSQL::Utils
+
+ def test_extract_schema_and_table
+ {
+ %(table_name) => [nil,'table_name'],
+ %("table.name") => [nil,'table.name'],
+ %(schema.table_name) => %w{schema table_name},
+ %("schema".table_name) => %w{schema table_name},
+ %(schema."table_name") => %w{schema table_name},
+ %("schema"."table_name") => %w{schema table_name},
+ %("even spaces".table) => ['even spaces','table'],
+ %(schema."table.name") => ['schema', 'table.name']
+ }.each do |given, expect|
+ assert_equal expect, extract_schema_and_table(given)
+ end
+ end
+end
diff --git a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
index 63170e710e..0c4f06d6a9 100644
--- a/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
+++ b/activerecord/test/cases/adapters/sqlite3/quoting_test.rb
@@ -47,13 +47,13 @@ module ActiveRecord
end
def test_type_cast_true
- c = Column.new(nil, 1, Type::Value.new, 'int')
+ c = Column.new(nil, 1, Type::Integer.new)
assert_equal 't', @conn.type_cast(true, nil)
assert_equal 1, @conn.type_cast(true, c)
end
def test_type_cast_false
- c = Column.new(nil, 1, Type::Value.new, 'int')
+ c = Column.new(nil, 1, Type::Integer.new)
assert_equal 'f', @conn.type_cast(false, nil)
assert_equal 0, @conn.type_cast(false, c)
end
@@ -61,16 +61,16 @@ module ActiveRecord
def test_type_cast_string
assert_equal '10', @conn.type_cast('10', nil)
- c = Column.new(nil, 1, Type::Value.new, 'int')
+ c = Column.new(nil, 1, Type::Integer.new)
assert_equal 10, @conn.type_cast('10', c)
- c = Column.new(nil, 1, Type::Value.new, 'float')
+ c = Column.new(nil, 1, Type::Float.new)
assert_equal 10.1, @conn.type_cast('10.1', c)
- c = Column.new(nil, 1, Type::Value.new, 'binary')
+ c = Column.new(nil, 1, Type::Binary.new)
assert_equal '10.1', @conn.type_cast('10.1', c)
- c = Column.new(nil, 1, Type::Value.new, 'date')
+ c = Column.new(nil, 1, Type::Date.new)
assert_equal '10.1', @conn.type_cast('10.1', c)
end
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb
index c88a843282..7c7c1fbfbd 100644
--- a/activerecord/test/cases/base_test.rb
+++ b/activerecord/test/cases/base_test.rb
@@ -774,8 +774,14 @@ class BasicsTest < ActiveRecord::TestCase
assert_equal("c", duped_topic.title)
end
+ DeveloperSalary = Struct.new(:amount)
def test_dup_with_aggregate_of_same_name_as_attribute
- dev = DeveloperWithAggregate.find(1)
+ developer_with_aggregate = Class.new(ActiveRecord::Base) do
+ self.table_name = 'developers'
+ composed_of :salary, :class_name => 'BasicsTest::DeveloperSalary', :mapping => [%w(salary amount)]
+ end
+
+ dev = developer_with_aggregate.find(1)
assert_kind_of DeveloperSalary, dev.salary
dup = nil
diff --git a/activerecord/test/cases/column_definition_test.rb b/activerecord/test/cases/column_definition_test.rb
index 33aba6421e..23e6254577 100644
--- a/activerecord/test/cases/column_definition_test.rb
+++ b/activerecord/test/cases/column_definition_test.rb
@@ -12,13 +12,13 @@ module ActiveRecord
end
def test_can_set_coder
- column = Column.new("title", nil, Type::Value.new, "varchar(20)")
+ column = Column.new("title", nil, Type::String.new, "varchar(20)")
column.coder = YAML
assert_equal YAML, column.coder
end
def test_encoded?
- column = Column.new("title", nil, Type::Value.new, "varchar(20)")
+ column = Column.new("title", nil, Type::String.new, "varchar(20)")
assert !column.encoded?
column.coder = YAML
@@ -26,7 +26,7 @@ module ActiveRecord
end
def test_type_case_coded_column
- column = Column.new("title", nil, Type::Value.new, "varchar(20)")
+ column = Column.new("title", nil, Type::String.new, "varchar(20)")
column.coder = YAML
assert_equal "hello", column.type_cast("--- hello")
end
@@ -34,7 +34,7 @@ module ActiveRecord
# Avoid column definitions in create table statements like:
# `title` varchar(255) DEFAULT NULL
def test_should_not_include_default_clause_when_default_is_null
- column = Column.new("title", nil, Type::Value.new, "varchar(20)")
+ column = Column.new("title", nil, Type::String.new, "varchar(20)")
column_def = ColumnDefinition.new(
column.name, "string",
column.limit, column.precision, column.scale, column.default, column.null)
@@ -42,7 +42,7 @@ module ActiveRecord
end
def test_should_include_default_clause_when_default_is_present
- column = Column.new("title", "Hello", Type::Value.new, "varchar(20)")
+ column = Column.new("title", "Hello", Type::String.new, "varchar(20)")
column_def = ColumnDefinition.new(
column.name, "string",
column.limit, column.precision, column.scale, column.default, column.null)
@@ -50,7 +50,7 @@ module ActiveRecord
end
def test_should_specify_not_null_if_null_option_is_false
- column = Column.new("title", "Hello", Type::Value.new, "varchar(20)", false)
+ column = Column.new("title", "Hello", Type::String.new, "varchar(20)", false)
column_def = ColumnDefinition.new(
column.name, "string",
column.limit, column.precision, column.scale, column.default, column.null)
@@ -59,68 +59,68 @@ module ActiveRecord
if current_adapter?(:MysqlAdapter)
def test_should_set_default_for_mysql_binary_data_types
- binary_column = MysqlAdapter::Column.new("title", "a", Type::Value.new, "binary(1)")
+ binary_column = MysqlAdapter::Column.new("title", "a", Type::Binary.new, "binary(1)")
assert_equal "a", binary_column.default
- varbinary_column = MysqlAdapter::Column.new("title", "a", Type::Value.new, "varbinary(1)")
+ varbinary_column = MysqlAdapter::Column.new("title", "a", Type::Binary.new, "varbinary(1)")
assert_equal "a", varbinary_column.default
end
def test_should_not_set_default_for_blob_and_text_data_types
assert_raise ArgumentError do
- MysqlAdapter::Column.new("title", "a", Type::Value.new, "blob")
+ MysqlAdapter::Column.new("title", "a", Type::Binary.new, "blob")
end
assert_raise ArgumentError do
- MysqlAdapter::Column.new("title", "Hello", Type::Value.new, "text")
+ MysqlAdapter::Column.new("title", "Hello", Type::Text.new)
end
- text_column = MysqlAdapter::Column.new("title", nil, Type::Value.new, "text")
+ text_column = MysqlAdapter::Column.new("title", nil, Type::Text.new)
assert_equal nil, text_column.default
- not_null_text_column = MysqlAdapter::Column.new("title", nil, Type::Value.new, "text", false)
+ not_null_text_column = MysqlAdapter::Column.new("title", nil, Type::Text.new, "text", false)
assert_equal "", not_null_text_column.default
end
def test_has_default_should_return_false_for_blob_and_text_data_types
- blob_column = MysqlAdapter::Column.new("title", nil, Type::Value.new, "blob")
+ blob_column = MysqlAdapter::Column.new("title", nil, Type::Binary.new, "blob")
assert !blob_column.has_default?
- text_column = MysqlAdapter::Column.new("title", nil, Type::Value.new, "text")
+ text_column = MysqlAdapter::Column.new("title", nil, Type::Text.new)
assert !text_column.has_default?
end
end
if current_adapter?(:Mysql2Adapter)
def test_should_set_default_for_mysql_binary_data_types
- binary_column = Mysql2Adapter::Column.new("title", "a", Type::Value.new, "binary(1)")
+ binary_column = Mysql2Adapter::Column.new("title", "a", Type::Binary.new, "binary(1)")
assert_equal "a", binary_column.default
- varbinary_column = Mysql2Adapter::Column.new("title", "a", Type::Value.new, "varbinary(1)")
+ varbinary_column = Mysql2Adapter::Column.new("title", "a", Type::Binary.new, "varbinary(1)")
assert_equal "a", varbinary_column.default
end
def test_should_not_set_default_for_blob_and_text_data_types
assert_raise ArgumentError do
- Mysql2Adapter::Column.new("title", "a", Type::Value.new, "blob")
+ Mysql2Adapter::Column.new("title", "a", Type::Binary.new, "blob")
end
assert_raise ArgumentError do
- Mysql2Adapter::Column.new("title", "Hello", Type::Value.new, "text")
+ Mysql2Adapter::Column.new("title", "Hello", Type::Text.new)
end
- text_column = Mysql2Adapter::Column.new("title", nil, Type::Value.new, "text")
+ text_column = Mysql2Adapter::Column.new("title", nil, Type::Text.new)
assert_equal nil, text_column.default
- not_null_text_column = Mysql2Adapter::Column.new("title", nil, Type::Value.new, "text", false)
+ not_null_text_column = Mysql2Adapter::Column.new("title", nil, Type::Text.new, "text", false)
assert_equal "", not_null_text_column.default
end
def test_has_default_should_return_false_for_blob_and_text_data_types
- blob_column = Mysql2Adapter::Column.new("title", nil, Type::Value.new, "blob")
+ blob_column = Mysql2Adapter::Column.new("title", nil, Type::Binary.new, "blob")
assert !blob_column.has_default?
- text_column = Mysql2Adapter::Column.new("title", nil, Type::Value.new, "text")
+ text_column = Mysql2Adapter::Column.new("title", nil, Type::Text.new)
assert !text_column.has_default?
end
end
diff --git a/activerecord/test/cases/column_test.rb b/activerecord/test/cases/column_test.rb
index c2135d75da..91605a52f9 100644
--- a/activerecord/test/cases/column_test.rb
+++ b/activerecord/test/cases/column_test.rb
@@ -5,7 +5,7 @@ module ActiveRecord
module ConnectionAdapters
class ColumnTest < ActiveRecord::TestCase
def test_type_cast_boolean
- column = Column.new("field", nil, Type::Value.new, "boolean")
+ column = Column.new("field", nil, Type::Boolean.new)
assert column.type_cast('').nil?
assert column.type_cast(nil).nil?
@@ -36,14 +36,14 @@ module ActiveRecord
end
def test_type_cast_string
- column = Column.new("field", nil, Type::Value.new, "varchar")
+ column = Column.new("field", nil, Type::String.new)
assert_equal "1", column.type_cast(true)
assert_equal "0", column.type_cast(false)
assert_equal "123", column.type_cast(123)
end
def test_type_cast_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
assert_equal 1, column.type_cast(1)
assert_equal 1, column.type_cast('1')
assert_equal 1, column.type_cast('1ignore')
@@ -56,50 +56,50 @@ module ActiveRecord
end
def test_type_cast_non_integer_to_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
assert_nil column.type_cast([1,2])
assert_nil column.type_cast({1 => 2})
assert_nil column.type_cast((1..2))
end
def test_type_cast_activerecord_to_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
firm = Firm.create(:name => 'Apple')
assert_nil column.type_cast(firm)
end
def test_type_cast_object_without_to_i_to_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
assert_nil column.type_cast(Object.new)
end
def test_type_cast_nan_and_infinity_to_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
assert_nil column.type_cast(Float::NAN)
assert_nil column.type_cast(1.0/0.0)
end
def test_type_cast_float
- column = Column.new("field", nil, Type::Value.new, "float")
+ column = Column.new("field", nil, Type::Float.new)
assert_equal 1.0, column.type_cast("1")
end
def test_type_cast_decimal
- column = Column.new("field", nil, Type::Value.new, "decimal")
+ column = Column.new("field", nil, Type::Decimal.new)
assert_equal BigDecimal.new("0"), column.type_cast(BigDecimal.new("0"))
assert_equal BigDecimal.new("123"), column.type_cast(123.0)
assert_equal BigDecimal.new("1"), column.type_cast(:"1")
end
def test_type_cast_binary
- column = Column.new("field", nil, Type::Value.new, "binary")
+ column = Column.new("field", nil, Type::Binary.new)
assert_equal nil, column.type_cast(nil)
assert_equal "1", column.type_cast("1")
assert_equal 1, column.type_cast(1)
end
def test_type_cast_time
- column = Column.new("field", nil, Type::Value.new, "time")
+ column = Column.new("field", nil, Type::Time.new)
assert_equal nil, column.type_cast(nil)
assert_equal nil, column.type_cast('')
assert_equal nil, column.type_cast('ABC')
@@ -109,7 +109,11 @@ module ActiveRecord
end
def test_type_cast_datetime_and_timestamp
- [Column.new("field", nil, Type::Value.new, "datetime"), Column.new("field", nil, Type::Value.new, "timestamp")].each do |column|
+ columns = [
+ Column.new("field", nil, Type::DateTime.new),
+ Column.new("field", nil, Type::Timestamp.new),
+ ]
+ columns.each do |column|
assert_equal nil, column.type_cast(nil)
assert_equal nil, column.type_cast('')
assert_equal nil, column.type_cast(' ')
@@ -121,7 +125,7 @@ module ActiveRecord
end
def test_type_cast_date
- column = Column.new("field", nil, Type::Value.new, "date")
+ column = Column.new("field", nil, Type::Date.new)
assert_equal nil, column.type_cast(nil)
assert_equal nil, column.type_cast('')
assert_equal nil, column.type_cast(' ')
@@ -132,7 +136,7 @@ module ActiveRecord
end
def test_type_cast_duration_to_integer
- column = Column.new("field", nil, Type::Value.new, "integer")
+ column = Column.new("field", nil, Type::Integer.new)
assert_equal 1800, column.type_cast(30.minutes)
assert_equal 7200, column.type_cast(2.hours)
end
@@ -147,7 +151,7 @@ module ActiveRecord
if current_adapter?(:SQLite3Adapter)
def test_binary_encoding
- column = SQLite3Column.new("field", nil, Type::Value.new, "binary")
+ column = SQLite3Column.new("field", nil, Type::Binary.new)
utf8_string = "a string".encode(Encoding::UTF_8)
type_cast = column.type_cast(utf8_string)
diff --git a/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb
new file mode 100644
index 0000000000..d4d67487db
--- /dev/null
+++ b/activerecord/test/cases/connection_adapters/mysql_type_lookup_test.rb
@@ -0,0 +1,61 @@
+require "cases/helper"
+
+if current_adapter?(:MysqlAdapter, :Mysql2Adapter)
+module ActiveRecord
+ module ConnectionAdapters
+ class MysqlTypeLookupTest < ActiveRecord::TestCase
+ setup do
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def test_boolean_types
+ emulate_booleans(true) do
+ assert_lookup_type :boolean, 'tinyint(1)'
+ assert_lookup_type :boolean, 'TINYINT(1)'
+ end
+ end
+
+ def test_string_types
+ assert_lookup_type :string, "enum('one', 'two', 'three')"
+ assert_lookup_type :string, "ENUM('one', 'two', 'three')"
+ assert_lookup_type :string, "set('one', 'two', 'three')"
+ assert_lookup_type :string, "SET('one', 'two', 'three')"
+ end
+
+ def test_binary_types
+ assert_lookup_type :binary, 'bit'
+ assert_lookup_type :binary, 'BIT'
+ end
+
+ def test_integer_types
+ emulate_booleans(false) do
+ assert_lookup_type :integer, 'tinyint(1)'
+ assert_lookup_type :integer, 'TINYINT(1)'
+ assert_lookup_type :integer, 'year'
+ assert_lookup_type :integer, 'YEAR'
+ end
+ end
+
+ private
+
+ def assert_lookup_type(type, lookup)
+ cast_type = @connection.type_map.lookup(lookup)
+ assert_equal type, cast_type.type
+ end
+
+ def emulate_booleans(value)
+ old_emulate_booleans = @connection.emulate_booleans
+ change_emulate_booleans(value)
+ yield
+ ensure
+ change_emulate_booleans(old_emulate_booleans)
+ end
+
+ def change_emulate_booleans(value)
+ @connection.emulate_booleans = value
+ @connection.clear_cache!
+ end
+ end
+ end
+end
+end
diff --git a/activerecord/test/cases/connection_adapters/type/type_map_test.rb b/activerecord/test/cases/connection_adapters/type/type_map_test.rb
new file mode 100644
index 0000000000..565f44eef8
--- /dev/null
+++ b/activerecord/test/cases/connection_adapters/type/type_map_test.rb
@@ -0,0 +1,102 @@
+require "cases/helper"
+
+module ActiveRecord
+ module ConnectionAdapters
+ module Type
+ class TypeMapTest < ActiveRecord::TestCase
+ def test_default_type
+ mapping = TypeMap.new
+
+ assert_kind_of Value, mapping.lookup(:undefined)
+ end
+
+ def test_registering_types
+ boolean = Boolean.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/boolean/i, boolean)
+
+ assert_equal mapping.lookup('boolean'), boolean
+ end
+
+ def test_overriding_registered_types
+ time = Time.new
+ timestamp = Timestamp.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/time/i, time)
+ mapping.register_type(/time/i, timestamp)
+
+ assert_equal mapping.lookup('time'), timestamp
+ end
+
+ def test_fuzzy_lookup
+ string = String.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/varchar/i, string)
+
+ assert_equal mapping.lookup('varchar(20)'), string
+ end
+
+ def test_aliasing_types
+ string = String.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/string/i, string)
+ mapping.alias_type(/varchar/i, 'string')
+
+ assert_equal mapping.lookup('varchar'), string
+ end
+
+ def test_changing_type_changes_aliases
+ time = Time.new
+ timestamp = Timestamp.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/timestamp/i, time)
+ mapping.alias_type(/datetime/i, 'timestamp')
+ mapping.register_type(/timestamp/i, timestamp)
+
+ assert_equal mapping.lookup('datetime'), timestamp
+ end
+
+ def test_aliases_keep_metadata
+ mapping = TypeMap.new
+
+ mapping.register_type(/decimal/i) { |sql_type| sql_type }
+ mapping.alias_type(/number/i, 'decimal')
+
+ assert_equal mapping.lookup('number(20)'), 'decimal(20)'
+ assert_equal mapping.lookup('number'), 'decimal'
+ end
+
+ def test_register_proc
+ string = String.new
+ binary = Binary.new
+ mapping = TypeMap.new
+
+ mapping.register_type(/varchar/i) do |type|
+ if type.include?('(')
+ string
+ else
+ binary
+ end
+ end
+
+ assert_equal mapping.lookup('varchar(20)'), string
+ assert_equal mapping.lookup('varchar'), binary
+ end
+
+ def test_requires_value_or_block
+ mapping = TypeMap.new
+
+ assert_raises(ArgumentError) do
+ mapping.register_type(/only key/i)
+ end
+ end
+ end
+ end
+ end
+end
+
diff --git a/activerecord/test/cases/connection_adapters/type_lookup_test.rb b/activerecord/test/cases/connection_adapters/type_lookup_test.rb
new file mode 100644
index 0000000000..a5b01260d3
--- /dev/null
+++ b/activerecord/test/cases/connection_adapters/type_lookup_test.rb
@@ -0,0 +1,100 @@
+require "cases/helper"
+
+unless current_adapter?(:PostgreSQLAdapter) # PostgreSQL does not use type strigns for lookup
+module ActiveRecord
+ module ConnectionAdapters
+ class TypeLookupTest < ActiveRecord::TestCase
+ setup do
+ @connection = ActiveRecord::Base.connection
+ end
+
+ def test_boolean_types
+ assert_lookup_type :boolean, 'boolean'
+ assert_lookup_type :boolean, 'BOOLEAN'
+ end
+
+ def test_string_types
+ assert_lookup_type :string, 'char'
+ assert_lookup_type :string, 'varchar'
+ assert_lookup_type :string, 'VARCHAR'
+ assert_lookup_type :string, 'varchar(255)'
+ assert_lookup_type :string, 'character varying'
+ end
+
+ def test_binary_types
+ assert_lookup_type :binary, 'binary'
+ assert_lookup_type :binary, 'BINARY'
+ assert_lookup_type :binary, 'blob'
+ assert_lookup_type :binary, 'BLOB'
+ end
+
+ def test_text_types
+ assert_lookup_type :text, 'text'
+ assert_lookup_type :text, 'TEXT'
+ assert_lookup_type :text, 'clob'
+ assert_lookup_type :text, 'CLOB'
+ end
+
+ def test_date_types
+ assert_lookup_type :date, 'date'
+ assert_lookup_type :date, 'DATE'
+ end
+
+ def test_time_types
+ assert_lookup_type :time, 'time'
+ assert_lookup_type :time, 'TIME'
+ end
+
+ def test_timestamp_types
+ assert_lookup_type :timestamp, 'timestamp'
+ assert_lookup_type :timestamp, 'TIMESTAMP'
+ end
+
+ def test_datetime_types
+ assert_lookup_type :datetime, 'datetime'
+ assert_lookup_type :datetime, 'DATETIME'
+ end
+
+ def test_decimal_types
+ assert_lookup_type :decimal, 'decimal'
+ assert_lookup_type :decimal, 'decimal(2,8)'
+ assert_lookup_type :decimal, 'DECIMAL'
+ assert_lookup_type :decimal, 'numeric'
+ assert_lookup_type :decimal, 'numeric(2,8)'
+ assert_lookup_type :decimal, 'NUMERIC'
+ assert_lookup_type :decimal, 'number'
+ assert_lookup_type :decimal, 'number(2,8)'
+ assert_lookup_type :decimal, 'NUMBER'
+ end
+
+ def test_float_types
+ assert_lookup_type :float, 'float'
+ assert_lookup_type :float, 'FLOAT'
+ assert_lookup_type :float, 'double'
+ assert_lookup_type :float, 'DOUBLE'
+ end
+
+ def test_integer_types
+ assert_lookup_type :integer, 'integer'
+ assert_lookup_type :integer, 'INTEGER'
+ assert_lookup_type :integer, 'tinyint'
+ assert_lookup_type :integer, 'smallint'
+ assert_lookup_type :integer, 'bigint'
+ assert_lookup_type :integer, 'decimal(2)'
+ assert_lookup_type :integer, 'decimal(2,0)'
+ assert_lookup_type :integer, 'numeric(2)'
+ assert_lookup_type :integer, 'numeric(2,0)'
+ assert_lookup_type :integer, 'number(2)'
+ assert_lookup_type :integer, 'number(2,0)'
+ end
+
+ private
+
+ def assert_lookup_type(type, lookup)
+ cast_type = @connection.type_map.lookup(lookup)
+ assert_equal type, cast_type.type
+ end
+ end
+ end
+end
+end
diff --git a/activerecord/test/cases/migration/columns_test.rb b/activerecord/test/cases/migration/columns_test.rb
index 2d7a7ec73a..a7c287515d 100644
--- a/activerecord/test/cases/migration/columns_test.rb
+++ b/activerecord/test/cases/migration/columns_test.rb
@@ -274,6 +274,16 @@ module ActiveRecord
ensure
connection.drop_table(:my_table) rescue nil
end
+
+ def test_column_with_index
+ connection.create_table "my_table", force: true do |t|
+ t.string :item_number, index: true
+ end
+
+ assert connection.index_exists?("my_table", :item_number, name: :index_my_table_on_item_number)
+ ensure
+ connection.drop_table(:my_table) rescue nil
+ end
end
end
end
diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb
index 0a614c3bfd..5bd2f00129 100644
--- a/activerecord/test/models/developer.rb
+++ b/activerecord/test/models/developer.rb
@@ -76,12 +76,6 @@ class AuditLog < ActiveRecord::Base
belongs_to :unvalidated_developer, :class_name => 'Developer'
end
-DeveloperSalary = Struct.new(:amount)
-class DeveloperWithAggregate < ActiveRecord::Base
- self.table_name = 'developers'
- composed_of :salary, :class_name => 'DeveloperSalary', :mapping => [%w(salary amount)]
-end
-
class DeveloperWithBeforeDestroyRaise < ActiveRecord::Base
self.table_name = 'developers'
has_and_belongs_to_many :projects, :join_table => 'developers_projects', :foreign_key => 'developer_id'
diff --git a/ci/travis.rb b/ci/travis.rb
index 7e68993332..956a01dbee 100755
--- a/ci/travis.rb
+++ b/ci/travis.rb
@@ -52,7 +52,7 @@ class Build
def tasks
if activerecord?
- ['mysql:rebuild_databases', "#{adapter}:#{'isolated_' if isolated?}test"]
+ ['db:mysql:rebuild', "#{adapter}:#{'isolated_' if isolated?}test"]
else
["test#{':isolated' if isolated?}"]
end
diff --git a/guides/source/active_record_postgresql.md b/guides/source/active_record_postgresql.md
index 169a48afb9..b69c8dbb7a 100644
--- a/guides/source/active_record_postgresql.md
+++ b/guides/source/active_record_postgresql.md
@@ -3,13 +3,6 @@ Active Record and PostgreSQL
This guide covers PostgreSQL specific usage of Active Record.
-In order to use the PostgreSQL adapter you need to have at least version 8.2
-installed. Older versions are not supported.
-
-To get started with PostgreSQL have a look at the
-[configuring Rails guide](configuring.html#configuring-a-postgresql-database).
-It describes how to properly setup Active Record for PostgreSQL.
-
After reading this guide, you will know:
* How to use PostgreSQL's datatypes.
@@ -18,6 +11,13 @@ After reading this guide, you will know:
--------------------------------------------------------------------------------
+In order to use the PostgreSQL adapter you need to have at least version 8.2
+installed. Older versions are not supported.
+
+To get started with PostgreSQL have a look at the
+[configuring Rails guide](configuring.html#configuring-a-postgresql-database).
+It describes how to properly setup Active Record for PostgreSQL.
+
Datatypes
---------
@@ -171,7 +171,7 @@ event.ends_at # => Thu, 13 Feb 2014
* [type definition](http://www.postgresql.org/docs/9.3/static/rowtypes.html)
-Currently there is no special support for composite types. They are mapped to as
+Currently there is no special support for composite types. They are mapped to
normal text columns:
```sql
@@ -287,8 +287,9 @@ user.save!
* [type definition](http://www.postgresql.org/docs/9.3/static/datatype-net-types.html)
-The types `inet` and `cidr` are mapped to Ruby [`IPAddr`](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/ipaddr/rdoc/IPAddr.html) objects. The
-`macaddr` type is mapped to normal text.
+The types `inet` and `cidr` are mapped to Ruby
+[`IPAddr`](http://www.ruby-doc.org/stdlib-2.1.1/libdoc/ipaddr/rdoc/IPAddr.html)
+objects. The `macaddr` type is mapped to normal text.
```ruby
# db/migrate/20140508144913_create_devices.rb
diff --git a/guides/source/api_documentation_guidelines.md b/guides/source/api_documentation_guidelines.md
index dc9f9d1d54..f01675b50d 100644
--- a/guides/source/api_documentation_guidelines.md
+++ b/guides/source/api_documentation_guidelines.md
@@ -290,7 +290,7 @@ self.class_eval %{
Method Visibility
-----------------
-When writing documentation for Rails, it's important to understand the difference between public API (or User-facing) vs. internal API.
+When writing documentation for Rails, it's important to understand the difference between public user-facing API vs internal API.
Rails, like most libraries, uses the private keyword from Ruby for defining internal API. However, public API follows a slightly different convention. Instead of assuming all public methods are designed for user consumption, Rails uses the `:nodoc:` directive to annotate these kinds of methods as internal API.
@@ -306,17 +306,16 @@ module ActiveRecord::Core::ClassMethods
end
```
-If you thought, "this method looks like a public class method for `ActiveRecord::Core`", you were right. But actually the Rails team doesn't want users to rely on this method. So they mark it as `:nodoc:` and it's removed from public documentation. The reasoning behind this is to allow the team to change these methods according to their internal needs across releases as they see fit. The name of this method could change, or the return value, or this entire class may disappear; there's no guarantee and so you shouldn't depend on this API in your plugin or application. Otherwise, you risk your app or gem breaking when you upgrade to a newer release of Rails.
+If you thought, "this method looks like a public class method for `ActiveRecord::Core`", you were right. But actually the Rails team doesn't want users to rely on this method. So they mark it as `:nodoc:` and it's removed from public documentation. The reasoning behind this is to allow the team to change these methods according to their internal needs across releases as they see fit. The name of this method could change, or the return value, or this entire class may disappear; there's no guarantee and so you shouldn't depend on this API in your plugins or applications. Otherwise, you risk your app or gem breaking when you upgrade to a newer release of Rails.
-As a contributor, it's important to think about whether this API is meant for end-user consumption. The Rails team is committed to not making any breaking changes to public API across releases without going through a full deprecation cycle, which takes an eternity. It's recommended that you `:nodoc:` any of your internal methods/classes unless they're already private (meaning visibility), in which case it's internal by default. Once the API stabilizes the visibility can change from private later, but changing public API is much harder due to backwards compatibility.
+As a contributor, it's important to think about whether this API is meant for end-user consumption. The Rails team is committed to not making any breaking changes to public API across releases without going through a full deprecation cycle. It's recommended that you `:nodoc:` any of your internal methods/classes unless they're already private (meaning visibility), in which case it's internal by default. Once the API stabilizes the visibility can change, but changing public API is much harder due to backwards compatibility.
A class or module is marked with `:nodoc:` to indicate that all methods are internal API and should never be used directly.
-If you come across an existing `:nodoc:` you should tread lightly. Consider asking someone from the core team or author of the code before removing it. This should almost always happen through a Pull Request process instead of the docrails project.
+If you come across an existing `:nodoc:` you should tread lightly. Consider asking someone from the core team or author of the code before removing it. This should almost always happen through a pull request instead of the docrails project.
A `:nodoc:` should never be added simply because a method or class is missing documentation. There may be an instance where an internal public method wasn't given a `:nodoc:` by mistake, for example when switching a method from private to public visibility. When this happens it should be discussed over a PR on a case-by-case basis and never committed directly to docrails.
-To summarize, the Rails team uses `:nodoc:` to mark publicly visible methods and classes for internal use; changes to the visibility of API should be considered carefully and discussed over a Pull Request first.
-
-For whatever reason, you have a question on how the Rails team handles certain API don't hesitate to open a ticket or send a patch to the [issue tracker](https://github.com/rails/rails/issues).
+To summarize, the Rails team uses `:nodoc:` to mark publicly visible methods and classes for internal use; changes to the visibility of API should be considered carefully and discussed over a pull request first.
+If you have a question on how the Rails team handles certain API, don't hesitate to open a ticket or send a patch to the [issue tracker](https://github.com/rails/rails/issues).
diff --git a/guides/source/contributing_to_ruby_on_rails.md b/guides/source/contributing_to_ruby_on_rails.md
index 57010b85c3..ef4633ac1a 100644
--- a/guides/source/contributing_to_ruby_on_rails.md
+++ b/guides/source/contributing_to_ruby_on_rails.md
@@ -265,15 +265,15 @@ This is how you run the Active Record test suite only for SQLite3:
```bash
$ cd activerecord
-$ bundle exec rake test_sqlite3
+$ bundle exec rake test:sqlite3
```
You can now run the tests as you did for `sqlite3`. The tasks are respectively
```bash
-test_mysql
-test_mysql2
-test_postgresql
+test:mysql
+test:mysql2
+test:postgresql
```
Finally,
diff --git a/guides/source/development_dependencies_install.md b/guides/source/development_dependencies_install.md
index b0e070120d..b134c9d2d0 100644
--- a/guides/source/development_dependencies_install.md
+++ b/guides/source/development_dependencies_install.md
@@ -249,7 +249,7 @@ and create the test databases:
```bash
$ cd activerecord
-$ bundle exec rake mysql:build_databases
+$ bundle exec rake db:mysql:build
```
PostgreSQL's authentication works differently. A simple way to set up the development environment for example is to run with your development account
@@ -267,7 +267,7 @@ and then create the test databases with
```bash
$ cd activerecord
-$ bundle exec rake postgresql:build_databases
+$ bundle exec rake db:postgresql:build
```
It is possible to build databases for both PostgreSQL and MySQL with
diff --git a/guides/source/layout.html.erb b/guides/source/layout.html.erb
index 1d375f806c..1005057ca9 100644
--- a/guides/source/layout.html.erb
+++ b/guides/source/layout.html.erb
@@ -35,7 +35,6 @@
<li class="more-info"><a href="https://github.com/rails/rails">Code</a></li>
<li class="more-info"><a href="http://rubyonrails.org/screencasts">Screencasts</a></li>
<li class="more-info"><a href="http://rubyonrails.org/documentation">Documentation</a></li>
- <li class="more-info"><a href="http://rubyonrails.org/ecosystem">Ecosystem</a></li>
<li class="more-info"><a href="http://rubyonrails.org/community">Community</a></li>
<li class="more-info"><a href="http://weblog.rubyonrails.org/">Blog</a></li>
</ul>