diff options
Diffstat (limited to 'activerecord/test/cases/base_test.rb')
-rw-r--r-- | activerecord/test/cases/base_test.rb | 276 |
1 files changed, 131 insertions, 145 deletions
diff --git a/activerecord/test/cases/base_test.rb b/activerecord/test/cases/base_test.rb index cde188f6c3..6acd9aa39f 100644 --- a/activerecord/test/cases/base_test.rb +++ b/activerecord/test/cases/base_test.rb @@ -10,6 +10,7 @@ require 'models/category' require 'models/company' require 'models/customer' require 'models/developer' +require 'models/computer' require 'models/project' require 'models/default' require 'models/auto_id' @@ -102,8 +103,8 @@ class BasicsTest < ActiveRecord::TestCase end def test_columns_should_obey_set_primary_key - pk = Subscriber.columns.find { |x| x.name == 'nick' } - assert pk.primary, 'nick should be primary key' + pk = Subscriber.columns_hash[Subscriber.primary_key] + assert_equal 'nick', pk.name, 'nick should be primary key' end def test_primary_key_with_no_id @@ -121,6 +122,10 @@ class BasicsTest < ActiveRecord::TestCase assert_equal 1, Topic.limit(1).to_a.length end + def test_limit_should_take_value_from_latest_limit + assert_equal 1, Topic.limit(2).limit(1).to_a.length + end + def test_invalid_limit assert_raises(ArgumentError) do Topic.limit("asdfadf").to_a @@ -156,19 +161,11 @@ class BasicsTest < ActiveRecord::TestCase end def test_preserving_date_objects - if current_adapter?(:SybaseAdapter) - # Sybase ctlib does not (yet?) support the date type; use datetime instead. - assert_kind_of( - Time, Topic.find(1).last_read, - "The last_read attribute should be of the Time class" - ) - else - # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb) - assert_kind_of( - Date, Topic.find(1).last_read, - "The last_read attribute should be of the Date class" - ) - end + # Oracle enhanced adapter allows to define Date attributes in model class (see topic.rb) + assert_kind_of( + Date, Topic.find(1).last_read, + "The last_read attribute should be of the Date class" + ) end def test_previously_changed @@ -208,7 +205,7 @@ class BasicsTest < ActiveRecord::TestCase ) # For adapters which support microsecond resolution. - if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter) + if current_adapter?(:PostgreSQLAdapter, :SQLite3Adapter) || mysql_56? assert_equal 11, Topic.find(1).written_on.sec assert_equal 223300, Topic.find(1).written_on.usec assert_equal 9900, Topic.find(2).written_on.usec @@ -317,7 +314,7 @@ class BasicsTest < ActiveRecord::TestCase def test_load topics = Topic.all.merge!(:order => 'id').to_a - assert_equal(4, topics.size) + assert_equal(5, topics.size) assert_equal(topics(:first).title, topics.first.title) end @@ -476,8 +473,8 @@ class BasicsTest < ActiveRecord::TestCase end end - # Oracle, and Sybase do not have a TIME datatype. - unless current_adapter?(:OracleAdapter, :SybaseAdapter) + # Oracle does not have a TIME datatype. + unless current_adapter?(:OracleAdapter) def test_utc_as_time_zone with_timezone_config default: :utc do attributes = { "bonus_time" => "5:42:00AM" } @@ -511,12 +508,7 @@ class BasicsTest < ActiveRecord::TestCase topic = Topic.find(topic.id) assert_nil topic.last_read - # Sybase adapter does not allow nulls in boolean columns - if current_adapter?(:SybaseAdapter) - assert topic.approved == false - else - assert_nil topic.approved - end + assert_nil topic.approved end def test_equality @@ -527,8 +519,17 @@ class BasicsTest < ActiveRecord::TestCase assert_equal Topic.find('1-meowmeow'), Topic.find(1) end + def test_find_by_slug_with_array + assert_equal Topic.find(['1-meowmeow', '2-hello']), Topic.find([1, 2]) + end + + def test_find_by_slug_with_range + assert_equal Topic.where(id: '1-meowmeow'..'2-hello'), Topic.where(id: 1..2) + end + def test_equality_of_new_records assert_not_equal Topic.new, Topic.new + assert_equal false, Topic.new == Topic.new end def test_equality_of_destroyed_records @@ -540,6 +541,47 @@ class BasicsTest < ActiveRecord::TestCase assert_equal topic_2, topic_1 end + def test_equality_with_blank_ids + one = Subscriber.new(:id => '') + two = Subscriber.new(:id => '') + assert_equal one, two + end + + def test_equality_of_relation_and_collection_proxy + car = Car.create! + car.bulbs.build + car.save + + assert car.bulbs == Bulb.where(car_id: car.id), 'CollectionProxy should be comparable with Relation' + assert Bulb.where(car_id: car.id) == car.bulbs, 'Relation should be comparable with CollectionProxy' + end + + def test_equality_of_relation_and_array + car = Car.create! + car.bulbs.build + car.save + + assert Bulb.where(car_id: car.id) == car.bulbs.to_a, 'Relation should be comparable with Array' + end + + def test_equality_of_relation_and_association_relation + car = Car.create! + car.bulbs.build + car.save + + assert_equal Bulb.where(car_id: car.id), car.bulbs.includes(:car), 'Relation should be comparable with AssociationRelation' + assert_equal car.bulbs.includes(:car), Bulb.where(car_id: car.id), 'AssociationRelation should be comparable with Relation' + end + + def test_equality_of_collection_proxy_and_association_relation + car = Car.create! + car.bulbs.build + car.save + + assert_equal car.bulbs, car.bulbs.includes(:car), 'CollectionProxy should be comparable with AssociationRelation' + assert_equal car.bulbs.includes(:car), car.bulbs, 'AssociationRelation should be comparable with CollectionProxy' + end + def test_hashing assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ] end @@ -574,12 +616,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal nil, Topic.find_by_id(topic.id) end - def test_blank_ids - one = Subscriber.new(:id => '') - two = Subscriber.new(:id => '') - assert_equal one, two - end - def test_comparison_with_different_objects topic = Topic.create category = Category.create(:name => "comparison") @@ -622,6 +658,7 @@ class BasicsTest < ActiveRecord::TestCase assert_equal ["EUC-JP"], Weird.columns.map {|c| c.name.encoding.name }.uniq ensure silence_warnings { Encoding.default_internal = old_default_internal } + Weird.reset_column_information end end @@ -644,8 +681,8 @@ class BasicsTest < ActiveRecord::TestCase end def test_attributes_on_dummy_time - # Oracle, and Sybase do not have a TIME datatype. - return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + # Oracle does not have a TIME datatype. + return true if current_adapter?(:OracleAdapter) with_timezone_config default: :local do attributes = { @@ -658,8 +695,8 @@ class BasicsTest < ActiveRecord::TestCase end def test_attributes_on_dummy_time_with_invalid_time - # Oracle, and Sybase do not have a TIME datatype. - return true if current_adapter?(:OracleAdapter, :SybaseAdapter) + # Oracle does not have a TIME datatype. + return true if current_adapter?(:OracleAdapter) attributes = { "bonus_time" => "not a time" @@ -746,8 +783,14 @@ class BasicsTest < ActiveRecord::TestCase assert_equal("c", duped_topic.title) end + DeveloperSalary = Struct.new(:amount) def test_dup_with_aggregate_of_same_name_as_attribute - dev = DeveloperWithAggregate.find(1) + developer_with_aggregate = Class.new(ActiveRecord::Base) do + self.table_name = 'developers' + composed_of :salary, :class_name => 'BasicsTest::DeveloperSalary', :mapping => [%w(salary amount)] + end + + dev = developer_with_aggregate.find(1) assert_kind_of DeveloperSalary, dev.salary dup = nil @@ -855,97 +898,13 @@ class BasicsTest < ActiveRecord::TestCase assert_equal 'a text field', default.char3 end end - - class Geometric < ActiveRecord::Base; end - def test_geometric_content - - # accepted format notes: - # ()'s aren't required - # values can be a mix of float or integer - - g = Geometric.new( - :a_point => '(5.0, 6.1)', - #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql - :a_line_segment => '(2.0, 3), (5.5, 7.0)', - :a_box => '2.0, 3, 5.5, 7.0', - :a_path => '[(2.0, 3), (5.5, 7.0), (8.5, 11.0)]', # [ ] is an open path - :a_polygon => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', - :a_circle => '<(5.3, 10.4), 2>' - ) - - assert g.save - - # Reload and check that we have all the geometric attributes. - h = Geometric.find(g.id) - - assert_equal [5.0, 6.1], h.a_point - assert_equal '[(2,3),(5.5,7)]', h.a_line_segment - assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner - assert_equal '[(2,3),(5.5,7),(8.5,11)]', h.a_path - assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon - assert_equal '<(5.3,10.4),2>', h.a_circle - - # use a geometric function to test for an open path - objs = Geometric.find_by_sql ["select isopen(a_path) from geometrics where id = ?", g.id] - - assert_equal true, objs[0].isopen - - # test alternate formats when defining the geometric types - - g = Geometric.new( - :a_point => '5.0, 6.1', - #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql - :a_line_segment => '((2.0, 3), (5.5, 7.0))', - :a_box => '(2.0, 3), (5.5, 7.0)', - :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path - :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0', - :a_circle => '((5.3, 10.4), 2)' - ) - - assert g.save - - # Reload and check that we have all the geometric attributes. - h = Geometric.find(g.id) - - assert_equal [5.0, 6.1], h.a_point - assert_equal '[(2,3),(5.5,7)]', h.a_line_segment - assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner - assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path - assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon - assert_equal '<(5.3,10.4),2>', h.a_circle - - # use a geometric function to test for an closed path - objs = Geometric.find_by_sql ["select isclosed(a_path) from geometrics where id = ?", g.id] - - assert_equal true, objs[0].isclosed - - # test native ruby formats when defining the geometric types - g = Geometric.new( - :a_point => [5.0, 6.1], - #:a_line => '((2.0, 3), (5.5, 7.0))' # line type is currently unsupported in postgresql - :a_line_segment => '((2.0, 3), (5.5, 7.0))', - :a_box => '(2.0, 3), (5.5, 7.0)', - :a_path => '((2.0, 3), (5.5, 7.0), (8.5, 11.0))', # ( ) is a closed path - :a_polygon => '2.0, 3, 5.5, 7.0, 8.5, 11.0', - :a_circle => '((5.3, 10.4), 2)' - ) - - assert g.save - - # Reload and check that we have all the geometric attributes. - h = Geometric.find(g.id) - - assert_equal [5.0, 6.1], h.a_point - assert_equal '[(2,3),(5.5,7)]', h.a_line_segment - assert_equal '(5.5,7),(2,3)', h.a_box # reordered to store upper right corner then bottom left corner - assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_path - assert_equal '((2,3),(5.5,7),(8.5,11))', h.a_polygon - assert_equal '<(5.3,10.4),2>', h.a_circle - end end class NumericData < ActiveRecord::Base self.table_name = 'numeric_data' + + attribute :my_house_population, Type::Integer.new + attribute :atoms_in_universe, Type::Integer.new end def test_big_decimal_conditions @@ -1125,7 +1084,7 @@ class BasicsTest < ActiveRecord::TestCase k = Class.new(ak) k.table_name = "projects" orig_name = k.sequence_name - return skip "sequences not supported by db" unless orig_name + skip "sequences not supported by db" unless orig_name assert_equal k.reset_sequence_name, orig_name end @@ -1297,20 +1256,40 @@ class BasicsTest < ActiveRecord::TestCase end def test_compute_type_nonexistent_constant - assert_raises NameError do + e = assert_raises NameError do ActiveRecord::Base.send :compute_type, 'NonexistentModel' end + assert_equal 'uninitialized constant ActiveRecord::Base::NonexistentModel', e.message + assert_equal 'ActiveRecord::Base::NonexistentModel', e.name end def test_compute_type_no_method_error - ActiveSupport::Dependencies.stubs(:constantize).raises(NoMethodError) + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(NoMethodError) assert_raises NoMethodError do ActiveRecord::Base.send :compute_type, 'InvalidModel' end end + def test_compute_type_on_undefined_method + error = nil + begin + Class.new(Author) do + alias_method :foo, :bar + end + rescue => e + error = e + end + + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(e) + + exception = assert_raises NameError do + ActiveRecord::Base.send :compute_type, 'InvalidModel' + end + assert_equal error.message, exception.message + end + def test_compute_type_argument_error - ActiveSupport::Dependencies.stubs(:constantize).raises(ArgumentError) + ActiveSupport::Dependencies.stubs(:safe_constantize).raises(ArgumentError) assert_raises ArgumentError do ActiveRecord::Base.send :compute_type, 'InvalidModel' end @@ -1321,7 +1300,10 @@ class BasicsTest < ActiveRecord::TestCase c1 = Post.connection.schema_cache.columns('posts') ActiveRecord::Base.clear_cache! c2 = Post.connection.schema_cache.columns('posts') - assert_not_equal c1, c2 + c1.each_with_index do |v, i| + assert_not_same v, c2[i] + end + assert_equal c1, c2 end def test_current_scope_is_reset @@ -1373,6 +1355,8 @@ class BasicsTest < ActiveRecord::TestCase }) rd, wr = IO.pipe + rd.binmode + wr.binmode ActiveRecord::Base.connection_handler.clear_all_connections! @@ -1442,15 +1426,14 @@ class BasicsTest < ActiveRecord::TestCase attrs = topic.attributes.dup attrs.delete 'id' - typecast = Class.new { + typecast = Class.new(ActiveRecord::Type::Value) { def type_cast value "t.lo" end } types = { 'author_name' => typecast.new } - topic = Topic.allocate.init_with 'attributes' => attrs, - 'column_types' => types + topic = Topic.instantiate(attrs, types) assert_equal 't.lo', topic.author_name end @@ -1477,20 +1460,6 @@ class BasicsTest < ActiveRecord::TestCase assert_equal "", Company.new.description end - ["find_by", "find_by!"].each do |meth| - test "#{meth} delegates to scoped" do - record = stub - - scope = mock - scope.expects(meth).with(:foo, :bar).returns(record) - - klass = Class.new(ActiveRecord::Base) - klass.stubs(:all => scope) - - assert_equal record, klass.public_send(meth, :foo, :bar) - end - end - test "scoped can take a values hash" do klass = Class.new(ActiveRecord::Base) assert_equal ['foo'], klass.all.merge!(select: 'foo').select_values @@ -1551,4 +1520,21 @@ class BasicsTest < ActiveRecord::TestCase assert_equal after_handler, new_handler assert_equal orig_handler, klass.connection_handler end + + # Note: This is a performance optimization for Array#uniq and Hash#[] with + # AR::Base objects. If the future has made this irrelevant, feel free to + # delete this. + test "records without an id have unique hashes" do + assert_not_equal Post.new.hash, Post.new.hash + end + + test "resetting column information doesn't remove attribute methods" do + topic = topics(:first) + + assert_not topic.id_changed? + + Topic.reset_column_information + + assert_not topic.id_changed? + end end |