diff options
Diffstat (limited to 'activerecord')
38 files changed, 491 insertions, 133 deletions
diff --git a/activerecord/CHANGELOG.md b/activerecord/CHANGELOG.md index ed5f29cfe4..aeb3773c99 100644 --- a/activerecord/CHANGELOG.md +++ b/activerecord/CHANGELOG.md @@ -1,5 +1,40 @@ ## Rails 4.0.0 (unreleased) ## +* `ActiveRelation#inspect` no longer calls `#to_a` + + *Brian Cardarella* + +* Add `collate` and `ctype` support to PostgreSQL. These are available for PostgreSQL 8.4 or later. + Example: + + development: + adapter: postgresql + host: localhost + database: rails_development + username: foo + password: bar + encoding: UTF8 + collate: ja_JP.UTF8 + ctype: ja_JP.UTF8 + + *kennyj* + +* `FinderMethods#exists?` now returns `false` with the `false` argument. + + *Egor Lynko* + +* Added support for specifying the precision of a timestamp in the postgresql + adapter. So, instead of having to incorrectly specify the precision using the + `:limit` option, you may use `:precision`, as intended. For example, in a migration: + + def change + create_table :foobars do |t| + t.timestamps :precision => 0 + end + end + + *Tony Schneider* + * Allow ActiveRecord::Relation#pluck to accept multiple columns. Returns an array of arrays containing the typecasted values: diff --git a/activerecord/lib/active_record/attribute_assignment.rb b/activerecord/lib/active_record/attribute_assignment.rb index ab6d253ef8..5b41f72e52 100644 --- a/activerecord/lib/active_record/attribute_assignment.rb +++ b/activerecord/lib/active_record/attribute_assignment.rb @@ -158,11 +158,12 @@ module ActiveRecord begin send(name + "=", read_value_from_parameter(name, values_with_empty_parameters)) rescue => ex - errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name}", ex, name) + errors << AttributeAssignmentError.new("error on assignment #{values_with_empty_parameters.values.inspect} to #{name} (#{ex.message})", ex, name) end end unless errors.empty? - raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes" + error_descriptions = errors.map { |ex| ex.message }.join(",") + raise MultiparameterAssignmentErrors.new(errors), "#{errors.size} error(s) on assignment of multiparameter attributes [#{error_descriptions}]" end end @@ -180,15 +181,27 @@ module ActiveRecord end def read_time_parameter_value(name, values_hash_from_param) - # If Date bits were not provided, error - raise "Missing Parameter" if [1,2,3].any?{|position| !values_hash_from_param.has_key?(position)} - max_position = extract_max_param_for_multiparameter_attributes(values_hash_from_param, 6) - # If Date bits were provided but blank, then return nil - return nil if (1..3).any? {|position| values_hash_from_param[position].blank?} + # If column is a :time (and not :date or :timestamp) there is no need to validate if + # there are year/month/day fields + if column_for_attribute(name).type == :time + # if the column is a time set the values to their defaults as January 1, 1970, but only if they're nil + {1 => 1970, 2 => 1, 3 => 1}.each do |key,value| + values_hash_from_param[key] ||= value + end + else + # else column is a timestamp, so if Date bits were not provided, error + if missing_parameter = [1,2,3].detect{ |position| !values_hash_from_param.has_key?(position) } + raise ArgumentError.new("Missing Parameter - #{name}(#{missing_parameter}i)") + end + + # If Date bits were provided but blank, then return nil + return nil if (1..3).any? { |position| values_hash_from_param[position].blank? } + end - set_values = (1..max_position).collect{|position| values_hash_from_param[position] } + max_position = extract_max_param_for_multiparameter_attributes(values_hash_from_param, 6) + set_values = (1..max_position).collect{ |position| values_hash_from_param[position] } # If Time bits are not there, then default to 0 - (3..5).each {|i| set_values[i] = set_values[i].blank? ? 0 : set_values[i]} + (3..5).each { |i| set_values[i] = set_values[i].blank? ? 0 : set_values[i] } instantiate_time_object(name, set_values) end diff --git a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb index 17377bad96..3b4537aab4 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb @@ -2,7 +2,7 @@ module ActiveRecord module ConnectionAdapters # :nodoc: module QueryCache class << self - def included(base) + def included(base) #:nodoc: dirties_query_cache base, :insert, :update, :delete end diff --git a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb index 921278d145..df4a9d5afc 100644 --- a/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/abstract_mysql_adapter.rb @@ -72,6 +72,8 @@ module ActiveRecord when /^mediumint/i; 3 when /^smallint/i; 2 when /^tinyint/i; 1 + when /^enum\((.+)\)/i + $1.split(',').map{|enum| enum.strip.length - 2}.max else super end diff --git a/activerecord/lib/active_record/connection_adapters/connection_specification.rb b/activerecord/lib/active_record/connection_adapters/connection_specification.rb index 8491d42b86..dd40351a38 100644 --- a/activerecord/lib/active_record/connection_adapters/connection_specification.rb +++ b/activerecord/lib/active_record/connection_adapters/connection_specification.rb @@ -1,3 +1,5 @@ +require 'uri' + module ActiveRecord module ConnectionAdapters class ConnectionSpecification #:nodoc: diff --git a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb index 43e243581c..507e937c3e 100644 --- a/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb @@ -187,6 +187,7 @@ module ActiveRecord case sql_type when /^bigint/i; 8 when /^smallint/i; 2 + when /^timestamp/i; nil else super end end @@ -201,6 +202,8 @@ module ActiveRecord def extract_precision(sql_type) if sql_type == 'money' self.class.money_precision + elsif sql_type =~ /timestamp/i + $1.to_i if sql_type =~ /\((\d+)\)/ else super end @@ -913,7 +916,8 @@ module ActiveRecord end # Create a new PostgreSQL database. Options include <tt>:owner</tt>, <tt>:template</tt>, - # <tt>:encoding</tt>, <tt>:tablespace</tt>, and <tt>:connection_limit</tt> (note that MySQL uses + # <tt>:encoding</tt>, <tt>:collate</tt>, <tt>:ctype</tt>, + # <tt>:tablespace</tt>, and <tt>:connection_limit</tt> (note that MySQL uses # <tt>:charset</tt> while PostgreSQL uses <tt>:encoding</tt>). # # Example: @@ -930,6 +934,10 @@ module ActiveRecord " TEMPLATE = \"#{value}\"" when :encoding " ENCODING = '#{value}'" + when :collate + " LC_COLLATE = '#{value}'" + when :ctype + " LC_CTYPE = '#{value}'" when :tablespace " TABLESPACE = \"#{value}\"" when :connection_limit @@ -1056,6 +1064,20 @@ module ActiveRecord end_sql end + # Returns the current database collate. + def collate + query(<<-end_sql, 'SCHEMA')[0][0] + SELECT pg_database.datcollate FROM pg_database WHERE pg_database.datname LIKE '#{current_database}' + end_sql + end + + # Returns the current database ctype. + def ctype + query(<<-end_sql, 'SCHEMA')[0][0] + SELECT pg_database.datctype FROM pg_database WHERE pg_database.datname LIKE '#{current_database}' + end_sql + end + # Returns an array of schema names. def schema_names query(<<-SQL, 'SCHEMA').flatten @@ -1285,6 +1307,13 @@ module ActiveRecord when 5..8; 'bigint' else raise(ActiveRecordError, "No integer type has byte size #{limit}. Use a numeric with precision 0 instead.") end + when 'datetime' + return super unless precision + + case precision + when 0..6; "timestamp(#{precision})" + else raise(ActiveRecordError, "No timestamp type has precision of #{precision}. The allowed range of precision is from 0 to 6") + end else super end diff --git a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb index a0c7e559ce..57aa47ab61 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite3_adapter.rb @@ -191,7 +191,7 @@ module ActiveRecord :decimal => { :name => "decimal" }, :datetime => { :name => "datetime" }, :timestamp => { :name => "datetime" }, - :time => { :name => "datetime" }, + :time => { :name => "time" }, :date => { :name => "date" }, :binary => { :name => "blob" }, :boolean => { :name => "boolean" } diff --git a/activerecord/lib/active_record/errors.rb b/activerecord/lib/active_record/errors.rb index 858b667e22..5f157fde6d 100644 --- a/activerecord/lib/active_record/errors.rb +++ b/activerecord/lib/active_record/errors.rb @@ -106,13 +106,11 @@ module ActiveRecord attr_reader :record, :attempted_action def initialize(record, attempted_action) + super("Attempted to #{attempted_action} a stale object: #{record.class.name}") @record = record @attempted_action = attempted_action end - def message - "Attempted to #{attempted_action} a stale object: #{record.class.name}" - end end # Raised when association is being configured improperly or @@ -168,9 +166,9 @@ module ActiveRecord class AttributeAssignmentError < ActiveRecordError attr_reader :exception, :attribute def initialize(message, exception, attribute) + super(message) @exception = exception @attribute = attribute - @message = message end end @@ -189,12 +187,10 @@ module ActiveRecord attr_reader :model def initialize(model) + super("Unknown primary key for table #{model.table_name} in model #{model}.") @model = model end - def message - "Unknown primary key for table #{model.table_name} in model #{model}." - end end class ImmutableRelation < ActiveRecordError diff --git a/activerecord/lib/active_record/railties/databases.rake b/activerecord/lib/active_record/railties/databases.rake index 8199b5c2e0..78ecb1cdc5 100644 --- a/activerecord/lib/active_record/railties/databases.rake +++ b/activerecord/lib/active_record/railties/databases.rake @@ -35,7 +35,7 @@ db_namespace = namespace :db do ActiveRecord::Tasks::DatabaseTasks.drop_current end - desc "Migrate the database (options: VERSION=x, VERBOSE=false)." + desc "Migrate the database (options: VERSION=x, VERBOSE=false, SCOPE=blog)." task :migrate => [:environment, :load_config] do ActiveRecord::Migration.verbose = ENV["VERBOSE"] ? ENV["VERBOSE"] == "true" : true ActiveRecord::Migrator.migrate(ActiveRecord::Migrator.migrations_paths, ENV["VERSION"] ? ENV["VERSION"].to_i : nil) do |migration| @@ -148,13 +148,10 @@ db_namespace = namespace :db do # desc "Retrieves the collation for the current environment's database" task :collation => [:environment, :load_config] do - config = ActiveRecord::Base.configurations[Rails.env || 'development'] - case config['adapter'] - when /mysql/ - ActiveRecord::Base.establish_connection(config) - puts ActiveRecord::Base.connection.collation - else - $stderr.puts 'sorry, your database adapter is not supported yet, feel free to submit a patch' + begin + puts ActiveRecord::Tasks::DatabaseTasks.collation_current + rescue NoMethodError + $stderr.puts 'Sorry, your database adapter is not supported yet, feel free to submit a patch' end end @@ -270,6 +267,15 @@ db_namespace = namespace :db do end namespace :structure do + def set_firebird_env(config) + ENV['ISC_USER'] = config['username'].to_s if config['username'] + ENV['ISC_PASSWORD'] = config['password'].to_s if config['password'] + end + + def firebird_db_string(config) + FireRuby::Database.db_string_for(config.symbolize_keys) + end + desc 'Dump the database structure to db/structure.sql. Specify another file with DB_STRUCTURE=db/my_structure.sql' task :dump => [:environment, :load_config] do abcs = ActiveRecord::Base.configurations @@ -304,7 +310,7 @@ db_namespace = namespace :db do filename = ENV['DB_STRUCTURE'] || File.join(Rails.root, "db", "structure.sql") case abcs[env]['adapter'] when /mysql/, /postgresql/, /sqlite/ - ActiveRecord::Tasks::DatabaseTasks.structure_load(abcs[Rails.env], filename) + ActiveRecord::Tasks::DatabaseTasks.structure_load(abcs[env], filename) when 'sqlserver' `sqlcmd -S #{abcs[env]['host']} -d #{abcs[env]['database']} -U #{abcs[env]['username']} -P #{abcs[env]['password']} -i #{filename}` when 'oci', 'oracle' @@ -338,6 +344,13 @@ db_namespace = namespace :db do end end + # desc "Recreate the test database from an existent schema.rb file" + task :load_schema => 'db:test:purge' do + ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) + ActiveRecord::Schema.verbose = false + db_namespace["schema:load"].invoke + end + # desc "Recreate the test database from an existent structure.sql file" task :load_structure => 'db:test:purge' do begin @@ -348,15 +361,18 @@ db_namespace = namespace :db do end end - # desc "Recreate the test database from an existent schema.rb file" - task :load_schema => 'db:test:purge' do - ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['test']) - ActiveRecord::Schema.verbose = false - db_namespace["schema:load"].invoke + # desc "Recreate the test database from a fresh schema" + task :clone do + case ActiveRecord::Base.schema_format + when :ruby + db_namespace["test:clone_schema"].invoke + when :sql + db_namespace["test:clone_structure"].invoke + end end # desc "Recreate the test database from a fresh schema.rb file" - task :clone => %w(db:schema:dump db:test:load_schema) + task :clone_schema => ["db:schema:dump", "db:test:load_schema"] # desc "Recreate the test database from a fresh structure.sql file" task :clone_structure => [ "db:structure:dump", "db:test:load_structure" ] @@ -389,7 +405,7 @@ db_namespace = namespace :db do # desc 'Check for pending migrations and load the test schema' task :prepare => 'db:abort_if_pending_migrations' do unless ActiveRecord::Base.configurations.blank? - db_namespace[{ :sql => 'test:clone_structure', :ruby => 'test:load' }[ActiveRecord::Base.schema_format]].invoke + db_namespace['test:load'].invoke end end end @@ -405,7 +421,7 @@ db_namespace = namespace :db do # desc "Clear the sessions table" task :clear => [:environment, :load_config] do - ActiveRecord::Base.connection.execute "DELETE FROM #{session_table_name}" + ActiveRecord::Base.connection.execute "DELETE FROM #{ActiveRecord::SessionStore::Session.table_name}" end end end @@ -416,7 +432,7 @@ namespace :railties do task :migrations => :'db:load_config' do to_load = ENV['FROM'].blank? ? :all : ENV['FROM'].split(",").map {|n| n.strip } railties = {} - Rails.application.railties.all do |railtie| + Rails.application.railties.each do |railtie| next unless to_load == :all || to_load.include?(railtie.railtie_name) if railtie.respond_to?(:paths) && (path = railtie.paths['db/migrate'].first) @@ -440,15 +456,3 @@ end task 'test:prepare' => 'db:test:prepare' -def session_table_name - ActiveRecord::SessionStore::Session.table_name -end - -def set_firebird_env(config) - ENV['ISC_USER'] = config['username'].to_s if config['username'] - ENV['ISC_PASSWORD'] = config['password'].to_s if config['password'] -end - -def firebird_db_string(config) - FireRuby::Database.db_string_for(config.symbolize_keys) -end diff --git a/activerecord/lib/active_record/relation.rb b/activerecord/lib/active_record/relation.rb index fe3aa00a74..e268d451e0 100644 --- a/activerecord/lib/active_record/relation.rb +++ b/activerecord/lib/active_record/relation.rb @@ -492,10 +492,6 @@ module ActiveRecord end end - def inspect - to_a.inspect - end - def pretty_print(q) q.pp(self.to_a) end diff --git a/activerecord/lib/active_record/relation/calculations.rb b/activerecord/lib/active_record/relation/calculations.rb index 86eb8f35b5..e40b958b54 100644 --- a/activerecord/lib/active_record/relation/calculations.rb +++ b/activerecord/lib/active_record/relation/calculations.rb @@ -262,10 +262,16 @@ module ActiveRecord end def execute_grouped_calculation(operation, column_name, distinct) #:nodoc: - group_attr = group_values - association = @klass.reflect_on_association(group_attr.first.to_sym) - associated = group_attr.size == 1 && association && association.macro == :belongs_to # only count belongs_to associations - group_fields = Array(associated ? association.foreign_key : group_attr) + group_attrs = group_values + + if group_attrs.first.respond_to?(:to_sym) + association = @klass.reflect_on_association(group_attrs.first.to_sym) + associated = group_attrs.size == 1 && association && association.macro == :belongs_to # only count belongs_to associations + group_fields = Array(associated ? association.foreign_key : group_attrs) + else + group_fields = group_attrs + end + group_aliases = group_fields.map { |field| column_alias_for(field) } group_columns = group_aliases.zip(group_fields).map { |aliaz,field| [aliaz, column_for(field)] @@ -288,10 +294,14 @@ module ActiveRecord select_values += select_values unless having_values.empty? select_values.concat group_fields.zip(group_aliases).map { |field,aliaz| - "#{field} AS #{aliaz}" + if field.respond_to?(:as) + field.as(aliaz) + else + "#{field} AS #{aliaz}" + end } - relation = except(:group).group(group.join(',')) + relation = except(:group).group(group) relation.select_values = select_values calculated_data = @klass.connection.select_all(relation, nil, bind_values) @@ -303,10 +313,10 @@ module ActiveRecord end Hash[calculated_data.map do |row| - key = group_columns.map { |aliaz, column| + key = group_columns.map { |aliaz, column| type_cast_calculated_value(row[aliaz], column) } - key = key.first if key.size == 1 + key = key.first if key.size == 1 key = key_records[key] if associated [key, type_cast_calculated_value(row[aggregate_alias], column_for(column_name), operation)] end] @@ -321,6 +331,7 @@ module ActiveRecord # column_alias_for("count(*)") # => "count_all" # column_alias_for("count", "id") # => "count_id" def column_alias_for(*keys) + keys.map! {|k| k.respond_to?(:to_sql) ? k.to_sql : k} table_name = keys.join(' ') table_name.downcase! table_name.gsub!(/\*/, 'all') @@ -332,7 +343,7 @@ module ActiveRecord end def column_for(field) - field_name = field.to_s.split('.').last + field_name = field.respond_to?(:name) ? field.name.to_s : field.to_s.split('.').last @klass.columns.detect { |c| c.name.to_s == field_name } end diff --git a/activerecord/lib/active_record/relation/finder_methods.rb b/activerecord/lib/active_record/relation/finder_methods.rb index eb901727de..974cd326ef 100644 --- a/activerecord/lib/active_record/relation/finder_methods.rb +++ b/activerecord/lib/active_record/relation/finder_methods.rb @@ -172,19 +172,19 @@ module ActiveRecord # Person.exists?(name: 'David') # Person.exists?(false) # Person.exists? - def exists?(id = false) - id = id.id if ActiveRecord::Model === id - return false if id.nil? + def exists?(conditions = :none) + conditions = conditions.id if ActiveRecord::Model === conditions + return false if !conditions join_dependency = construct_join_dependency_for_association_find relation = construct_relation_for_association_find(join_dependency) relation = relation.except(:select, :order).select("1 AS one").limit(1) - case id + case conditions when Array, Hash - relation = relation.where(id) + relation = relation.where(conditions) else - relation = relation.where(table[primary_key].eq(id)) if id + relation = relation.where(table[primary_key].eq(conditions)) if conditions != :none end connection.select_value(relation, "#{name} Exists", relation.bind_values) diff --git a/activerecord/lib/active_record/relation/query_methods.rb b/activerecord/lib/active_record/relation/query_methods.rb index 5e5aca0396..6f49548aab 100644 --- a/activerecord/lib/active_record/relation/query_methods.rb +++ b/activerecord/lib/active_record/relation/query_methods.rb @@ -83,7 +83,9 @@ module ActiveRecord end def references!(*args) - self.references_values = (references_values + args.flatten.map(&:to_s)).uniq + args.flatten! + + self.references_values = (references_values + args.map!(&:to_s)).uniq self end @@ -134,7 +136,9 @@ module ActiveRecord end def group!(*args) - self.group_values += args.flatten + args.flatten! + + self.group_values += args self end @@ -143,11 +147,10 @@ module ActiveRecord end def order!(*args) - args = args.flatten + args.flatten! references = args.reject { |arg| Arel::Node === arg } - .map { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 } - .compact + references.map! { |arg| arg =~ /^([a-zA-Z]\w*)\.(\w+)/ && $1 }.compact! references!(references) if references.any? self.order_values += args @@ -168,8 +171,10 @@ module ActiveRecord end def reorder!(*args) + args.flatten! + self.reordering_value = true - self.order_values = args.flatten + self.order_values = args self end @@ -327,7 +332,7 @@ module ActiveRecord # # Should be used with order. # - # User.offset(10).order("name ASC") + # User.offset(10).order("name ASC") def offset(value) spawn.offset!(value) end @@ -410,10 +415,10 @@ module ActiveRecord # # Can accept other relation objects. For example: # - # Topic.select('title').from(Topics.approved) + # Topic.select('title').from(Topic.approved) # # => SELECT title FROM (SELECT * FROM topics WHERE approved = 't') subquery # - # Topics.select('a.title').from(Topics.approved, :a) + # Topic.select('a.title').from(Topic.approved, :a) # # => SELECT a.title FROM (SELECT * FROM topics WHERE approved = 't') a # def from(value, subquery_name = nil) diff --git a/activerecord/lib/active_record/tasks/database_tasks.rb b/activerecord/lib/active_record/tasks/database_tasks.rb index 999b2ebc85..f1241502f5 100644 --- a/activerecord/lib/active_record/tasks/database_tasks.rb +++ b/activerecord/lib/active_record/tasks/database_tasks.rb @@ -56,6 +56,15 @@ module ActiveRecord class_for_adapter(configuration['adapter']).new(*arguments).charset end + def collation_current(environment = Rails.env) + collation ActiveRecord::Base.configurations[environment] + end + + def collation(*arguments) + configuration = arguments.first + class_for_adapter(configuration['adapter']).new(*arguments).collation + end + def purge(configuration) class_for_adapter(configuration['adapter']).new(configuration).purge end diff --git a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb index b39cd2282f..bf62dfd5b5 100644 --- a/activerecord/lib/active_record/tasks/mysql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/mysql_database_tasks.rb @@ -44,6 +44,10 @@ module ActiveRecord connection.charset end + def collation + connection.collation + end + def structure_dump(filename) establish_connection configuration File.open(filename, "w:utf-8") { |f| f << ActiveRecord::Base.connection.structure_dump } diff --git a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb index a210392e53..4139460273 100644 --- a/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb +++ b/activerecord/lib/active_record/tasks/postgresql_database_tasks.rb @@ -29,6 +29,10 @@ module ActiveRecord connection.encoding end + def collation + connection.collate + end + def purge clear_active_connections! drop diff --git a/activerecord/lib/rails/generators/active_record/model/templates/model.rb b/activerecord/lib/rails/generators/active_record/model/templates/model.rb index d56f9f57a4..2cca17b94f 100644 --- a/activerecord/lib/rails/generators/active_record/model/templates/model.rb +++ b/activerecord/lib/rails/generators/active_record/model/templates/model.rb @@ -1,7 +1,7 @@ <% module_namespacing do -%> class <%= class_name %> < <%= parent_class_name.classify %> <% attributes.select {|attr| attr.reference? }.each do |attribute| -%> - belongs_to :<%= attribute.name %> + belongs_to :<%= attribute.name %><%= ', polymorphic: true' if attribute.polymorphic? %> <% end -%> <% if !accessible_attributes.empty? -%> attr_accessible <%= accessible_attributes.map {|a| ":#{a.name}" }.sort.join(', ') %> diff --git a/activerecord/test/cases/adapters/mysql/enum_test.rb b/activerecord/test/cases/adapters/mysql/enum_test.rb new file mode 100644 index 0000000000..40af317ad1 --- /dev/null +++ b/activerecord/test/cases/adapters/mysql/enum_test.rb @@ -0,0 +1,10 @@ +require "cases/helper" + +class MysqlEnumTest < ActiveRecord::TestCase + class EnumTest < ActiveRecord::Base + end + + def test_enum_limit + assert_equal 5, EnumTest.columns.first.limit + end +end diff --git a/activerecord/test/cases/adapters/mysql2/enum_test.rb b/activerecord/test/cases/adapters/mysql2/enum_test.rb new file mode 100644 index 0000000000..f3a05e48ad --- /dev/null +++ b/activerecord/test/cases/adapters/mysql2/enum_test.rb @@ -0,0 +1,10 @@ +require "cases/helper" + +class Mysql2EnumTest < ActiveRecord::TestCase + class EnumTest < ActiveRecord::Base + end + + def test_enum_limit + assert_equal 5, EnumTest.columns.first.limit + end +end diff --git a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb index 447d729e52..148584214e 100644 --- a/activerecord/test/cases/adapters/postgresql/active_schema_test.rb +++ b/activerecord/test/cases/adapters/postgresql/active_schema_test.rb @@ -21,6 +21,10 @@ class PostgresqlActiveSchemaTest < ActiveRecord::TestCase assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'latin1'), create_database(:aimonetti, :encoding => :latin1) end + def test_create_database_with_collate_and_ctype + assert_equal %(CREATE DATABASE "aimonetti" ENCODING = 'UTF8' LC_COLLATE = 'ja_JP.UTF8' LC_CTYPE = 'ja_JP.UTF8'), create_database(:aimonetti, :encoding => :"UTF8", :collate => :"ja_JP.UTF8", :ctype => :"ja_JP.UTF8") + end + def test_add_index # add_index calls index_name_exists? which can't work since execute is stubbed ActiveRecord::ConnectionAdapters::PostgreSQLAdapter.send(:define_method, :index_name_exists?) do |*| diff --git a/activerecord/test/cases/adapters/postgresql/connection_test.rb b/activerecord/test/cases/adapters/postgresql/connection_test.rb index f6e168caf2..9b5c5eb72f 100644 --- a/activerecord/test/cases/adapters/postgresql/connection_test.rb +++ b/activerecord/test/cases/adapters/postgresql/connection_test.rb @@ -21,6 +21,14 @@ module ActiveRecord assert_not_nil @connection.encoding end + def test_collate + assert_not_nil @connection.collate + end + + def test_ctype + assert_not_nil @connection.ctype + end + def test_default_client_min_messages assert_equal "warning", @connection.client_min_messages end diff --git a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb index 337f43c421..26507ad654 100644 --- a/activerecord/test/cases/adapters/postgresql/timestamp_test.rb +++ b/activerecord/test/cases/adapters/postgresql/timestamp_test.rb @@ -27,4 +27,69 @@ class TimestampTest < ActiveRecord::TestCase d = Developer.create!(:name => 'aaron', :updated_at => -1.0 / 0.0) assert_equal(-1.0 / 0.0, d.updated_at) end + + def test_default_datetime_precision + ActiveRecord::Base.connection.create_table(:foos) + ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime + ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime + assert_nil activerecord_column_option('foos', 'created_at', 'precision') + end + + def test_timestamp_data_type_with_precision + ActiveRecord::Base.connection.create_table(:foos) + ActiveRecord::Base.connection.add_column :foos, :created_at, :datetime, :precision => 0 + ActiveRecord::Base.connection.add_column :foos, :updated_at, :datetime, :precision => 5 + assert_equal 0, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 5, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_timestamps_helper_with_custom_precision + ActiveRecord::Base.connection.create_table(:foos) do |t| + t.timestamps :precision => 4 + end + assert_equal 4, activerecord_column_option('foos', 'created_at', 'precision') + assert_equal 4, activerecord_column_option('foos', 'updated_at', 'precision') + end + + def test_passing_precision_to_timestamp_does_not_set_limit + ActiveRecord::Base.connection.create_table(:foos) do |t| + t.timestamps :precision => 4 + end + assert_nil activerecord_column_option("foos", "created_at", "limit") + assert_nil activerecord_column_option("foos", "updated_at", "limit") + end + + def test_invalid_timestamp_precision_raises_error + assert_raises ActiveRecord::ActiveRecordError do + ActiveRecord::Base.connection.create_table(:foos) do |t| + t.timestamps :precision => 7 + end + end + end + + def test_postgres_agrees_with_activerecord_about_precision + ActiveRecord::Base.connection.create_table(:foos) do |t| + t.timestamps :precision => 4 + end + assert_equal '4', pg_datetime_precision('foos', 'created_at') + assert_equal '4', pg_datetime_precision('foos', 'updated_at') + end + + private + + def pg_datetime_precision(table_name, column_name) + results = ActiveRecord::Base.connection.execute("SELECT column_name, datetime_precision FROM information_schema.columns WHERE table_name ='#{table_name}'") + result = results.find do |result_hash| + result_hash["column_name"] == column_name + end + result && result["datetime_precision"] + end + + def activerecord_column_option(tablename, column_name, option) + result = ActiveRecord::Base.connection.columns(tablename).find do |column| + column.name == column_name + end + result && result.send(option) + end + end diff --git a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb index 5e947799cc..4e26c5dda1 100644 --- a/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb +++ b/activerecord/test/cases/adapters/sqlite3/sqlite3_adapter_test.rb @@ -24,7 +24,7 @@ module ActiveRecord @conn.extend(LogIntercepter) @conn.intercepted = true end - + def teardown @conn.intercepted = false @conn.logged = [] @@ -43,11 +43,6 @@ module ActiveRecord assert(!result.rows.first.include?("blob"), "should not store blobs") end - def test_time_column - owner = Owner.create!(:eats_at => Time.utc(1995,1,1,6,0)) - assert_match(/1995-01-01/, owner.reload.eats_at.to_s) - end - def test_exec_insert column = @conn.columns('items').find { |col| col.name == 'number' } vals = [[column, 10]] diff --git a/activerecord/test/cases/associations/has_many_associations_test.rb b/activerecord/test/cases/associations/has_many_associations_test.rb index b8481175b2..3ea6201d60 100644 --- a/activerecord/test/cases/associations/has_many_associations_test.rb +++ b/activerecord/test/cases/associations/has_many_associations_test.rb @@ -193,7 +193,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase def test_no_sql_should_be_fired_if_association_already_loaded Car.create(:name => 'honda') bulbs = Car.first.bulbs - bulbs.inspect # to load all instances of bulbs + bulbs.to_a # to load all instances of bulbs assert_no_queries do bulbs.first() diff --git a/activerecord/test/cases/attribute_methods_test.rb b/activerecord/test/cases/attribute_methods_test.rb index 1093fedea1..fe385feb4a 100644 --- a/activerecord/test/cases/attribute_methods_test.rb +++ b/activerecord/test/cases/attribute_methods_test.rb @@ -792,6 +792,7 @@ class AttributeMethodsTest < ActiveRecord::TestCase end private + def cached_columns Topic.columns.find_all { |column| !Topic.serialized_attributes.include? column.name diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index 2fee553cef..e34f505a02 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -81,6 +81,12 @@ end class BasicsTest < ActiveRecord::TestCase fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, 'warehouse-things', :authors, :categorizations, :categories, :posts + def setup + ActiveRecord::Base.time_zone_aware_attributes = false + ActiveRecord::Base.default_timezone = :local + Time.zone = nil + end + def test_generated_methods_modules modules = Computer.ancestors assert modules.include?(Computer::GeneratedFeatureMethods) @@ -504,7 +510,7 @@ class BasicsTest < ActiveRecord::TestCase end # Oracle, and Sybase do not have a TIME datatype. - unless current_adapter?(:OracleAdapter, :SybaseAdapter, :SQLite3Adapter) + unless current_adapter?(:OracleAdapter, :SybaseAdapter) def test_utc_as_time_zone Topic.default_timezone = :utc attributes = { "bonus_time" => "5:42:00AM" } @@ -686,7 +692,7 @@ class BasicsTest < ActiveRecord::TestCase } topic = Topic.find(1) topic.attributes = attributes - assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on + assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on end def test_multiparameter_attributes_on_time_with_no_date @@ -746,9 +752,6 @@ class BasicsTest < ActiveRecord::TestCase end def test_multiparameter_attributes_on_time_will_ignore_hour_if_missing - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - Time.zone = nil attributes = { "written_on(1i)" => "2004", "written_on(2i)" => "12", "written_on(3i)" => "12", "written_on(5i)" => "12", "written_on(6i)" => "02" @@ -796,8 +799,6 @@ class BasicsTest < ActiveRecord::TestCase topic = Topic.find(1) topic.attributes = attributes assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on - ensure - ActiveRecord::Base.default_timezone = :local end def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes @@ -813,14 +814,9 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Time.utc(2004, 6, 24, 23, 24, 0), topic.written_on assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on.time assert_equal Time.zone, topic.written_on.time_zone - ensure - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - Time.zone = nil end def test_multiparameter_attributes_on_time_with_time_zone_aware_attributes_false - ActiveRecord::Base.time_zone_aware_attributes = false Time.zone = ActiveSupport::TimeZone[-28800] attributes = { "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", @@ -830,8 +826,6 @@ class BasicsTest < ActiveRecord::TestCase topic.attributes = attributes assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on assert_equal false, topic.written_on.respond_to?(:time_zone) - ensure - Time.zone = nil end def test_multiparameter_attributes_on_time_with_skip_time_zone_conversion_for_attributes @@ -848,14 +842,11 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Time.utc(2004, 6, 24, 16, 24, 0), topic.written_on assert_equal false, topic.written_on.respond_to?(:time_zone) ensure - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - Time.zone = nil Topic.skip_time_zone_conversion_for_attributes = [] end # Oracle, and Sybase do not have a TIME datatype. - unless current_adapter?(:OracleAdapter, :SybaseAdapter, :SQLite3Adapter) + unless current_adapter?(:OracleAdapter, :SybaseAdapter) def test_multiparameter_attributes_on_time_only_column_with_time_zone_aware_attributes_does_not_do_time_zone_conversion ActiveRecord::Base.time_zone_aware_attributes = true ActiveRecord::Base.default_timezone = :utc @@ -868,17 +859,10 @@ class BasicsTest < ActiveRecord::TestCase topic.attributes = attributes assert_equal Time.utc(2000, 1, 1, 16, 24, 0), topic.bonus_time assert topic.bonus_time.utc? - ensure - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - Time.zone = nil end end def test_multiparameter_attributes_on_time_with_empty_seconds - ActiveRecord::Base.time_zone_aware_attributes = false - ActiveRecord::Base.default_timezone = :local - Time.zone = nil attributes = { "written_on(1i)" => "2004", "written_on(2i)" => "6", "written_on(3i)" => "24", "written_on(4i)" => "16", "written_on(5i)" => "24", "written_on(6i)" => "" @@ -888,36 +872,51 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Time.local(2004, 6, 24, 16, 24, 0), topic.written_on end - def test_multiparameter_assignment_of_aggregation_with_missing_values - ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do - customer = Customer.new - address = Address.new("The Street", "The City", "The Country") - attributes = { "address(2)" => address.city, "address(3)" => address.country } - customer.attributes = attributes - end - assert_equal("address", ex.errors[0].attribute) + def test_multiparameter_attributes_setting_time_attribute + return skip "Oracle does not have TIME data type" if current_adapter? :OracleAdapter + + topic = Topic.new( "bonus_time(4i)"=> "01", "bonus_time(5i)" => "05" ) + assert_equal 1, topic.bonus_time.hour + assert_equal 5, topic.bonus_time.min end - def test_multiparameter_assignment_of_aggregation_with_large_index - ex = assert_raise(ActiveRecord::MultiparameterAssignmentErrors) do - customer = Customer.new - address = Address.new("The Street", "The City", "The Country") - attributes = { "address(1)" => "The Street", "address(2)" => address.city, "address(3000)" => address.country } - customer.attributes = attributes + def test_multiparameter_attributes_setting_date_attribute + topic = Topic.new( "written_on(1i)" => "1952", "written_on(2i)" => "3", "written_on(3i)" => "11" ) + assert_equal 1952, topic.written_on.year + assert_equal 3, topic.written_on.month + assert_equal 11, topic.written_on.day + end + + def test_multiparameter_attributes_setting_date_and_time_attribute + topic = Topic.new( + "written_on(1i)" => "1952", + "written_on(2i)" => "3", + "written_on(3i)" => "11", + "written_on(4i)" => "13", + "written_on(5i)" => "55") + assert_equal 1952, topic.written_on.year + assert_equal 3, topic.written_on.month + assert_equal 11, topic.written_on.day + assert_equal 13, topic.written_on.hour + assert_equal 55, topic.written_on.min + end + + def test_multiparameter_attributes_setting_time_but_not_date_on_date_field + assert_raise( ActiveRecord::MultiparameterAssignmentErrors ) do + Topic.new( "written_on(4i)" => "13", "written_on(5i)" => "55" ) end - assert_equal("address", ex.errors[0].attribute) end def test_attributes_on_dummy_time # Oracle, and Sybase do not have a TIME datatype. - return true if current_adapter?(:OracleAdapter, :SybaseAdapter, :SQLite3Adapter) + return true if current_adapter?(:OracleAdapter, :SybaseAdapter) attributes = { "bonus_time" => "5:42:00AM" } topic = Topic.find(1) topic.attributes = attributes - assert_equal Time.utc(2000, 1, 1, 5, 42, 0), topic.bonus_time + assert_equal Time.local(2000, 1, 1, 5, 42, 0), topic.bonus_time end def test_boolean @@ -1882,8 +1881,6 @@ class BasicsTest < ActiveRecord::TestCase est_key = Developer.first.cache_key assert_equal utc_key, est_key - ensure - ActiveRecord::Base.time_zone_aware_attributes = false end def test_cache_key_format_for_existing_record_with_updated_at diff --git a/activerecord/test/cases/calculations_test.rb b/activerecord/test/cases/calculations_test.rb index 4df613488a..e1c1e449ef 100644 --- a/activerecord/test/cases/calculations_test.rb +++ b/activerecord/test/cases/calculations_test.rb @@ -58,7 +58,16 @@ class CalculationsTest < ActiveRecord::TestCase def test_should_group_by_field c = Account.group(:firm_id).sum(:credit_limit) - [1,6,2].each { |firm_id| assert c.keys.include?(firm_id) } + [1,6,2].each do |firm_id| + assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}" + end + end + + def test_should_group_by_arel_attribute + c = Account.group(Account.arel_table[:firm_id]).sum(:credit_limit) + [1,6,2].each do |firm_id| + assert c.keys.include?(firm_id), "Group #{c.inspect} does not contain firm_id #{firm_id}" + end end def test_should_group_by_multiple_fields diff --git a/activerecord/test/cases/finder_test.rb b/activerecord/test/cases/finder_test.rb index e62d984ebd..576a455f09 100644 --- a/activerecord/test/cases/finder_test.rb +++ b/activerecord/test/cases/finder_test.rb @@ -55,6 +55,10 @@ class FinderTest < ActiveRecord::TestCase assert Topic.exists? end + def test_exists_returns_false_with_false_arg + assert !Topic.exists?(false) + end + # exists? should handle nil for id's that come from URLs and always return false # (example: Topic.exists?(params[:id])) where params[:id] is nil def test_exists_with_nil_arg diff --git a/activerecord/test/cases/inclusion_test.rb b/activerecord/test/cases/inclusion_test.rb index 8726ba5e51..9b9c09d2d8 100644 --- a/activerecord/test/cases/inclusion_test.rb +++ b/activerecord/test/cases/inclusion_test.rb @@ -4,7 +4,7 @@ require 'models/teapot' class BasicInclusionModelTest < ActiveRecord::TestCase def test_basic_model Teapot.create!(:name => "Ronnie Kemper") - assert_equal "Ronnie Kemper", Teapot.find(1).name + assert_equal "Ronnie Kemper", Teapot.first.name end def test_initialization diff --git a/activerecord/test/cases/reflection_test.rb b/activerecord/test/cases/reflection_test.rb index bac3376c9f..6631dce08f 100644 --- a/activerecord/test/cases/reflection_test.rb +++ b/activerecord/test/cases/reflection_test.rb @@ -305,6 +305,58 @@ class ReflectionTest < ActiveRecord::TestCase assert_equal Client, Firm.reflect_on_association(:unsorted_clients_with_symbol).klass end + def test_join_table + category = Struct.new(:table_name, :pluralize_table_names).new('categories', true) + product = Struct.new(:table_name, :pluralize_table_names).new('products', true) + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, {}, product) + reflection.stubs(:klass).returns(category) + assert_equal 'categories_products', reflection.join_table + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, {}, category) + reflection.stubs(:klass).returns(product) + assert_equal 'categories_products', reflection.join_table + end + + def test_join_table_with_common_prefix + category = Struct.new(:table_name, :pluralize_table_names).new('catalog_categories', true) + product = Struct.new(:table_name, :pluralize_table_names).new('catalog_products', true) + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, {}, product) + reflection.stubs(:klass).returns(category) + assert_equal 'catalog_categories_products', reflection.join_table + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, {}, category) + reflection.stubs(:klass).returns(product) + assert_equal 'catalog_categories_products', reflection.join_table + end + + def test_join_table_with_different_prefix + category = Struct.new(:table_name, :pluralize_table_names).new('catalog_categories', true) + page = Struct.new(:table_name, :pluralize_table_names).new('content_pages', true) + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, {}, page) + reflection.stubs(:klass).returns(category) + assert_equal 'catalog_categories_content_pages', reflection.join_table + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :pages, {}, category) + reflection.stubs(:klass).returns(page) + assert_equal 'catalog_categories_content_pages', reflection.join_table + end + + def test_join_table_can_be_overridden + category = Struct.new(:table_name, :pluralize_table_names).new('categories', true) + product = Struct.new(:table_name, :pluralize_table_names).new('products', true) + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :categories, { :join_table => 'product_categories' }, product) + reflection.stubs(:klass).returns(category) + assert_equal 'product_categories', reflection.join_table + + reflection = AssociationReflection.new(:has_and_belongs_to_many, :products, { :join_table => 'product_categories' }, category) + reflection.stubs(:klass).returns(product) + assert_equal 'product_categories', reflection.join_table + end + private def assert_reflection(klass, association, options) assert reflection = klass.reflect_on_association(association) diff --git a/activerecord/test/cases/database_tasks_test.rb b/activerecord/test/cases/tasks/database_tasks_test.rb index 5f36b2c841..8c96a8aaa1 100644 --- a/activerecord/test/cases/database_tasks_test.rb +++ b/activerecord/test/cases/tasks/database_tasks_test.rb @@ -251,6 +251,17 @@ module ActiveRecord end end + class DatabaseTasksCollationTest < ActiveRecord::TestCase + include DatabaseTasksSetupper + + ADAPTERS_TASKS.each do |k, v| + define_method("test_#{k}_collation") do + eval("@#{v}").expects(:collation) + ActiveRecord::Tasks::DatabaseTasks.collation 'adapter' => k + end + end + end + class DatabaseTasksStructureDumpTest < ActiveRecord::TestCase include DatabaseTasksSetupper diff --git a/activerecord/test/cases/mysql_rake_test.rb b/activerecord/test/cases/tasks/mysql_rake_test.rb index 42a11b0171..9a0eb423bd 100644 --- a/activerecord/test/cases/mysql_rake_test.rb +++ b/activerecord/test/cases/tasks/mysql_rake_test.rb @@ -195,6 +195,24 @@ module ActiveRecord end end + class MysqlDBCollationTest < ActiveRecord::TestCase + def setup + @connection = stub(:create_database => true) + @configuration = { + 'adapter' => 'mysql', + 'database' => 'my-app-db' + } + + ActiveRecord::Base.stubs(:connection).returns(@connection) + ActiveRecord::Base.stubs(:establish_connection).returns(true) + end + + def test_db_retrieves_collation + @connection.expects(:collation) + ActiveRecord::Tasks::DatabaseTasks.collation @configuration + end + end + class MySQLStructureDumpTest < ActiveRecord::TestCase def setup @connection = stub(:structure_dump => true) diff --git a/activerecord/test/cases/postgresql_rake_test.rb b/activerecord/test/cases/tasks/postgresql_rake_test.rb index e8769bd4df..df1075d816 100644 --- a/activerecord/test/cases/postgresql_rake_test.rb +++ b/activerecord/test/cases/tasks/postgresql_rake_test.rb @@ -38,6 +38,14 @@ module ActiveRecord merge('encoding' => 'latin') end + def test_creates_database_with_given_collate_and_ctype + @connection.expects(:create_database). + with('my-app-db', @configuration.merge('encoding' => 'utf8', 'collate' => 'ja_JP.UTF8', 'ctype' => 'ja_JP.UTF8')) + + ActiveRecord::Tasks::DatabaseTasks.create @configuration. + merge('collate' => 'ja_JP.UTF8', 'ctype' => 'ja_JP.UTF8') + end + def test_establishes_connection_to_new_database ActiveRecord::Base.expects(:establish_connection).with(@configuration) @@ -151,6 +159,24 @@ module ActiveRecord end end + class PostgreSQLDBCollationTest < ActiveRecord::TestCase + def setup + @connection = stub(:create_database => true) + @configuration = { + 'adapter' => 'postgresql', + 'database' => 'my-app-db' + } + + ActiveRecord::Base.stubs(:connection).returns(@connection) + ActiveRecord::Base.stubs(:establish_connection).returns(true) + end + + def test_db_retrieves_collation + @connection.expects(:collate) + ActiveRecord::Tasks::DatabaseTasks.collation @configuration + end + end + class PostgreSQLStructureDumpTest < ActiveRecord::TestCase def setup @connection = stub(:structure_dump => true) diff --git a/activerecord/test/cases/sqlite_rake_test.rb b/activerecord/test/cases/tasks/sqlite_rake_test.rb index b5557fc953..06a1d0ffc2 100644 --- a/activerecord/test/cases/sqlite_rake_test.rb +++ b/activerecord/test/cases/tasks/sqlite_rake_test.rb @@ -124,6 +124,27 @@ module ActiveRecord end end + class SqliteDBCollationTest < ActiveRecord::TestCase + def setup + @database = 'db_create.sqlite3' + @connection = stub :connection + @configuration = { + 'adapter' => 'sqlite3', + 'database' => @database + } + + File.stubs(:exist?).returns(false) + ActiveRecord::Base.stubs(:connection).returns(@connection) + ActiveRecord::Base.stubs(:establish_connection).returns(true) + end + + def test_db_retrieves_collation + assert_raise NoMethodError do + ActiveRecord::Tasks::DatabaseTasks.collation @configuration, '/rails/root' + end + end + end + class SqliteStructureDumpTest < ActiveRecord::TestCase def setup @database = "db_create.sqlite3" diff --git a/activerecord/test/models/developer.rb b/activerecord/test/models/developer.rb index 9fefa9ad3a..43cde4ab73 100644 --- a/activerecord/test/models/developer.rb +++ b/activerecord/test/models/developer.rb @@ -64,7 +64,6 @@ class AuditLog < ActiveRecord::Base belongs_to :unvalidated_developer, :class_name => 'Developer' end -DeveloperSalary = Struct.new(:amount) 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/activerecord/test/schema/mysql2_specific_schema.rb b/activerecord/test/schema/mysql2_specific_schema.rb index 65b6f9f227..24a43d7ece 100644 --- a/activerecord/test/schema/mysql2_specific_schema.rb +++ b/activerecord/test/schema/mysql2_specific_schema.rb @@ -32,4 +32,13 @@ CREATE TABLE collation_tests ( ) CHARACTER SET utf8 COLLATE utf8_general_ci SQL + ActiveRecord::Base.connection.execute <<-SQL +DROP TABLE IF EXISTS enum_tests; +SQL + + ActiveRecord::Base.connection.execute <<-SQL +CREATE TABLE enum_tests ( + enum_column ENUM('true','false') +) +SQL end diff --git a/activerecord/test/schema/mysql_specific_schema.rb b/activerecord/test/schema/mysql_specific_schema.rb index 7d324f98c4..802c08b819 100644 --- a/activerecord/test/schema/mysql_specific_schema.rb +++ b/activerecord/test/schema/mysql_specific_schema.rb @@ -43,4 +43,14 @@ CREATE TABLE collation_tests ( ) CHARACTER SET utf8 COLLATE utf8_general_ci SQL + ActiveRecord::Base.connection.execute <<-SQL +DROP TABLE IF EXISTS enum_tests; +SQL + + ActiveRecord::Base.connection.execute <<-SQL +CREATE TABLE enum_tests ( + enum_column ENUM('true','false') +) +SQL + end diff --git a/activerecord/test/schema/schema.rb b/activerecord/test/schema/schema.rb index ba01ef35f0..00688eab37 100644 --- a/activerecord/test/schema/schema.rb +++ b/activerecord/test/schema/schema.rb @@ -437,7 +437,6 @@ ActiveRecord::Schema.define do t.string :name t.column :updated_at, :datetime t.column :happy_at, :datetime - t.column :eats_at, :time t.string :essay_id end |