diff options
Diffstat (limited to 'activerecord')
-rw-r--r-- | activerecord/CHANGELOG | 4 | ||||
-rw-r--r-- | activerecord/Rakefile | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/associations/association_collection.rb | 14 | ||||
-rwxr-xr-x | activerecord/lib/active_record/base.rb | 4 | ||||
-rw-r--r-- | activerecord/lib/active_record/batches.rb | 38 | ||||
-rw-r--r-- | activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb | 55 | ||||
-rw-r--r-- | activerecord/lib/active_record/validations.rb | 2 | ||||
-rw-r--r-- | activerecord/lib/active_record/version.rb | 2 | ||||
-rw-r--r-- | activerecord/test/cases/migration_test.rb | 26 | ||||
-rw-r--r-- | activerecord/test/cases/transactions_test.rb | 15 |
10 files changed, 106 insertions, 56 deletions
diff --git a/activerecord/CHANGELOG b/activerecord/CHANGELOG index 6d2f597004..c73ac4649e 100644 --- a/activerecord/CHANGELOG +++ b/activerecord/CHANGELOG @@ -1,11 +1,9 @@ -*2.3.1 [RC2] (March 5, 2009)* +*2.3.2 [Final] (March 15, 2009)* * Added ActiveRecord::Base.find_each and ActiveRecord::Base.find_in_batches for batch processing [DHH/Jamis Buck] * Added that ActiveRecord::Base.exists? can be called with no arguments #1817 [Scott Taylor] -*2.3.0 [RC1] (February 1st, 2009)* - * Add Support for updating deeply nested models from a single form. #1202 [Eloy Duran] class Book < ActiveRecord::Base diff --git a/activerecord/Rakefile b/activerecord/Rakefile index aec9b3825b..b50008c971 100644 --- a/activerecord/Rakefile +++ b/activerecord/Rakefile @@ -177,7 +177,7 @@ spec = Gem::Specification.new do |s| s.files = s.files + Dir.glob( "#{dir}/**/*" ).delete_if { |item| item.include?( "\.svn" ) } end - s.add_dependency('activesupport', '= 2.3.1' + PKG_BUILD) + s.add_dependency('activesupport', '= 2.3.2' + PKG_BUILD) s.files.delete FIXTURES_ROOT + "/fixture_database.sqlite" s.files.delete FIXTURES_ROOT + "/fixture_database_2.sqlite" diff --git a/activerecord/lib/active_record/associations/association_collection.rb b/activerecord/lib/active_record/associations/association_collection.rb index ad375be184..3aef1b21e9 100644 --- a/activerecord/lib/active_record/associations/association_collection.rb +++ b/activerecord/lib/active_record/associations/association_collection.rb @@ -143,6 +143,8 @@ module ActiveRecord end # Remove all records from this association + # + # See delete for more info. def delete_all load_target delete(@target) @@ -200,11 +202,11 @@ module ActiveRecord end end - # Destroy +records+ and remove from this association calling +before_remove+ - # and +after_remove+ callbacks. + # Destroy +records+ and remove them from this association calling + # +before_remove+ and +after_remove+ callbacks. # - # Note this method will always remove records from database ignoring the - # +:dependent+ option. + # Note that this method will _always_ remove records from the database + # ignoring the +:dependent+ option. def destroy(*records) remove_records(records) do |records, old_records| old_records.each { |record| record.destroy } @@ -226,7 +228,9 @@ module ActiveRecord self end - # Destory all the records from this association + # Destory all the records from this association. + # + # See destroy for more info. def destroy_all load_target destroy(@target) diff --git a/activerecord/lib/active_record/base.rb b/activerecord/lib/active_record/base.rb index 4ef3cc698b..2a5385119d 100755 --- a/activerecord/lib/active_record/base.rb +++ b/activerecord/lib/active_record/base.rb @@ -736,12 +736,12 @@ module ActiveRecord #:nodoc: # ==== Parameters # # * +id+ - This should be the id or an array of ids to be updated. - # * +attributes+ - This should be a Hash of attributes to be set on the object, or an array of Hashes. + # * +attributes+ - This should be a hash of attributes to be set on the object, or an array of hashes. # # ==== Examples # # # Updating one record: - # Person.update(15, { :user_name => 'Samuel', :group => 'expert' }) + # Person.update(15, :user_name => 'Samuel', :group => 'expert') # # # Updating multiple records: # people = { 1 => { "first_name" => "David" }, 2 => { "first_name" => "Jeremy" } } diff --git a/activerecord/lib/active_record/batches.rb b/activerecord/lib/active_record/batches.rb index 03bd4f9f93..5a6cecd4ad 100644 --- a/activerecord/lib/active_record/batches.rb +++ b/activerecord/lib/active_record/batches.rb @@ -4,10 +4,12 @@ module ActiveRecord base.extend(ClassMethods) end - # When processing large numbers of records, it's often a good idea to do so in batches to prevent memory ballooning. + # When processing large numbers of records, it's often a good idea to do + # so in batches to prevent memory ballooning. module ClassMethods - # Yields each record that was found by the find +options+. The find is performed by find_in_batches - # with a batch size of 1000 (or as specified by the +batch_size+ option). + # Yields each record that was found by the find +options+. The find is + # performed by find_in_batches with a batch size of 1000 (or as + # specified by the <tt>:batch_size</tt> option). # # Example: # @@ -15,9 +17,10 @@ module ActiveRecord # person.party_all_night! # end # - # Note: This method is only intended to use for batch processing of large amounts of records that wouldn't fit in - # memory all at once. If you just need to loop over less than 1000 records, it's probably better just to use the - # regular find methods. + # Note: This method is only intended to use for batch processing of + # large amounts of records that wouldn't fit in memory all at once. If + # you just need to loop over less than 1000 records, it's probably + # better just to use the regular find methods. def find_each(options = {}) find_in_batches(options) do |records| records.each { |record| yield record } @@ -26,17 +29,22 @@ module ActiveRecord self end - # Yields each batch of records that was found by the find +options+ as an array. The size of each batch is - # set by the +batch_size+ option; the default is 1000. + # Yields each batch of records that was found by the find +options+ as + # an array. The size of each batch is set by the <tt>:batch_size</tt> + # option; the default is 1000. # - # You can control the starting point for the batch processing by supplying the +start+ option. This is especially - # useful if you want multiple workers dealing with the same processing queue. You can make worker 1 handle all the - # records between id 0 and 10,000 and worker 2 handle from 10,000 and beyond (by setting the +start+ option on that - # worker). + # You can control the starting point for the batch processing by + # supplying the <tt>:start</tt> option. This is especially useful if you + # want multiple workers dealing with the same processing queue. You can + # make worker 1 handle all the records between id 0 and 10,000 and + # worker 2 handle from 10,000 and beyond (by setting the <tt>:start</tt> + # option on that worker). # - # It's not possible to set the order. That is automatically set to ascending on the primary key ("id ASC") - # to make the batch ordering work. This also mean that this method only works with integer-based primary keys. - # You can't set the limit either, that's used to control the the batch sizes. + # It's not possible to set the order. That is automatically set to + # ascending on the primary key ("id ASC") to make the batch ordering + # work. This also mean that this method only works with integer-based + # primary keys. You can't set the limit either, that's used to control + # the the batch sizes. # # Example: # diff --git a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb index 6077ddcdb6..afd6472db8 100644 --- a/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb +++ b/activerecord/lib/active_record/connection_adapters/sqlite_adapter.rb @@ -72,6 +72,18 @@ module ActiveRecord # # * <tt>:database</tt> - Path to the database file. class SQLiteAdapter < AbstractAdapter + class Version + include Comparable + + def initialize(version_string) + @version = version_string.split('.').map(&:to_i) + end + + def <=>(version_string) + @version <=> version_string.split('.').map(&:to_i) + end + end + def initialize(connection, logger, config) super(connection, logger) @config = config @@ -81,6 +93,10 @@ module ActiveRecord 'SQLite' end + def supports_ddl_transactions? + sqlite_version >= '2.0.0' + end + def supports_migrations? #:nodoc: true end @@ -88,6 +104,10 @@ module ActiveRecord def requires_reloading? true end + + def supports_add_column? + sqlite_version >= '3.1.6' + end def disconnect! super @@ -169,7 +189,6 @@ module ActiveRecord catch_schema_changes { @connection.rollback } end - # SELECT ... FOR UPDATE is redundant since the table is locked. def add_lock!(sql, options) #:nodoc: sql @@ -218,14 +237,20 @@ module ActiveRecord execute "ALTER TABLE #{name} RENAME TO #{new_name}" end + # See: http://www.sqlite.org/lang_altertable.html + # SQLite has an additional restriction on the ALTER TABLE statement + def valid_alter_table_options( type, options) + type.to_sym != :primary_key + end + def add_column(table_name, column_name, type, options = {}) #:nodoc: - if @connection.respond_to?(:transaction_active?) && @connection.transaction_active? - raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction' + if supports_add_column? && valid_alter_table_options( type, options ) + super(table_name, column_name, type, options) + else + alter_table(table_name) do |definition| + definition.column(column_name, type, options) + end end - - super(table_name, column_name, type, options) - # See last paragraph on http://www.sqlite.org/lang_altertable.html - execute "VACUUM" end def remove_column(table_name, *column_names) #:nodoc: @@ -385,7 +410,7 @@ module ActiveRecord end def sqlite_version - @sqlite_version ||= select_value('select sqlite_version(*)') + @sqlite_version ||= SQLiteAdapter::Version.new(select_value('select sqlite_version(*)')) end def default_primary_key_type @@ -398,23 +423,9 @@ module ActiveRecord end class SQLite2Adapter < SQLiteAdapter # :nodoc: - def supports_count_distinct? #:nodoc: - false - end - def rename_table(name, new_name) move_table(name, new_name) end - - def add_column(table_name, column_name, type, options = {}) #:nodoc: - if @connection.respond_to?(:transaction_active?) && @connection.transaction_active? - raise StatementInvalid, 'Cannot add columns to a SQLite database while inside a transaction' - end - - alter_table(table_name) do |definition| - definition.column(column_name, type, options) - end - end end class DeprecatedSQLiteAdapter < SQLite2Adapter # :nodoc: diff --git a/activerecord/lib/active_record/validations.rb b/activerecord/lib/active_record/validations.rb index 4e084f071c..d2d12b80c9 100644 --- a/activerecord/lib/active_record/validations.rb +++ b/activerecord/lib/active_record/validations.rb @@ -802,7 +802,7 @@ module ActiveRecord # Validates whether the value of the specified attribute is available in a particular enumerable object. # # class Person < ActiveRecord::Base - # validates_inclusion_of :gender, :in => %w( m f ), :message => "woah! what are you then!??!!" + # validates_inclusion_of :gender, :in => %w( m f ) # validates_inclusion_of :age, :in => 0..99 # validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension {{value}} is not included in the list" # end diff --git a/activerecord/lib/active_record/version.rb b/activerecord/lib/active_record/version.rb index 809e91897e..852807b4c5 100644 --- a/activerecord/lib/active_record/version.rb +++ b/activerecord/lib/active_record/version.rb @@ -2,7 +2,7 @@ module ActiveRecord module VERSION #:nodoc: MAJOR = 2 MINOR = 3 - TINY = 1 + TINY = 2 STRING = [MAJOR, MINOR, TINY].join('.') end diff --git a/activerecord/test/cases/migration_test.rb b/activerecord/test/cases/migration_test.rb index 50d039ec77..16861f21b1 100644 --- a/activerecord/test/cases/migration_test.rb +++ b/activerecord/test/cases/migration_test.rb @@ -93,6 +93,30 @@ if ActiveRecord::Base.connection.supports_migrations? end end + def testing_table_with_only_foo_attribute + Person.connection.create_table :testings, :id => false do |t| + t.column :foo, :string + end + + yield Person.connection + ensure + Person.connection.drop_table :testings rescue nil + end + protected :testing_table_with_only_foo_attribute + + def test_create_table_without_id + testing_table_with_only_foo_attribute do |connection| + assert_equal connection.columns(:testings).size, 1 + end + end + + def test_add_column_with_primary_key_attribute + testing_table_with_only_foo_attribute do |connection| + assert_nothing_raised { connection.add_column :testings, :id, :primary_key } + assert_equal connection.columns(:testings).size, 2 + end + end + def test_create_table_adds_id Person.connection.create_table :testings do |t| t.column :foo, :string @@ -928,7 +952,7 @@ if ActiveRecord::Base.connection.supports_migrations? assert_equal(0, ActiveRecord::Migrator.current_version) end - if current_adapter?(:PostgreSQLAdapter) + if ActiveRecord::Base.connection.supports_ddl_transactions? def test_migrator_one_up_with_exception_and_rollback assert !Person.column_methods_hash.include?(:last_name) diff --git a/activerecord/test/cases/transactions_test.rb b/activerecord/test/cases/transactions_test.rb index f9ae5115fc..f6533b5396 100644 --- a/activerecord/test/cases/transactions_test.rb +++ b/activerecord/test/cases/transactions_test.rb @@ -349,7 +349,7 @@ class TransactionTest < ActiveRecord::TestCase end end - def test_sqlite_add_column_in_transaction_raises_statement_invalid + def test_sqlite_add_column_in_transaction return true unless current_adapter?(:SQLite3Adapter, :SQLiteAdapter) # Test first if column creation/deletion works correctly when no @@ -368,10 +368,15 @@ class TransactionTest < ActiveRecord::TestCase assert !Topic.column_names.include?('stuff') end - # Test now inside a transaction: add_column should raise a StatementInvalid - Topic.transaction do - assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) } - raise ActiveRecord::Rollback + if Topic.connection.supports_ddl_transactions? + assert_nothing_raised do + Topic.transaction { Topic.connection.add_column('topics', 'stuff', :string) } + end + else + Topic.transaction do + assert_raise(ActiveRecord::StatementInvalid) { Topic.connection.add_column('topics', 'stuff', :string) } + raise ActiveRecord::Rollback + end end end |