ibm_db 1.0.0 → 1.0.1

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.
@@ -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],