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.
@@ -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
- end
710
- end
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
- posts(:thinking).people << people(:david)
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
@@ -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 test_update_all_ignores_order_limit_from_association
668
- author = Author.find(1)
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 author.posts_with_comments_and_categories.length, author.posts_with_comments_and_categories.update_all("body = 'bulk update!'")
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, SQLServer, and Sybase do not have a TIME datatype.
758
- unless current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
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, :allow_concurrency, :schema_format, :verification_timeout, :lock_optimistically, :record_timestamps].each do |method|
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, SQL Server, and Sybase do not have a TIME datatype.
1116
- return true if current_adapter?(:SQLServerAdapter, :OracleAdapter, :SybaseAdapter)
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
- str = 'The Narrator'
1422
- topic = Topic.create(:author_name => str)
1423
- assert_equal str, topic.author_name
1424
-
1425
- assert_kind_of ActiveSupport::Multibyte::Chars, str.chars
1426
- topic = Topic.find_by_author_name(str.chars)
1427
-
1428
- assert_kind_of Topic, topic
1429
- assert_equal str, topic.author_name, "The right topic should have been found by name even with name passed as Chars"
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
- :joins => "p, comments co",
1586
- :select => "p.id")
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, :SQLServerAdapter, :OracleAdapter)
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)
@@ -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 test_bind_string_with_nl
391
- assert_equal ActiveRecord::Base.connection.quote("a\nb"), bind('?', "a\nb")
392
- end
393
-
394
- def test_bind_mb_string_with_nl
395
- assert_equal ActiveRecord::Base.connection.quote("a\nb"), bind('?', "a\nb".chars)
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],