ibm_db 1.0.0 → 1.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGES +6 -0
- data/README +17 -17
- data/ext/extconf.rb +18 -15
- data/ext/ibm_db.c +91 -3
- data/ext/ruby_ibm_db.h +17 -0
- data/lib/active_record/connection_adapters/ibm_db_adapter.rb +65 -39
- data/test/cases/adapter_test.rb +6 -0
- data/test/cases/associations/eager_test.rb +54 -5
- data/test/cases/associations/has_and_belongs_to_many_associations_test.rb +71 -4
- data/test/cases/associations/has_many_through_associations_test.rb +50 -3
- data/test/cases/base_test.rb +106 -34
- data/test/cases/calculations_test.rb +5 -0
- data/test/cases/finder_test.rb +162 -11
- data/test/cases/fixtures_test.rb +32 -3
- data/test/cases/migration_test.rb +60 -22
- data/test/cases/validations_test.rb +44 -33
- data/test/schema/schema.rb +13 -2
- metadata +2 -2
@@ -68,6 +68,16 @@ class DeveloperWithSymbolsForKeys < ActiveRecord::Base
|
|
68
68
|
:foreign_key => "developer_id"
|
69
69
|
end
|
70
70
|
|
71
|
+
class DeveloperWithCounterSQL < ActiveRecord::Base
|
72
|
+
set_table_name 'developers'
|
73
|
+
has_and_belongs_to_many :projects,
|
74
|
+
:class_name => "DeveloperWithCounterSQL",
|
75
|
+
:join_table => "developers_projects",
|
76
|
+
:association_foreign_key => "project_id",
|
77
|
+
:foreign_key => "developer_id",
|
78
|
+
:counter_sql => 'SELECT COUNT(*) AS count_all FROM projects INNER JOIN developers_projects ON projects.id = developers_projects.project_id WHERE developers_projects.developer_id =#{id}'
|
79
|
+
end
|
80
|
+
|
71
81
|
class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
72
82
|
fixtures :accounts, :companies, :categories, :posts, :categories_posts, :developers, :projects, :developers_projects,
|
73
83
|
:parrots, :pirates, :treasures, :price_estimates, :tags, :taggings
|
@@ -253,8 +263,8 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
253
263
|
assert !devel.projects.loaded?
|
254
264
|
|
255
265
|
assert_equal devel.projects.last, proj
|
256
|
-
assert devel.projects.loaded?
|
257
|
-
|
266
|
+
assert !devel.projects.loaded?
|
267
|
+
|
258
268
|
assert !proj.new_record?
|
259
269
|
assert_equal Developer.find(1).projects.sort_by(&:id).last, proj # prove join table is updated
|
260
270
|
end
|
@@ -636,11 +646,39 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
636
646
|
assert_equal 3, Developer.find(:all, :include => {:projects => :developers}, :conditions => 'developers_projects_join.joined_on IS NOT NULL', :group => group.join(",")).size
|
637
647
|
end
|
638
648
|
|
649
|
+
def test_find_grouped
|
650
|
+
all_posts_from_category1 = Post.find(:all, :conditions => "category_id = 1", :joins => :categories)
|
651
|
+
grouped_posts_of_category1 = Post.find(:all, :conditions => "category_id = 1", :group => "author_id", :select => 'count(posts.id) as posts_count', :joins => :categories)
|
652
|
+
assert_equal 4, all_posts_from_category1.size
|
653
|
+
assert_equal 1, grouped_posts_of_category1.size
|
654
|
+
end
|
655
|
+
|
656
|
+
def test_find_scoped_grouped
|
657
|
+
assert_equal 4, categories(:general).posts_gruoped_by_title.size
|
658
|
+
assert_equal 1, categories(:technology).posts_gruoped_by_title.size
|
659
|
+
end
|
660
|
+
|
639
661
|
def test_get_ids
|
640
662
|
assert_equal projects(:active_record, :action_controller).map(&:id).sort, developers(:david).project_ids.sort
|
641
663
|
assert_equal [projects(:active_record).id], developers(:jamis).project_ids
|
642
664
|
end
|
643
665
|
|
666
|
+
def test_get_ids_for_loaded_associations
|
667
|
+
developer = developers(:david)
|
668
|
+
developer.projects(true)
|
669
|
+
assert_queries(0) do
|
670
|
+
developer.project_ids
|
671
|
+
developer.project_ids
|
672
|
+
end
|
673
|
+
end
|
674
|
+
|
675
|
+
def test_get_ids_for_unloaded_associations_does_not_load_them
|
676
|
+
developer = developers(:david)
|
677
|
+
assert !developer.projects.loaded?
|
678
|
+
assert_equal projects(:active_record, :action_controller).map(&:id).sort, developer.project_ids.sort
|
679
|
+
assert !developer.projects.loaded?
|
680
|
+
end
|
681
|
+
|
644
682
|
def test_assign_ids
|
645
683
|
developer = Developer.new("name" => "Joe")
|
646
684
|
developer.project_ids = projects(:active_record, :action_controller).map(&:id)
|
@@ -706,5 +744,34 @@ class HasAndBelongsToManyAssociationsTest < ActiveRecord::TestCase
|
|
706
744
|
# due to Unknown column 'authors.id'
|
707
745
|
assert Category.find(1).posts_with_authors_sorted_by_author_id.find_by_title('Welcome to the weblog')
|
708
746
|
end
|
709
|
-
|
710
|
-
|
747
|
+
|
748
|
+
def test_counting_on_habtm_association_and_not_array
|
749
|
+
david = Developer.find(1)
|
750
|
+
# Extra parameter just to make sure we aren't falling back to
|
751
|
+
# Array#count in Ruby >=1.8.7, which would raise an ArgumentError
|
752
|
+
assert_nothing_raised { david.projects.count(:all, :conditions => '1=1') }
|
753
|
+
end
|
754
|
+
|
755
|
+
def test_count
|
756
|
+
david = Developer.find(1)
|
757
|
+
assert_equal 2, david.projects.count
|
758
|
+
end
|
759
|
+
|
760
|
+
def test_count_with_counter_sql
|
761
|
+
developer = DeveloperWithCounterSQL.create(:name => 'tekin')
|
762
|
+
developer.project_ids = [projects(:active_record).id]
|
763
|
+
developer.save
|
764
|
+
developer.reload
|
765
|
+
assert_equal 1, developer.projects.count
|
766
|
+
end
|
767
|
+
|
768
|
+
uses_mocha 'mocking Post.transaction' do
|
769
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
770
|
+
Post.expects(:transaction)
|
771
|
+
Category.find(:first).posts.transaction do
|
772
|
+
# nothing
|
773
|
+
end
|
774
|
+
end
|
775
|
+
end
|
776
|
+
end
|
777
|
+
end
|
@@ -2,15 +2,18 @@ require "cases/helper"
|
|
2
2
|
require 'models/post'
|
3
3
|
require 'models/person'
|
4
4
|
require 'models/reader'
|
5
|
+
require 'models/comment'
|
5
6
|
|
6
7
|
class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
7
|
-
fixtures :posts, :readers, :people
|
8
|
+
fixtures :posts, :readers, :people, :comments, :authors
|
8
9
|
|
9
10
|
def test_associate_existing
|
10
11
|
assert_queries(2) { posts(:thinking);people(:david) }
|
11
|
-
|
12
|
+
|
13
|
+
posts(:thinking).people
|
14
|
+
|
12
15
|
assert_queries(1) do
|
13
|
-
|
16
|
+
posts(:thinking).people << people(:david)
|
14
17
|
end
|
15
18
|
|
16
19
|
assert_queries(1) do
|
@@ -199,4 +202,48 @@ class HasManyThroughAssociationsTest < ActiveRecord::TestCase
|
|
199
202
|
def test_count_with_include_should_alias_join_table
|
200
203
|
assert_equal 2, people(:michael).posts.count(:include => :readers)
|
201
204
|
end
|
205
|
+
|
206
|
+
def test_get_ids
|
207
|
+
assert_equal [posts(:welcome).id, posts(:authorless).id].sort, people(:michael).post_ids.sort
|
208
|
+
end
|
209
|
+
|
210
|
+
def test_get_ids_for_loaded_associations
|
211
|
+
person = people(:michael)
|
212
|
+
person.posts(true)
|
213
|
+
assert_queries(0) do
|
214
|
+
person.post_ids
|
215
|
+
person.post_ids
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def test_get_ids_for_unloaded_associations_does_not_load_them
|
220
|
+
person = people(:michael)
|
221
|
+
assert !person.posts.loaded?
|
222
|
+
assert_equal [posts(:welcome).id, posts(:authorless).id].sort, person.post_ids.sort
|
223
|
+
assert !person.posts.loaded?
|
224
|
+
end
|
225
|
+
|
226
|
+
uses_mocha 'mocking Tag.transaction' do
|
227
|
+
def test_association_proxy_transaction_method_starts_transaction_in_association_class
|
228
|
+
Tag.expects(:transaction)
|
229
|
+
Post.find(:first).tags.transaction do
|
230
|
+
# nothing
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
|
235
|
+
def test_has_many_association_through_a_belongs_to_association_where_the_association_doesnt_exist
|
236
|
+
author = authors(:mary)
|
237
|
+
post = Post.create!(:title => "TITLE", :body => "BODY")
|
238
|
+
assert_equal [], post.author_favorites
|
239
|
+
end
|
240
|
+
|
241
|
+
def test_has_many_association_through_a_belongs_to_association
|
242
|
+
author = authors(:mary)
|
243
|
+
post = Post.create!(:author => author, :title => "TITLE", :body => "BODY")
|
244
|
+
author.author_favorites.create(:favorite_author_id => 1)
|
245
|
+
author.author_favorites.create(:favorite_author_id => 2)
|
246
|
+
author.author_favorites.create(:favorite_author_id => 3)
|
247
|
+
assert_equal post.author.author_favorites, post.author_favorites
|
248
|
+
end
|
202
249
|
end
|
data/test/cases/base_test.rb
CHANGED
@@ -76,7 +76,7 @@ class TopicWithProtectedContentAndAccessibleAuthorName < ActiveRecord::Base
|
|
76
76
|
end
|
77
77
|
|
78
78
|
class BasicsTest < ActiveRecord::TestCase
|
79
|
-
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, :warehouse_things, :authors, :categorizations, :categories
|
79
|
+
fixtures :topics, :companies, :developers, :projects, :computers, :accounts, :minimalistics, :warehouse_things, :authors, :categorizations, :categories, :posts
|
80
80
|
|
81
81
|
def test_table_exists
|
82
82
|
assert !NonExistentTable.table_exists?
|
@@ -138,7 +138,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
138
138
|
if current_adapter?(:MysqlAdapter)
|
139
139
|
def test_read_attributes_before_type_cast_on_boolean
|
140
140
|
bool = Booleantest.create({ "value" => false })
|
141
|
-
assert_equal 0, bool.attributes_before_type_cast["value"]
|
141
|
+
assert_equal "0", bool.reload.attributes_before_type_cast["value"]
|
142
142
|
end
|
143
143
|
end
|
144
144
|
|
@@ -428,9 +428,6 @@ class BasicsTest < ActiveRecord::TestCase
|
|
428
428
|
end
|
429
429
|
|
430
430
|
def test_preserving_date_objects
|
431
|
-
# SQL Server doesn't have a separate column type just for dates, so all are returned as time
|
432
|
-
return true if current_adapter?(:SQLServerAdapter)
|
433
|
-
|
434
431
|
if current_adapter?(:SybaseAdapter, :OracleAdapter)
|
435
432
|
# Sybase ctlib does not (yet?) support the date type; use datetime instead.
|
436
433
|
# Oracle treats all dates/times as Time.
|
@@ -471,7 +468,19 @@ class BasicsTest < ActiveRecord::TestCase
|
|
471
468
|
topic.send(:approved=, true)
|
472
469
|
assert topic.instance_variable_get("@custom_approved")
|
473
470
|
end
|
474
|
-
|
471
|
+
|
472
|
+
def test_delete
|
473
|
+
topic = Topic.find(1)
|
474
|
+
assert_equal topic, topic.delete, 'topic.delete did not return self'
|
475
|
+
assert topic.frozen?, 'topic not frozen after delete'
|
476
|
+
assert_raise(ActiveRecord::RecordNotFound) { Topic.find(topic.id) }
|
477
|
+
end
|
478
|
+
|
479
|
+
def test_delete_doesnt_run_callbacks
|
480
|
+
Topic.find(1).delete
|
481
|
+
assert_not_nil Topic.find(2)
|
482
|
+
end
|
483
|
+
|
475
484
|
def test_destroy
|
476
485
|
topic = Topic.find(1)
|
477
486
|
assert_equal topic, topic.destroy, 'topic.destroy did not return self'
|
@@ -663,11 +672,22 @@ class BasicsTest < ActiveRecord::TestCase
|
|
663
672
|
assert_equal 1, Topic.update_all("content = 'bulk updated!'", nil, :limit => 1, :order => 'id DESC')
|
664
673
|
end
|
665
674
|
end
|
666
|
-
|
667
|
-
def
|
668
|
-
author =
|
675
|
+
|
676
|
+
def test_update_all_ignores_order_without_limit_from_association
|
677
|
+
author = authors(:david)
|
678
|
+
assert_nothing_raised do
|
679
|
+
assert_equal author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all([ "body = ?", "bulk update!" ])
|
680
|
+
end
|
681
|
+
end
|
682
|
+
|
683
|
+
def test_update_all_with_order_and_limit_updates_subset_only
|
684
|
+
author = authors(:david)
|
669
685
|
assert_nothing_raised do
|
670
|
-
assert_equal
|
686
|
+
assert_equal 1, author.posts_sorted_by_id_limited.size
|
687
|
+
assert_equal 2, author.posts_sorted_by_id_limited.find(:all, :limit => 2).size
|
688
|
+
assert_equal 1, author.posts_sorted_by_id_limited.update_all([ "body = ?", "bulk update!" ])
|
689
|
+
assert_equal "bulk update!", posts(:welcome).body
|
690
|
+
assert_not_equal "bulk update!", posts(:thinking).body
|
671
691
|
end
|
672
692
|
end
|
673
693
|
|
@@ -753,9 +773,9 @@ class BasicsTest < ActiveRecord::TestCase
|
|
753
773
|
assert_equal 3, test.test_int
|
754
774
|
end
|
755
775
|
end
|
756
|
-
|
757
|
-
# Oracle,
|
758
|
-
unless current_adapter?(:
|
776
|
+
|
777
|
+
# Oracle, and Sybase do not have a TIME datatype.
|
778
|
+
unless current_adapter?(:OracleAdapter, :SybaseAdapter)
|
759
779
|
def test_utc_as_time_zone
|
760
780
|
Topic.default_timezone = :utc
|
761
781
|
attributes = { "bonus_time" => "5:42:00AM" }
|
@@ -808,7 +828,21 @@ class BasicsTest < ActiveRecord::TestCase
|
|
808
828
|
def test_hashing
|
809
829
|
assert_equal [ Topic.find(1) ], [ Topic.find(2).topic ] & [ Topic.find(1) ]
|
810
830
|
end
|
811
|
-
|
831
|
+
|
832
|
+
def test_delete_new_record
|
833
|
+
client = Client.new
|
834
|
+
client.delete
|
835
|
+
assert client.frozen?
|
836
|
+
end
|
837
|
+
|
838
|
+
def test_delete_record_with_associations
|
839
|
+
client = Client.find(3)
|
840
|
+
client.delete
|
841
|
+
assert client.frozen?
|
842
|
+
assert_kind_of Firm, client.firm
|
843
|
+
assert_raises(ActiveSupport::FrozenObjectError) { client.name = "something else" }
|
844
|
+
end
|
845
|
+
|
812
846
|
def test_destroy_new_record
|
813
847
|
client = Client.new
|
814
848
|
client.destroy
|
@@ -880,7 +914,7 @@ class BasicsTest < ActiveRecord::TestCase
|
|
880
914
|
|
881
915
|
def test_mass_assignment_protection_against_class_attribute_writers
|
882
916
|
[:logger, :configurations, :primary_key_prefix_type, :table_name_prefix, :table_name_suffix, :pluralize_table_names, :colorize_logging,
|
883
|
-
:default_timezone, :
|
917
|
+
:default_timezone, :schema_format, :lock_optimistically, :record_timestamps].each do |method|
|
884
918
|
assert Task.respond_to?(method)
|
885
919
|
assert Task.respond_to?("#{method}=")
|
886
920
|
assert Task.new.respond_to?(method)
|
@@ -903,7 +937,15 @@ class BasicsTest < ActiveRecord::TestCase
|
|
903
937
|
keyboard = Keyboard.new(:id => 9, :name => 'nice try')
|
904
938
|
assert_nil keyboard.id
|
905
939
|
end
|
906
|
-
|
940
|
+
|
941
|
+
def test_mass_assigning_invalid_attribute
|
942
|
+
firm = Firm.new
|
943
|
+
|
944
|
+
assert_raises(ActiveRecord::UnknownAttributeError) do
|
945
|
+
firm.attributes = { "id" => 5, "type" => "Client", "i_dont_even_exist" => 20 }
|
946
|
+
end
|
947
|
+
end
|
948
|
+
|
907
949
|
def test_mass_assignment_protection_on_defaults
|
908
950
|
firm = Firm.new
|
909
951
|
firm.attributes = { "id" => 5, "type" => "Client" }
|
@@ -1112,9 +1154,9 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1112
1154
|
end
|
1113
1155
|
|
1114
1156
|
def test_attributes_on_dummy_time
|
1115
|
-
# Oracle,
|
1116
|
-
return true if current_adapter?(:
|
1117
|
-
|
1157
|
+
# Oracle, and Sybase do not have a TIME datatype.
|
1158
|
+
return true if current_adapter?(:OracleAdapter, :SybaseAdapter)
|
1159
|
+
|
1118
1160
|
attributes = {
|
1119
1161
|
"bonus_time" => "5:42:00AM"
|
1120
1162
|
}
|
@@ -1124,11 +1166,15 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1124
1166
|
end
|
1125
1167
|
|
1126
1168
|
def test_boolean
|
1169
|
+
b_nil = Booleantest.create({ "value" => nil })
|
1170
|
+
nil_id = b_nil.id
|
1127
1171
|
b_false = Booleantest.create({ "value" => false })
|
1128
1172
|
false_id = b_false.id
|
1129
1173
|
b_true = Booleantest.create({ "value" => true })
|
1130
1174
|
true_id = b_true.id
|
1131
|
-
|
1175
|
+
|
1176
|
+
b_nil = Booleantest.find(nil_id)
|
1177
|
+
assert_nil b_nil.value
|
1132
1178
|
b_false = Booleantest.find(false_id)
|
1133
1179
|
assert !b_false.value?
|
1134
1180
|
b_true = Booleantest.find(true_id)
|
@@ -1136,11 +1182,15 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1136
1182
|
end
|
1137
1183
|
|
1138
1184
|
def test_boolean_cast_from_string
|
1185
|
+
b_blank = Booleantest.create({ "value" => "" })
|
1186
|
+
blank_id = b_blank.id
|
1139
1187
|
b_false = Booleantest.create({ "value" => "0" })
|
1140
1188
|
false_id = b_false.id
|
1141
1189
|
b_true = Booleantest.create({ "value" => "1" })
|
1142
1190
|
true_id = b_true.id
|
1143
|
-
|
1191
|
+
|
1192
|
+
b_blank = Booleantest.find(blank_id)
|
1193
|
+
assert_nil b_blank.value
|
1144
1194
|
b_false = Booleantest.find(false_id)
|
1145
1195
|
assert !b_false.value?
|
1146
1196
|
b_true = Booleantest.find(true_id)
|
@@ -1383,6 +1433,12 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1383
1433
|
topic = Topic.create("content" => myobj).reload
|
1384
1434
|
assert_equal(myobj, topic.content)
|
1385
1435
|
end
|
1436
|
+
|
1437
|
+
def test_serialized_string_attribute
|
1438
|
+
myobj = "Yes"
|
1439
|
+
topic = Topic.create("content" => myobj).reload
|
1440
|
+
assert_equal(myobj, topic.content)
|
1441
|
+
end
|
1386
1442
|
|
1387
1443
|
def test_nil_serialized_attribute_with_class_constraint
|
1388
1444
|
myobj = MyObject.new('value1', 'value2')
|
@@ -1418,15 +1474,17 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1418
1474
|
|
1419
1475
|
if RUBY_VERSION < '1.9'
|
1420
1476
|
def test_quote_chars
|
1421
|
-
|
1422
|
-
|
1423
|
-
|
1424
|
-
|
1425
|
-
|
1426
|
-
|
1427
|
-
|
1428
|
-
|
1429
|
-
|
1477
|
+
with_kcode('UTF8') do
|
1478
|
+
str = 'The Narrator'
|
1479
|
+
topic = Topic.create(:author_name => str)
|
1480
|
+
assert_equal str, topic.author_name
|
1481
|
+
|
1482
|
+
assert_kind_of ActiveSupport::Multibyte.proxy_class, str.mb_chars
|
1483
|
+
topic = Topic.find_by_author_name(str.mb_chars)
|
1484
|
+
|
1485
|
+
assert_kind_of Topic, topic
|
1486
|
+
assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
|
1487
|
+
end
|
1430
1488
|
end
|
1431
1489
|
end
|
1432
1490
|
|
@@ -1582,8 +1640,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1582
1640
|
res5 = nil
|
1583
1641
|
assert_nothing_raised do
|
1584
1642
|
res5 = Post.count(:conditions => "p.#{QUOTED_TYPE} = 'Post' AND p.id=co.post_id",
|
1585
|
-
|
1586
|
-
|
1643
|
+
:joins => "p, comments co",
|
1644
|
+
:select => "p.id")
|
1587
1645
|
end
|
1588
1646
|
|
1589
1647
|
assert_equal res4, res5
|
@@ -1819,8 +1877,8 @@ class BasicsTest < ActiveRecord::TestCase
|
|
1819
1877
|
assert_equal nil, xml.elements["//parent-id"].text
|
1820
1878
|
assert_equal "integer", xml.elements["//parent-id"].attributes['type']
|
1821
1879
|
assert_equal "true", xml.elements["//parent-id"].attributes['nil']
|
1822
|
-
|
1823
|
-
if current_adapter?(:SybaseAdapter, :
|
1880
|
+
|
1881
|
+
if current_adapter?(:SybaseAdapter, :OracleAdapter)
|
1824
1882
|
assert_equal last_read_in_current_timezone, xml.elements["//last-read"].text
|
1825
1883
|
assert_equal "datetime" , xml.elements["//last-read"].attributes['type']
|
1826
1884
|
else
|
@@ -2019,4 +2077,18 @@ class BasicsTest < ActiveRecord::TestCase
|
|
2019
2077
|
ensure
|
2020
2078
|
ActiveRecord::Base.logger = original_logger
|
2021
2079
|
end
|
2080
|
+
|
2081
|
+
private
|
2082
|
+
def with_kcode(kcode)
|
2083
|
+
if RUBY_VERSION < '1.9'
|
2084
|
+
orig_kcode, $KCODE = $KCODE, kcode
|
2085
|
+
begin
|
2086
|
+
yield
|
2087
|
+
ensure
|
2088
|
+
$KCODE = orig_kcode
|
2089
|
+
end
|
2090
|
+
else
|
2091
|
+
yield
|
2092
|
+
end
|
2093
|
+
end
|
2022
2094
|
end
|
@@ -25,6 +25,11 @@ class CalculationsTest < ActiveRecord::TestCase
|
|
25
25
|
def test_should_return_nil_as_average
|
26
26
|
assert_nil NumericData.average(:bank_balance)
|
27
27
|
end
|
28
|
+
|
29
|
+
def test_type_cast_calculated_value_should_convert_db_averages_of_fixnum_class_to_decimal
|
30
|
+
assert_equal 0, NumericData.send(:type_cast_calculated_value, 0, nil, 'avg')
|
31
|
+
assert_equal 53.0, NumericData.send(:type_cast_calculated_value, 53, nil, 'avg')
|
32
|
+
end
|
28
33
|
|
29
34
|
def test_should_get_maximum_of_field
|
30
35
|
assert_equal 60, Account.maximum(:credit_limit)
|
data/test/cases/finder_test.rb
CHANGED
@@ -12,6 +12,57 @@ require 'models/customer'
|
|
12
12
|
require 'models/job'
|
13
13
|
require 'models/categorization'
|
14
14
|
|
15
|
+
class DynamicFinderMatchTest < ActiveRecord::TestCase
|
16
|
+
def test_find_no_match
|
17
|
+
assert_nil ActiveRecord::DynamicFinderMatch.match("not_a_finder")
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_find_by
|
21
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_by_age_and_sex_and_location")
|
22
|
+
assert_not_nil match
|
23
|
+
assert match.finder?
|
24
|
+
assert_equal :first, match.finder
|
25
|
+
assert_equal %w(age sex location), match.attribute_names
|
26
|
+
end
|
27
|
+
|
28
|
+
def find_by_bang
|
29
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_by_age_and_sex_and_location!")
|
30
|
+
assert_not_nil match
|
31
|
+
assert match.finder?
|
32
|
+
assert match.bang?
|
33
|
+
assert_equal :first, match.finder
|
34
|
+
assert_equal %w(age sex location), match.attribute_names
|
35
|
+
end
|
36
|
+
|
37
|
+
def test_find_all_by
|
38
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_all_by_age_and_sex_and_location")
|
39
|
+
assert_not_nil match
|
40
|
+
assert match.finder?
|
41
|
+
assert_equal :all, match.finder
|
42
|
+
assert_equal %w(age sex location), match.attribute_names
|
43
|
+
end
|
44
|
+
|
45
|
+
def test_find_or_initialize_by
|
46
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_or_initialize_by_age_and_sex_and_location")
|
47
|
+
assert_not_nil match
|
48
|
+
assert !match.finder?
|
49
|
+
assert match.instantiator?
|
50
|
+
assert_equal :first, match.finder
|
51
|
+
assert_equal :new, match.instantiator
|
52
|
+
assert_equal %w(age sex location), match.attribute_names
|
53
|
+
end
|
54
|
+
|
55
|
+
def test_find_or_create_by
|
56
|
+
match = ActiveRecord::DynamicFinderMatch.match("find_or_create_by_age_and_sex_and_location")
|
57
|
+
assert_not_nil match
|
58
|
+
assert !match.finder?
|
59
|
+
assert match.instantiator?
|
60
|
+
assert_equal :first, match.finder
|
61
|
+
assert_equal :create, match.instantiator
|
62
|
+
assert_equal %w(age sex location), match.attribute_names
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
15
66
|
class FinderTest < ActiveRecord::TestCase
|
16
67
|
fixtures :companies, :topics, :entrants, :developers, :developers_projects, :posts, :comments, :accounts, :authors, :customers
|
17
68
|
|
@@ -117,7 +168,13 @@ class FinderTest < ActiveRecord::TestCase
|
|
117
168
|
assert_equal(1, developers.size)
|
118
169
|
assert_equal("fixture_3", developers.first.name)
|
119
170
|
end
|
120
|
-
|
171
|
+
|
172
|
+
def test_find_with_group
|
173
|
+
developers = Developer.find(:all, :group => "salary", :select => "salary")
|
174
|
+
assert_equal 4, developers.size
|
175
|
+
assert_equal 4, developers.map(&:salary).uniq.size
|
176
|
+
end
|
177
|
+
|
121
178
|
def test_find_with_entire_select_statement
|
122
179
|
topics = Topic.find_by_sql "SELECT * FROM topics WHERE author_name = 'Mary'"
|
123
180
|
|
@@ -199,7 +256,24 @@ class FinderTest < ActiveRecord::TestCase
|
|
199
256
|
assert Topic.find(1, :conditions => { 'topics.approved' => false })
|
200
257
|
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => { 'topics.approved' => true }) }
|
201
258
|
end
|
202
|
-
|
259
|
+
|
260
|
+
def test_find_on_hash_conditions_with_hashed_table_name
|
261
|
+
assert Topic.find(1, :conditions => {:topics => { :approved => false }})
|
262
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find(1, :conditions => {:topics => { :approved => true }}) }
|
263
|
+
end
|
264
|
+
|
265
|
+
def test_find_with_hash_conditions_on_joined_table
|
266
|
+
firms = Firm.all :joins => :account, :conditions => {:accounts => { :credit_limit => 50 }}
|
267
|
+
assert_equal 1, firms.size
|
268
|
+
assert_equal companies(:first_firm), firms.first
|
269
|
+
end
|
270
|
+
|
271
|
+
def test_find_with_hash_conditions_on_joined_table_and_with_range
|
272
|
+
firms = DependentFirm.all :joins => :account, :conditions => {:name => 'RailsCore', :accounts => { :credit_limit => 55..60 }}
|
273
|
+
assert_equal 1, firms.size
|
274
|
+
assert_equal companies(:rails_core), firms.first
|
275
|
+
end
|
276
|
+
|
203
277
|
def test_find_on_hash_conditions_with_explicit_table_name_and_aggregate
|
204
278
|
david = customers(:david)
|
205
279
|
assert Customer.find(david.id, :conditions => { 'customers.name' => david.name, :address => david.address })
|
@@ -387,12 +461,13 @@ class FinderTest < ActiveRecord::TestCase
|
|
387
461
|
assert_equal ActiveRecord::Base.connection.quote(''), bind('?', '')
|
388
462
|
end
|
389
463
|
|
390
|
-
def
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
assert_equal
|
464
|
+
def test_bind_chars
|
465
|
+
quoted_bambi = ActiveRecord::Base.connection.quote("Bambi")
|
466
|
+
quoted_bambi_and_thumper = ActiveRecord::Base.connection.quote("Bambi\nand\nThumper")
|
467
|
+
assert_equal "name=#{quoted_bambi}", bind('name=?', "Bambi")
|
468
|
+
assert_equal "name=#{quoted_bambi_and_thumper}", bind('name=?', "Bambi\nand\nThumper")
|
469
|
+
assert_equal "name=#{quoted_bambi}", bind('name=?', "Bambi".mb_chars)
|
470
|
+
assert_equal "name=#{quoted_bambi_and_thumper}", bind('name=?', "Bambi\nand\nThumper".mb_chars)
|
396
471
|
end
|
397
472
|
|
398
473
|
def test_bind_record
|
@@ -425,12 +500,34 @@ class FinderTest < ActiveRecord::TestCase
|
|
425
500
|
assert_equal(1, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 2]))
|
426
501
|
assert_equal(2, Entrant.count_by_sql(["SELECT COUNT(*) FROM entrants WHERE id > ?", 1]))
|
427
502
|
end
|
428
|
-
|
503
|
+
|
504
|
+
uses_mocha('test_dynamic_finder_should_go_through_the_find_class_method') do
|
505
|
+
def test_dynamic_finders_should_go_through_the_find_class_method
|
506
|
+
Topic.expects(:find).with(:first, :conditions => { :title => 'The First Topic!' })
|
507
|
+
Topic.find_by_title("The First Topic!")
|
508
|
+
|
509
|
+
Topic.expects(:find).with(:last, :conditions => { :title => 'The Last Topic!' })
|
510
|
+
Topic.find_last_by_title("The Last Topic!")
|
511
|
+
|
512
|
+
Topic.expects(:find).with(:all, :conditions => { :title => 'A Topic.' })
|
513
|
+
Topic.find_all_by_title("A Topic.")
|
514
|
+
|
515
|
+
Topic.expects(:find).with(:first, :conditions => { :title => 'Does not exist yet for sure!' }).times(2)
|
516
|
+
Topic.find_or_initialize_by_title('Does not exist yet for sure!')
|
517
|
+
Topic.find_or_create_by_title('Does not exist yet for sure!')
|
518
|
+
end
|
519
|
+
end
|
520
|
+
|
429
521
|
def test_find_by_one_attribute
|
430
522
|
assert_equal topics(:first), Topic.find_by_title("The First Topic")
|
431
523
|
assert_nil Topic.find_by_title("The First Topic!")
|
432
524
|
end
|
433
|
-
|
525
|
+
|
526
|
+
def test_find_by_one_attribute_bang
|
527
|
+
assert_equal topics(:first), Topic.find_by_title!("The First Topic")
|
528
|
+
assert_raises(ActiveRecord::RecordNotFound) { Topic.find_by_title!("The First Topic!") }
|
529
|
+
end
|
530
|
+
|
434
531
|
def test_find_by_one_attribute_caches_dynamic_finder
|
435
532
|
# ensure this test can run independently of order
|
436
533
|
class << Topic; self; end.send(:remove_method, :find_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_by_title' }
|
@@ -524,6 +621,38 @@ class FinderTest < ActiveRecord::TestCase
|
|
524
621
|
assert_nil Topic.find_by_title_and_author_name("The First Topic", "Mary")
|
525
622
|
end
|
526
623
|
|
624
|
+
def test_find_last_by_one_attribute
|
625
|
+
assert_equal Topic.last, Topic.find_last_by_title(Topic.last.title)
|
626
|
+
assert_nil Topic.find_last_by_title("A title with no matches")
|
627
|
+
end
|
628
|
+
|
629
|
+
def test_find_last_by_one_attribute_caches_dynamic_finder
|
630
|
+
# ensure this test can run independently of order
|
631
|
+
class << Topic; self; end.send(:remove_method, :find_last_by_title) if Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
632
|
+
assert !Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
633
|
+
t = Topic.find_last_by_title(Topic.last.title)
|
634
|
+
assert Topic.public_methods.any? { |m| m.to_s == 'find_last_by_title' }
|
635
|
+
end
|
636
|
+
|
637
|
+
def test_find_last_by_invalid_method_syntax
|
638
|
+
assert_raises(NoMethodError) { Topic.fail_to_find_last_by_title("The First Topic") }
|
639
|
+
assert_raises(NoMethodError) { Topic.find_last_by_title?("The First Topic") }
|
640
|
+
end
|
641
|
+
|
642
|
+
def test_find_last_by_one_attribute_with_several_options
|
643
|
+
assert_equal accounts(:signals37), Account.find_last_by_credit_limit(50, :order => 'id DESC', :conditions => ['id != ?', 3])
|
644
|
+
end
|
645
|
+
|
646
|
+
def test_find_last_by_one_missing_attribute
|
647
|
+
assert_raises(NoMethodError) { Topic.find_last_by_undertitle("The Last Topic!") }
|
648
|
+
end
|
649
|
+
|
650
|
+
def test_find_last_by_two_attributes
|
651
|
+
topic = Topic.last
|
652
|
+
assert_equal topic, Topic.find_last_by_title_and_author_name(topic.title, topic.author_name)
|
653
|
+
assert_nil Topic.find_last_by_title_and_author_name(topic.title, "Anonymous")
|
654
|
+
end
|
655
|
+
|
527
656
|
def test_find_all_by_one_attribute
|
528
657
|
topics = Topic.find_all_by_content("Have a nice day")
|
529
658
|
assert_equal 2, topics.size
|
@@ -717,7 +846,18 @@ class FinderTest < ActiveRecord::TestCase
|
|
717
846
|
assert c.valid?
|
718
847
|
assert !c.new_record?
|
719
848
|
end
|
720
|
-
|
849
|
+
|
850
|
+
def test_find_or_create_should_work_with_block_on_first_call
|
851
|
+
class << Company
|
852
|
+
undef_method(:find_or_create_by_name) if method_defined?(:find_or_create_by_name)
|
853
|
+
end
|
854
|
+
c = Company.find_or_create_by_name(:name => "Fortune 1000") { |f| f.rating = 1000 }
|
855
|
+
assert_equal "Fortune 1000", c.name
|
856
|
+
assert_equal 1000.to_f, c.rating.to_f
|
857
|
+
assert c.valid?
|
858
|
+
assert !c.new_record?
|
859
|
+
end
|
860
|
+
|
721
861
|
def test_dynamic_find_or_initialize_from_one_attribute_caches_method
|
722
862
|
class << Company; self; end.send(:remove_method, :find_or_initialize_by_name) if Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
723
863
|
assert !Company.public_methods.any? { |m| m.to_s == 'find_or_initialize_by_name' }
|
@@ -824,6 +964,17 @@ class FinderTest < ActiveRecord::TestCase
|
|
824
964
|
assert_equal 1, first.id
|
825
965
|
end
|
826
966
|
|
967
|
+
def test_joins_with_string_array
|
968
|
+
person_with_reader_and_post = Post.find(
|
969
|
+
:all,
|
970
|
+
:joins => [
|
971
|
+
"INNER JOIN categorizations ON categorizations.post_id = posts.id",
|
972
|
+
"INNER JOIN categories ON categories.id = categorizations.category_id AND categories.type = 'SpecialCategory'"
|
973
|
+
]
|
974
|
+
)
|
975
|
+
assert_equal 1, person_with_reader_and_post.size
|
976
|
+
end
|
977
|
+
|
827
978
|
def test_find_by_id_with_conditions_with_or
|
828
979
|
assert_nothing_raised do
|
829
980
|
Post.find([1,2,3],
|