activerecord 2.3.8 → 2.3.9.pre
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of activerecord might be problematic. Click here for more details.
- data/CHANGELOG +1 -4
- data/Rakefile +1 -1
- data/examples/performance.rb +2 -0
- data/lib/active_record/association_preload.rb +12 -2
- data/lib/active_record/associations.rb +1 -1
- data/lib/active_record/associations/association_collection.rb +33 -4
- data/lib/active_record/attribute_methods.rb +0 -4
- data/lib/active_record/autosave_association.rb +2 -2
- data/lib/active_record/base.rb +28 -16
- data/lib/active_record/connection_adapters/abstract/connection_specification.rb +1 -1
- data/lib/active_record/connection_adapters/abstract/schema_statements.rb +1 -0
- data/lib/active_record/connection_adapters/abstract_adapter.rb +6 -0
- data/lib/active_record/connection_adapters/mysql_adapter.rb +2 -0
- data/lib/active_record/connection_adapters/sqlite3_adapter.rb +1 -1
- data/lib/active_record/connection_adapters/sqlite_adapter.rb +2 -1
- data/lib/active_record/dirty.rb +1 -1
- data/lib/active_record/locale/en.yml +11 -11
- data/lib/active_record/locking/optimistic.rb +1 -0
- data/lib/active_record/migration.rb +1 -1
- data/lib/active_record/named_scope.rb +14 -9
- data/lib/active_record/nested_attributes.rb +11 -8
- data/lib/active_record/serialization.rb +1 -1
- data/lib/active_record/session_store.rb +9 -1
- data/lib/active_record/validations.rb +12 -12
- data/lib/active_record/version.rb +1 -1
- data/test/cases/adapter_test.rb +7 -8
- data/test/cases/associations/eager_load_nested_include_test.rb +7 -7
- data/test/cases/associations/eager_load_nested_polymorphic_include.rb +19 -0
- data/test/cases/associations/eager_test.rb +7 -0
- data/test/cases/associations/has_many_associations_test.rb +68 -3
- data/test/cases/associations_test.rb +29 -0
- data/test/cases/base_test.rb +35 -75
- data/test/cases/connection_test_mysql.rb +1 -0
- data/test/cases/counter_cache_test.rb +84 -0
- data/test/cases/locking_test.rb +2 -1
- data/test/cases/migration_test.rb +4 -0
- data/test/cases/named_scope_test.rb +6 -1
- data/test/cases/nested_attributes_test.rb +49 -14
- data/test/cases/reflection_test.rb +5 -5
- data/test/cases/sp_test_mysql.rb +16 -0
- data/test/cases/transactions_test.rb +22 -1
- data/test/cases/validations_i18n_test.rb +12 -12
- data/test/cases/validations_test.rb +42 -30
- data/test/fixtures/fixture_database.sqlite3 +0 -0
- data/test/fixtures/fixture_database_2.sqlite3 +0 -0
- data/test/fixtures/polymorphic_designs.yml +19 -0
- data/test/fixtures/polymorphic_prices.yml +19 -0
- data/test/fixtures/tees.yml +4 -0
- data/test/fixtures/ties.yml +4 -0
- data/test/models/author.rb +2 -0
- data/test/models/event_author.rb +3 -0
- data/test/models/pirate.rb +2 -2
- data/test/models/polymorphic_design.rb +3 -0
- data/test/models/polymorphic_price.rb +3 -0
- data/test/models/post.rb +2 -0
- data/test/models/tee.rb +4 -0
- data/test/models/tie.rb +4 -0
- data/test/schema/mysql_specific_schema.rb +7 -0
- data/test/schema/schema.rb +16 -0
- metadata +24 -13
- data/examples/performance.sql +0 -85
- data/test/cases/encoding_test.rb +0 -6
- data/test/fixtures/fixture_database.sqlite +0 -0
- data/test/fixtures/fixture_database_2.sqlite +0 -0
| @@ -286,7 +286,9 @@ module ActiveRecord | |
| 286 286 | 
             
                    assign_to_or_mark_for_destruction(record, attributes, options[:allow_destroy])
         | 
| 287 287 |  | 
| 288 288 | 
             
                  elsif attributes['id']
         | 
| 289 | 
            -
                     | 
| 289 | 
            +
                    existing_record = self.class.reflect_on_association(association_name).klass.find(attributes['id'])
         | 
| 290 | 
            +
                    assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
         | 
| 291 | 
            +
                    self.send(association_name.to_s+'=', existing_record)
         | 
| 290 292 |  | 
| 291 293 | 
             
                  elsif !reject_new_record?(association_name, attributes)
         | 
| 292 294 | 
             
                    method = "build_#{association_name}"
         | 
| @@ -356,11 +358,16 @@ module ActiveRecord | |
| 356 358 | 
             
                      unless reject_new_record?(association_name, attributes)
         | 
| 357 359 | 
             
                        association.build(attributes.except(*UNASSIGNABLE_KEYS))
         | 
| 358 360 | 
             
                      end
         | 
| 361 | 
            +
             | 
| 362 | 
            +
                    elsif existing_records.size == 0 # Existing record but not yet associated
         | 
| 363 | 
            +
                      existing_record = self.class.reflect_on_association(association_name).klass.find(attributes['id'])
         | 
| 364 | 
            +
                      association.send(:add_record_to_target_with_callbacks, existing_record) unless association.loaded?
         | 
| 365 | 
            +
                      assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
         | 
| 366 | 
            +
             | 
| 359 367 | 
             
                    elsif existing_record = existing_records.detect { |record| record.id.to_s == attributes['id'].to_s }
         | 
| 360 368 | 
             
                      association.send(:add_record_to_target_with_callbacks, existing_record) unless association.loaded?
         | 
| 361 369 | 
             
                      assign_to_or_mark_for_destruction(existing_record, attributes, options[:allow_destroy])
         | 
| 362 | 
            -
             | 
| 363 | 
            -
                      raise_nested_attributes_record_not_found(association_name, attributes['id'])
         | 
| 370 | 
            +
             | 
| 364 371 | 
             
                    end
         | 
| 365 372 | 
             
                  end
         | 
| 366 373 | 
             
                end
         | 
| @@ -380,7 +387,7 @@ module ActiveRecord | |
| 380 387 | 
             
                  ConnectionAdapters::Column.value_to_boolean(hash['_destroy'])
         | 
| 381 388 | 
             
                end
         | 
| 382 389 |  | 
| 383 | 
            -
                # Determines if a new record should be  | 
| 390 | 
            +
                # Determines if a new record should be built by checking for
         | 
| 384 391 | 
             
                # has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
         | 
| 385 392 | 
             
                # association and evaluates to +true+.
         | 
| 386 393 | 
             
                def reject_new_record?(association_name, attributes)
         | 
| @@ -396,9 +403,5 @@ module ActiveRecord | |
| 396 403 | 
             
                  end
         | 
| 397 404 | 
             
                end
         | 
| 398 405 |  | 
| 399 | 
            -
                def raise_nested_attributes_record_not_found(association_name, record_id)
         | 
| 400 | 
            -
                  reflection = self.class.reflect_on_association(association_name)
         | 
| 401 | 
            -
                  raise RecordNotFound, "Couldn't find #{reflection.klass.name} with ID=#{record_id} for #{self.class.name} with ID=#{id}"
         | 
| 402 | 
            -
                end
         | 
| 403 406 | 
             
              end
         | 
| 404 407 | 
             
            end
         | 
| @@ -74,7 +74,7 @@ module ActiveRecord #:nodoc: | |
| 74 74 | 
             
                  end
         | 
| 75 75 |  | 
| 76 76 | 
             
                  def serializable_record
         | 
| 77 | 
            -
                     | 
| 77 | 
            +
                    {}.tap do |serializable_record|
         | 
| 78 78 | 
             
                      serializable_names.each { |name| serializable_record[name] = @record.send(name) }
         | 
| 79 79 | 
             
                      add_includes do |association, records, opts|
         | 
| 80 80 | 
             
                        if records.is_a?(Enumerable)
         | 
| @@ -184,7 +184,7 @@ module ActiveRecord | |
| 184 184 |  | 
| 185 185 | 
             
                    # Look up a session by id and unmarshal its data if found.
         | 
| 186 186 | 
             
                    def find_by_session_id(session_id)
         | 
| 187 | 
            -
                      if record =  | 
| 187 | 
            +
                      if record = connection.select_one("SELECT * FROM #{@@table_name} WHERE #{@@session_id_column}=#{connection.quote(session_id)}")
         | 
| 188 188 | 
             
                        new(:session_id => session_id, :marshaled_data => record['data'])
         | 
| 189 189 | 
             
                      end
         | 
| 190 190 | 
             
                    end
         | 
| @@ -310,6 +310,14 @@ module ActiveRecord | |
| 310 310 | 
             
                    return true
         | 
| 311 311 | 
             
                  end
         | 
| 312 312 |  | 
| 313 | 
            +
                  def destroy(env)
         | 
| 314 | 
            +
                    if sid = current_session_id(env)
         | 
| 315 | 
            +
                      Base.silence do
         | 
| 316 | 
            +
                        get_session_model(env, sid).destroy
         | 
| 317 | 
            +
                      end
         | 
| 318 | 
            +
                    end
         | 
| 319 | 
            +
                  end
         | 
| 320 | 
            +
                  
         | 
| 313 321 | 
             
                  def get_session_model(env, sid)
         | 
| 314 322 | 
             
                    if env[ENV_SESSION_OPTIONS_KEY][:id].nil?
         | 
| 315 323 | 
             
                      env[SESSION_RECORD_KEY] = find_session(sid)
         | 
| @@ -80,7 +80,7 @@ module ActiveRecord | |
| 80 80 |  | 
| 81 81 | 
             
                  # Wraps an error message into a full_message format.
         | 
| 82 82 | 
             
                  #
         | 
| 83 | 
            -
                  # The default full_message format for any locale is <tt>"{ | 
| 83 | 
            +
                  # The default full_message format for any locale is <tt>"%{attribute} %{message}"</tt>.
         | 
| 84 84 | 
             
                  # One can specify locale specific default full_message format by storing it as a
         | 
| 85 85 | 
             
                  # translation for the key <tt>:"activerecord.errors.full_messages.format"</tt>.
         | 
| 86 86 | 
             
                  #
         | 
| @@ -109,7 +109,7 @@ module ActiveRecord | |
| 109 109 | 
             
                    keys = [
         | 
| 110 110 | 
             
                      :"full_messages.#{@message}",
         | 
| 111 111 | 
             
                      :'full_messages.format',
         | 
| 112 | 
            -
                      '{ | 
| 112 | 
            +
                      '%{attribute} %{message}'
         | 
| 113 113 | 
             
                    ]
         | 
| 114 114 |  | 
| 115 115 | 
             
                    options.merge!(:default => keys, :message => self.message)
         | 
| @@ -604,13 +604,13 @@ module ActiveRecord | |
| 604 604 | 
             
                  #
         | 
| 605 605 | 
             
                  #   class Person < ActiveRecord::Base
         | 
| 606 606 | 
             
                  #     validates_length_of :first_name, :maximum=>30
         | 
| 607 | 
            -
                  #     validates_length_of :last_name, :maximum=>30, :message=>"less than { | 
| 607 | 
            +
                  #     validates_length_of :last_name, :maximum=>30, :message=>"less than %{count} if you don't mind"
         | 
| 608 608 | 
             
                  #     validates_length_of :fax, :in => 7..32, :allow_nil => true
         | 
| 609 609 | 
             
                  #     validates_length_of :phone, :in => 7..32, :allow_blank => true
         | 
| 610 610 | 
             
                  #     validates_length_of :user_name, :within => 6..20, :too_long => "pick a shorter name", :too_short => "pick a longer name"
         | 
| 611 | 
            -
                  #     validates_length_of :fav_bra_size, :minimum => 1, :too_short => "please enter at least { | 
| 612 | 
            -
                  #     validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with { | 
| 613 | 
            -
                  #     validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least { | 
| 611 | 
            +
                  #     validates_length_of :fav_bra_size, :minimum => 1, :too_short => "please enter at least %{count} character"
         | 
| 612 | 
            +
                  #     validates_length_of :smurf_leader, :is => 4, :message => "papa is spelled with %{count} characters... don't play me."
         | 
| 613 | 
            +
                  #     validates_length_of :essay, :minimum => 100, :too_short => "Your essay must be at least %{count} words."), :tokenizer => lambda {|str| str.scan(/\w+/) }
         | 
| 614 614 | 
             
                  #   end
         | 
| 615 615 | 
             
                  #
         | 
| 616 616 | 
             
                  # Configuration options:
         | 
| @@ -621,9 +621,9 @@ module ActiveRecord | |
| 621 621 | 
             
                  # * <tt>:in</tt> - A synonym(or alias) for <tt>:within</tt>.
         | 
| 622 622 | 
             
                  # * <tt>:allow_nil</tt> - Attribute may be +nil+; skip validation.
         | 
| 623 623 | 
             
                  # * <tt>:allow_blank</tt> - Attribute may be blank; skip validation.
         | 
| 624 | 
            -
                  # * <tt>:too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is { | 
| 625 | 
            -
                  # * <tt>:too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is { | 
| 626 | 
            -
                  # * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt> method and the attribute is the wrong size (default is: "is the wrong length (should be { | 
| 624 | 
            +
                  # * <tt>:too_long</tt> - The error message if the attribute goes over the maximum (default is: "is too long (maximum is %{count} characters)").
         | 
| 625 | 
            +
                  # * <tt>:too_short</tt> - The error message if the attribute goes under the minimum (default is: "is too short (min is %{count} characters)").
         | 
| 626 | 
            +
                  # * <tt>:wrong_length</tt> - The error message if using the <tt>:is</tt> method and the attribute is the wrong size (default is: "is the wrong length (should be %{count} characters)").
         | 
| 627 627 | 
             
                  # * <tt>:message</tt> - The error message to use for a <tt>:minimum</tt>, <tt>:maximum</tt>, or <tt>:is</tt> violation.  An alias of the appropriate <tt>too_long</tt>/<tt>too_short</tt>/<tt>wrong_length</tt> message.
         | 
| 628 628 | 
             
                  # * <tt>:on</tt> - Specifies when this validation is active (default is <tt>:save</tt>, other options <tt>:create</tt>, <tt>:update</tt>).
         | 
| 629 629 | 
             
                  # * <tt>:if</tt> - Specifies a method, proc or string to call to determine if the validation should
         | 
| @@ -825,7 +825,7 @@ module ActiveRecord | |
| 825 825 | 
             
                      if scope = configuration[:scope]
         | 
| 826 826 | 
             
                        Array(scope).map do |scope_item|
         | 
| 827 827 | 
             
                          scope_value = record.send(scope_item)
         | 
| 828 | 
            -
                          condition_sql << " AND " << attribute_condition("#{record.class.quoted_table_name}.#{scope_item}", scope_value)
         | 
| 828 | 
            +
                          condition_sql << " AND " << attribute_condition("#{record.class.quoted_table_name}.#{connection.quote_column_name(scope_item)}", scope_value)
         | 
| 829 829 | 
             
                          condition_params << scope_value
         | 
| 830 830 | 
             
                        end
         | 
| 831 831 | 
             
                      end
         | 
| @@ -885,7 +885,7 @@ module ActiveRecord | |
| 885 885 | 
             
                  #   class Person < ActiveRecord::Base
         | 
| 886 886 | 
             
                  #     validates_inclusion_of :gender, :in => %w( m f )
         | 
| 887 887 | 
             
                  #     validates_inclusion_of :age, :in => 0..99
         | 
| 888 | 
            -
                  #     validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension { | 
| 888 | 
            +
                  #     validates_inclusion_of :format, :in => %w( jpg gif png ), :message => "extension %{value} is not included in the list"
         | 
| 889 889 | 
             
                  #   end
         | 
| 890 890 | 
             
                  #
         | 
| 891 891 | 
             
                  # Configuration options:
         | 
| @@ -919,7 +919,7 @@ module ActiveRecord | |
| 919 919 | 
             
                  #   class Person < ActiveRecord::Base
         | 
| 920 920 | 
             
                  #     validates_exclusion_of :username, :in => %w( admin superuser ), :message => "You don't belong here"
         | 
| 921 921 | 
             
                  #     validates_exclusion_of :age, :in => 30..60, :message => "This site is only for under 30 and over 60"
         | 
| 922 | 
            -
                  #     validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension { | 
| 922 | 
            +
                  #     validates_exclusion_of :format, :in => %w( mov avi ), :message => "extension %{value} is not allowed"
         | 
| 923 923 | 
             
                  #   end
         | 
| 924 924 | 
             
                  #
         | 
| 925 925 | 
             
                  # Configuration options:
         | 
    
        data/test/cases/adapter_test.rb
    CHANGED
    
    | @@ -65,15 +65,14 @@ class AdapterTest < ActiveRecord::TestCase | |
| 65 65 | 
             
                end
         | 
| 66 66 |  | 
| 67 67 | 
             
                def test_not_specifying_database_name_for_cross_database_selects
         | 
| 68 | 
            -
                   | 
| 69 | 
            -
                     | 
| 70 | 
            -
                       | 
| 71 | 
            -
                       | 
| 72 | 
            -
                     | 
| 73 | 
            -
             | 
| 68 | 
            +
                  begin
         | 
| 69 | 
            +
                    assert_nothing_raised do
         | 
| 70 | 
            +
                      ActiveRecord::Base.establish_connection(ActiveRecord::Base.configurations['arunit'].except(:database))
         | 
| 71 | 
            +
                      ActiveRecord::Base.connection.execute "SELECT activerecord_unittest.pirates.*, activerecord_unittest2.courses.* FROM activerecord_unittest.pirates, activerecord_unittest2.courses"
         | 
| 72 | 
            +
                    end
         | 
| 73 | 
            +
                  ensure
         | 
| 74 | 
            +
                    ActiveRecord::Base.establish_connection 'arunit'
         | 
| 74 75 | 
             
                  end
         | 
| 75 | 
            -
             | 
| 76 | 
            -
                  ActiveRecord::Base.establish_connection 'arunit'
         | 
| 77 76 | 
             
                end
         | 
| 78 77 | 
             
              end
         | 
| 79 78 |  | 
| @@ -18,7 +18,7 @@ module Remembered | |
| 18 18 |  | 
| 19 19 | 
             
              module ClassMethods
         | 
| 20 20 | 
             
                def remembered; @@remembered ||= []; end
         | 
| 21 | 
            -
                def  | 
| 21 | 
            +
                def sample; @@remembered.sample; end
         | 
| 22 22 | 
             
              end
         | 
| 23 23 | 
             
            end
         | 
| 24 24 |  | 
| @@ -82,14 +82,14 @@ class EagerLoadPolyAssocsTest < ActiveRecord::TestCase | |
| 82 82 | 
             
                  [Circle, Square, Triangle, NonPolyOne, NonPolyTwo].map(&:create!)
         | 
| 83 83 | 
             
                end
         | 
| 84 84 | 
             
                1.upto(NUM_SIMPLE_OBJS) do
         | 
| 85 | 
            -
                  PaintColor.create!(:non_poly_one_id => NonPolyOne. | 
| 86 | 
            -
                  PaintTexture.create!(:non_poly_two_id => NonPolyTwo. | 
| 85 | 
            +
                  PaintColor.create!(:non_poly_one_id => NonPolyOne.sample.id)
         | 
| 86 | 
            +
                  PaintTexture.create!(:non_poly_two_id => NonPolyTwo.sample.id)
         | 
| 87 87 | 
             
                end
         | 
| 88 88 | 
             
                1.upto(NUM_SHAPE_EXPRESSIONS) do
         | 
| 89 | 
            -
                  shape_type = [Circle, Square, Triangle]. | 
| 90 | 
            -
                  paint_type = [PaintColor, PaintTexture]. | 
| 91 | 
            -
                  ShapeExpression.create!(:shape_type => shape_type.to_s, :shape_id => shape_type. | 
| 92 | 
            -
                                          :paint_type => paint_type.to_s, :paint_id => paint_type. | 
| 89 | 
            +
                  shape_type = [Circle, Square, Triangle].sample
         | 
| 90 | 
            +
                  paint_type = [PaintColor, PaintTexture].sample
         | 
| 91 | 
            +
                  ShapeExpression.create!(:shape_type => shape_type.to_s, :shape_id => shape_type.sample.id,
         | 
| 92 | 
            +
                                          :paint_type => paint_type.to_s, :paint_id => paint_type.sample.id)
         | 
| 93 93 | 
             
                end
         | 
| 94 94 | 
             
              end
         | 
| 95 95 |  | 
| @@ -0,0 +1,19 @@ | |
| 1 | 
            +
            require 'cases/helper'
         | 
| 2 | 
            +
            require 'models/tee'
         | 
| 3 | 
            +
            require 'models/tie'
         | 
| 4 | 
            +
            require 'models/polymorphic_design'
         | 
| 5 | 
            +
            require 'models/polymorphic_price'
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            class EagerLoadNestedPolymorphicIncludeTest < ActiveRecord::TestCase
         | 
| 8 | 
            +
              fixtures :tees, :ties, :polymorphic_designs, :polymorphic_prices
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              def test_eager_load_polymorphic_has_one_nested_under_polymorphic_belongs_to
         | 
| 11 | 
            +
                designs = PolymorphicDesign.scoped(:include => {:designable => :polymorphic_price})
         | 
| 12 | 
            +
             | 
| 13 | 
            +
                associated_price_ids = designs.map{|design| design.designable.polymorphic_price.id}
         | 
| 14 | 
            +
                expected_price_ids = [1, 2, 3, 4]
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                assert expected_price_ids.all?{|expected_id| associated_price_ids.include?(expected_id)},
         | 
| 17 | 
            +
                  "Expected associated prices to be #{expected_price_ids.inspect} but they were #{associated_price_ids.sort.inspect}"
         | 
| 18 | 
            +
              end
         | 
| 19 | 
            +
            end
         | 
| @@ -357,6 +357,13 @@ class EagerAssociationTest < ActiveRecord::TestCase | |
| 357 357 | 
             
                assert_equal comments(:more_greetings), Author.find(authors(:david).id, :include => :comments_with_order_and_conditions).comments_with_order_and_conditions.first
         | 
| 358 358 | 
             
              end
         | 
| 359 359 |  | 
| 360 | 
            +
              def test_eager_with_has_many_through_with_conditions_join_model_with_include
         | 
| 361 | 
            +
                post_tags = Post.find(posts(:welcome).id).misc_tags
         | 
| 362 | 
            +
                eager_post_tags = Post.find(1, :include => :misc_tags).misc_tags
         | 
| 363 | 
            +
                assert_equal post_tags, eager_post_tags
         | 
| 364 | 
            +
              end
         | 
| 365 | 
            +
             | 
| 366 | 
            +
             | 
| 360 367 | 
             
              def test_eager_with_has_many_through_join_model_with_include
         | 
| 361 368 | 
             
                author_comments = Author.find(authors(:david).id, :include => :comments_with_include).comments_with_include.to_a
         | 
| 362 369 | 
             
                assert_no_queries do
         | 
| @@ -21,6 +21,68 @@ class HasManyAssociationsTest < ActiveRecord::TestCase | |
| 21 21 | 
             
                Client.destroyed_client_ids.clear
         | 
| 22 22 | 
             
              end
         | 
| 23 23 |  | 
| 24 | 
            +
              def test_create_by
         | 
| 25 | 
            +
                person = Person.create! :first_name => 'tenderlove'
         | 
| 26 | 
            +
                post   = Post.find :first
         | 
| 27 | 
            +
             | 
| 28 | 
            +
                assert_equal [], person.readers
         | 
| 29 | 
            +
                assert_nil person.readers.find_by_post_id post.id
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                reader = person.readers.create_by_post_id post.id
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                assert_equal 1, person.readers.count
         | 
| 34 | 
            +
                assert_equal 1, person.readers.length
         | 
| 35 | 
            +
                assert_equal post, person.readers.first.post
         | 
| 36 | 
            +
                assert_equal person, person.readers.first.person
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
             | 
| 39 | 
            +
              def test_create_by_multi
         | 
| 40 | 
            +
                person = Person.create! :first_name => 'tenderlove'
         | 
| 41 | 
            +
                post   = Post.find :first
         | 
| 42 | 
            +
             | 
| 43 | 
            +
                assert_equal [], person.readers
         | 
| 44 | 
            +
             | 
| 45 | 
            +
                reader = person.readers.create_by_post_id_and_skimmer post.id, false
         | 
| 46 | 
            +
             | 
| 47 | 
            +
                assert_equal 1, person.readers.count
         | 
| 48 | 
            +
                assert_equal 1, person.readers.length
         | 
| 49 | 
            +
                assert_equal post, person.readers.first.post
         | 
| 50 | 
            +
                assert_equal person, person.readers.first.person
         | 
| 51 | 
            +
              end
         | 
| 52 | 
            +
             | 
| 53 | 
            +
              def test_find_or_create_by
         | 
| 54 | 
            +
                person = Person.create! :first_name => 'tenderlove'
         | 
| 55 | 
            +
                post   = Post.find :first
         | 
| 56 | 
            +
             | 
| 57 | 
            +
                assert_equal [], person.readers
         | 
| 58 | 
            +
                assert_nil person.readers.find_by_post_id post.id
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                reader = person.readers.find_or_create_by_post_id post.id
         | 
| 61 | 
            +
             | 
| 62 | 
            +
                assert_equal 1, person.readers.count
         | 
| 63 | 
            +
                assert_equal 1, person.readers.length
         | 
| 64 | 
            +
                assert_equal post, person.readers.first.post
         | 
| 65 | 
            +
                assert_equal person, person.readers.first.person
         | 
| 66 | 
            +
              end
         | 
| 67 | 
            +
             | 
| 68 | 
            +
              def test_find_or_create
         | 
| 69 | 
            +
                person = Person.create! :first_name => 'tenderlove'
         | 
| 70 | 
            +
                post   = Post.find :first
         | 
| 71 | 
            +
             | 
| 72 | 
            +
                assert_equal [], person.readers
         | 
| 73 | 
            +
                assert_nil person.readers.find(:first, :conditions => {
         | 
| 74 | 
            +
                  :post_id => post.id
         | 
| 75 | 
            +
                })
         | 
| 76 | 
            +
             | 
| 77 | 
            +
                reader = person.readers.find_or_create :post_id => post.id
         | 
| 78 | 
            +
             | 
| 79 | 
            +
                assert_equal 1, person.readers.count
         | 
| 80 | 
            +
                assert_equal 1, person.readers.length
         | 
| 81 | 
            +
                assert_equal post, person.readers.first.post
         | 
| 82 | 
            +
                assert_equal person, person.readers.first.person
         | 
| 83 | 
            +
              end
         | 
| 84 | 
            +
             | 
| 85 | 
            +
             | 
| 24 86 | 
             
              def force_signal37_to_load_all_clients_of_firm
         | 
| 25 87 | 
             
                companies(:first_firm).clients_of_firm.each {|f| }
         | 
| 26 88 | 
             
              end
         | 
| @@ -486,7 +548,7 @@ class HasManyAssociationsTest < ActiveRecord::TestCase | |
| 486 548 | 
             
                assert the_client.new_record?
         | 
| 487 549 | 
             
              end
         | 
| 488 550 |  | 
| 489 | 
            -
              def  | 
| 551 | 
            +
              def test_find_or_create_updates_size
         | 
| 490 552 | 
             
                number_of_clients = companies(:first_firm).clients.size
         | 
| 491 553 | 
             
                the_client = companies(:first_firm).clients.find_or_create_by_name("Yet another client")
         | 
| 492 554 | 
             
                assert_equal number_of_clients + 1, companies(:first_firm, :reload).clients.size
         | 
| @@ -772,8 +834,11 @@ class HasManyAssociationsTest < ActiveRecord::TestCase | |
| 772 834 |  | 
| 773 835 | 
             
              def test_destroy_all
         | 
| 774 836 | 
             
                force_signal37_to_load_all_clients_of_firm
         | 
| 775 | 
            -
                 | 
| 776 | 
            -
                 | 
| 837 | 
            +
                clients = companies(:first_firm).clients_of_firm.to_a
         | 
| 838 | 
            +
                assert !clients.empty?, "37signals has clients after load"
         | 
| 839 | 
            +
                destroyed = companies(:first_firm).clients_of_firm.destroy_all
         | 
| 840 | 
            +
                assert_equal clients.sort_by(&:id), destroyed.sort_by(&:id)
         | 
| 841 | 
            +
                assert destroyed.all? { |client| client.frozen? }, "destroyed clients should be frozen"
         | 
| 777 842 | 
             
                assert companies(:first_firm).clients_of_firm.empty?, "37signals has no clients after destroy all"
         | 
| 778 843 | 
             
                assert companies(:first_firm).clients_of_firm(true).empty?, "37signals has no clients after destroy all and refresh"
         | 
| 779 844 | 
             
              end
         | 
| @@ -18,6 +18,8 @@ require 'models/person' | |
| 18 18 | 
             
            require 'models/reader'
         | 
| 19 19 | 
             
            require 'models/parrot'
         | 
| 20 20 | 
             
            require 'models/pirate'
         | 
| 21 | 
            +
            require 'models/ship'
         | 
| 22 | 
            +
            require 'models/ship_part'
         | 
| 21 23 | 
             
            require 'models/treasure'
         | 
| 22 24 | 
             
            require 'models/price_estimate'
         | 
| 23 25 | 
             
            require 'models/club'
         | 
| @@ -29,6 +31,23 @@ class AssociationsTest < ActiveRecord::TestCase | |
| 29 31 | 
             
              fixtures :accounts, :companies, :developers, :projects, :developers_projects,
         | 
| 30 32 | 
             
                       :computers, :people, :readers
         | 
| 31 33 |  | 
| 34 | 
            +
              def test_loading_the_association_target_should_keep_child_records_marked_for_destruction
         | 
| 35 | 
            +
                ship = Ship.create!(:name => "The good ship Dollypop")
         | 
| 36 | 
            +
                part = ship.parts.create!(:name => "Mast")
         | 
| 37 | 
            +
                part.mark_for_destruction
         | 
| 38 | 
            +
                ship.parts.send(:load_target)
         | 
| 39 | 
            +
                assert ship.parts[0].marked_for_destruction?
         | 
| 40 | 
            +
              end
         | 
| 41 | 
            +
             | 
| 42 | 
            +
              def test_loading_the_association_target_should_load_most_recent_attributes_for_child_records_marked_for_destruction
         | 
| 43 | 
            +
                ship = Ship.create!(:name => "The good ship Dollypop")
         | 
| 44 | 
            +
                part = ship.parts.create!(:name => "Mast")
         | 
| 45 | 
            +
                part.mark_for_destruction
         | 
| 46 | 
            +
                ShipPart.find(part.id).update_attribute(:name, 'Deck')
         | 
| 47 | 
            +
                ship.parts.send(:load_target)
         | 
| 48 | 
            +
                assert_equal 'Deck', ship.parts[0].name
         | 
| 49 | 
            +
              end
         | 
| 50 | 
            +
             | 
| 32 51 | 
             
              def test_include_with_order_works
         | 
| 33 52 | 
             
                assert_nothing_raised {Account.find(:first, :order => 'id', :include => :firm)}
         | 
| 34 53 | 
             
                assert_nothing_raised {Account.find(:first, :order => :id, :include => :firm)}
         | 
| @@ -74,6 +93,16 @@ class AssociationsTest < ActiveRecord::TestCase | |
| 74 93 | 
             
                  assert_queries(1) { assert_not_nil firm.clients(true).each {} }
         | 
| 75 94 | 
             
                end
         | 
| 76 95 | 
             
              end
         | 
| 96 | 
            +
              
         | 
| 97 | 
            +
              def test_using_limitable_reflections_helper
         | 
| 98 | 
            +
                using_limitable_reflections = lambda { |reflections| ActiveRecord::Base.send :using_limitable_reflections?, reflections }
         | 
| 99 | 
            +
                belongs_to_reflections = [Tagging.reflect_on_association(:tag), Tagging.reflect_on_association(:super_tag)]
         | 
| 100 | 
            +
                has_many_reflections = [Tag.reflect_on_association(:taggings), Developer.reflect_on_association(:projects)]
         | 
| 101 | 
            +
                mixed_reflections = (belongs_to_reflections + has_many_reflections).uniq
         | 
| 102 | 
            +
                assert using_limitable_reflections.call(belongs_to_reflections), "Belong to associations are limitable"
         | 
| 103 | 
            +
                assert !using_limitable_reflections.call(has_many_reflections), "All has many style associations are not limitable"
         | 
| 104 | 
            +
                assert !using_limitable_reflections.call(mixed_reflections), "No collection associations (has many style) should pass"
         | 
| 105 | 
            +
              end
         | 
| 77 106 |  | 
| 78 107 | 
             
              def test_storing_in_pstore
         | 
| 79 108 | 
             
                require "tmpdir"
         | 
    
        data/test/cases/base_test.rb
    CHANGED
    
    | @@ -1,6 +1,5 @@ | |
| 1 1 | 
             
            require "cases/helper"
         | 
| 2 2 | 
             
            require 'models/post'
         | 
| 3 | 
            -
            require 'models/author'
         | 
| 4 3 | 
             
            require 'models/event_author'
         | 
| 5 4 | 
             
            require 'models/topic'
         | 
| 6 5 | 
             
            require 'models/reply'
         | 
| @@ -588,17 +587,25 @@ class BasicsTest < ActiveRecord::TestCase | |
| 588 587 | 
             
              end
         | 
| 589 588 |  | 
| 590 589 | 
             
              def test_destroy_all
         | 
| 591 | 
            -
                 | 
| 592 | 
            -
                topics_by_mary = Topic. | 
| 593 | 
            -
             | 
| 594 | 
            -
             | 
| 595 | 
            -
                 | 
| 590 | 
            +
                conditions = "author_name = 'Mary'"
         | 
| 591 | 
            +
                topics_by_mary = Topic.all(:conditions => conditions, :order => 'id')
         | 
| 592 | 
            +
                assert ! topics_by_mary.empty?
         | 
| 593 | 
            +
             | 
| 594 | 
            +
                assert_difference('Topic.count', -topics_by_mary.size) do
         | 
| 595 | 
            +
                  destroyed = Topic.destroy_all(conditions).sort_by(&:id)
         | 
| 596 | 
            +
                  assert_equal topics_by_mary, destroyed
         | 
| 597 | 
            +
                  assert destroyed.all? { |topic| topic.frozen? }
         | 
| 598 | 
            +
                end
         | 
| 596 599 | 
             
              end
         | 
| 597 600 |  | 
| 598 601 | 
             
              def test_destroy_many
         | 
| 599 | 
            -
                 | 
| 600 | 
            -
             | 
| 601 | 
            -
                 | 
| 602 | 
            +
                clients = Client.find([2, 3], :order => 'id')
         | 
| 603 | 
            +
             | 
| 604 | 
            +
                assert_difference('Client.count', -2) do
         | 
| 605 | 
            +
                  destroyed = Client.destroy([2, 3]).sort_by(&:id)
         | 
| 606 | 
            +
                  assert_equal clients, destroyed
         | 
| 607 | 
            +
                  assert destroyed.all? { |client| client.frozen? }
         | 
| 608 | 
            +
                end
         | 
| 602 609 | 
             
              end
         | 
| 603 610 |  | 
| 604 611 | 
             
              def test_delete_many
         | 
| @@ -612,55 +619,6 @@ class BasicsTest < ActiveRecord::TestCase | |
| 612 619 | 
             
                assert Topic.find(2).approved?
         | 
| 613 620 | 
             
              end
         | 
| 614 621 |  | 
| 615 | 
            -
              def test_increment_counter
         | 
| 616 | 
            -
                Topic.increment_counter("replies_count", 1)
         | 
| 617 | 
            -
                assert_equal 2, Topic.find(1).replies_count
         | 
| 618 | 
            -
             | 
| 619 | 
            -
                Topic.increment_counter("replies_count", 1)
         | 
| 620 | 
            -
                assert_equal 3, Topic.find(1).replies_count
         | 
| 621 | 
            -
              end
         | 
| 622 | 
            -
             | 
| 623 | 
            -
              def test_decrement_counter
         | 
| 624 | 
            -
                Topic.decrement_counter("replies_count", 2)
         | 
| 625 | 
            -
                assert_equal -1, Topic.find(2).replies_count
         | 
| 626 | 
            -
             | 
| 627 | 
            -
                Topic.decrement_counter("replies_count", 2)
         | 
| 628 | 
            -
                assert_equal -2, Topic.find(2).replies_count
         | 
| 629 | 
            -
              end
         | 
| 630 | 
            -
             | 
| 631 | 
            -
              def test_reset_counters
         | 
| 632 | 
            -
                assert_equal 1, Topic.find(1).replies_count
         | 
| 633 | 
            -
             | 
| 634 | 
            -
                Topic.increment_counter("replies_count", 1)
         | 
| 635 | 
            -
                assert_equal 2, Topic.find(1).replies_count
         | 
| 636 | 
            -
             | 
| 637 | 
            -
                Topic.reset_counters(1, :replies)
         | 
| 638 | 
            -
                assert_equal 1, Topic.find(1).replies_count
         | 
| 639 | 
            -
              end
         | 
| 640 | 
            -
             | 
| 641 | 
            -
              def test_update_counter
         | 
| 642 | 
            -
                category = categories(:general)
         | 
| 643 | 
            -
                assert_nil category.categorizations_count
         | 
| 644 | 
            -
                assert_equal 2, category.categorizations.count
         | 
| 645 | 
            -
             | 
| 646 | 
            -
                Category.update_counters(category.id, "categorizations_count" => category.categorizations.count)
         | 
| 647 | 
            -
                category.reload
         | 
| 648 | 
            -
                assert_not_nil category.categorizations_count
         | 
| 649 | 
            -
                assert_equal 2, category.categorizations_count
         | 
| 650 | 
            -
             | 
| 651 | 
            -
                Category.update_counters(category.id, "categorizations_count" => category.categorizations.count)
         | 
| 652 | 
            -
                category.reload
         | 
| 653 | 
            -
                assert_not_nil category.categorizations_count
         | 
| 654 | 
            -
                assert_equal 4, category.categorizations_count
         | 
| 655 | 
            -
             | 
| 656 | 
            -
                category_2 = categories(:technology)
         | 
| 657 | 
            -
                count_1, count_2 = (category.categorizations_count || 0), (category_2.categorizations_count || 0)
         | 
| 658 | 
            -
                Category.update_counters([category.id, category_2.id], "categorizations_count" => 2)
         | 
| 659 | 
            -
                category.reload; category_2.reload
         | 
| 660 | 
            -
                assert_equal count_1 + 2, category.categorizations_count
         | 
| 661 | 
            -
                assert_equal count_2 + 2, category_2.categorizations_count
         | 
| 662 | 
            -
              end
         | 
| 663 | 
            -
             | 
| 664 622 | 
             
              def test_update_all
         | 
| 665 623 | 
             
                assert_equal Topic.count, Topic.update_all("content = 'bulk updated!'")
         | 
| 666 624 | 
             
                assert_equal "bulk updated!", Topic.find(1).content
         | 
| @@ -749,22 +707,24 @@ class BasicsTest < ActiveRecord::TestCase | |
| 749 707 | 
             
              end
         | 
| 750 708 |  | 
| 751 709 | 
             
              def test_class_name
         | 
| 752 | 
            -
                 | 
| 753 | 
            -
             | 
| 754 | 
            -
             | 
| 755 | 
            -
             | 
| 756 | 
            -
             | 
| 757 | 
            -
             | 
| 758 | 
            -
             | 
| 759 | 
            -
             | 
| 760 | 
            -
             | 
| 761 | 
            -
             | 
| 762 | 
            -
             | 
| 763 | 
            -
             | 
| 764 | 
            -
             | 
| 765 | 
            -
             | 
| 766 | 
            -
             | 
| 767 | 
            -
             | 
| 710 | 
            +
                ActiveSupport::Deprecation.silence do
         | 
| 711 | 
            +
                  assert_equal "Firm", ActiveRecord::Base.class_name("firms")
         | 
| 712 | 
            +
                  assert_equal "Category", ActiveRecord::Base.class_name("categories")
         | 
| 713 | 
            +
                  assert_equal "AccountHolder", ActiveRecord::Base.class_name("account_holder")
         | 
| 714 | 
            +
             | 
| 715 | 
            +
                  ActiveRecord::Base.pluralize_table_names = false
         | 
| 716 | 
            +
                  assert_equal "Firms", ActiveRecord::Base.class_name( "firms" )
         | 
| 717 | 
            +
                  ActiveRecord::Base.pluralize_table_names = true
         | 
| 718 | 
            +
             | 
| 719 | 
            +
                  ActiveRecord::Base.table_name_prefix = "test_"
         | 
| 720 | 
            +
                  assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms" )
         | 
| 721 | 
            +
                  ActiveRecord::Base.table_name_suffix = "_tests"
         | 
| 722 | 
            +
                  assert_equal "Firm", ActiveRecord::Base.class_name( "test_firms_tests" )
         | 
| 723 | 
            +
                  ActiveRecord::Base.table_name_prefix = ""
         | 
| 724 | 
            +
                  assert_equal "Firm", ActiveRecord::Base.class_name( "firms_tests" )
         | 
| 725 | 
            +
                  ActiveRecord::Base.table_name_suffix = ""
         | 
| 726 | 
            +
                  assert_equal "Firm", ActiveRecord::Base.class_name( "firms" )
         | 
| 727 | 
            +
                end
         | 
| 768 728 | 
             
              end
         | 
| 769 729 |  | 
| 770 730 | 
             
              def test_null_fields
         | 
| @@ -2090,7 +2050,7 @@ class BasicsTest < ActiveRecord::TestCase | |
| 2090 2050 |  | 
| 2091 2051 | 
             
              def test_inspect_instance
         | 
| 2092 2052 | 
             
                topic = topics(:first)
         | 
| 2093 | 
            -
                assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil>), topic.inspect
         | 
| 2053 | 
            +
                assert_equal %(#<Topic id: 1, title: "The First Topic", author_name: "David", author_email_address: "david@loudthinking.com", written_on: "#{topic.written_on.to_s(:db)}", bonus_time: "#{topic.bonus_time.to_s(:db)}", last_read: "#{topic.last_read.to_s(:db)}", content: "Have a nice day", approved: false, replies_count: 1, parent_id: nil, parent_title: nil, type: nil, group: nil>), topic.inspect
         | 
| 2094 2054 | 
             
              end
         | 
| 2095 2055 |  | 
| 2096 2056 | 
             
              def test_inspect_new_instance
         |