activerecord-spanner-adapter 0.3.0 → 1.0.0

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.
Files changed (282) hide show
  1. checksums.yaml +5 -5
  2. data/.github/CODEOWNERS +7 -0
  3. data/.github/sync-repo-settings.yaml +16 -0
  4. data/.github/workflows/acceptance-tests-on-emulator.yaml +45 -0
  5. data/.github/workflows/acceptance-tests-on-production.yaml +49 -0
  6. data/.github/workflows/ci.yaml +33 -0
  7. data/.github/workflows/nightly-acceptance-tests-on-emulator.yaml +52 -0
  8. data/.github/workflows/nightly-acceptance-tests-on-production.yaml +35 -0
  9. data/.github/workflows/nightly-unit-tests.yaml +40 -0
  10. data/.github/workflows/release-please-label.yml +25 -0
  11. data/.github/workflows/release-please.yml +39 -0
  12. data/.github/workflows/rubocop.yaml +31 -0
  13. data/.gitignore +67 -5
  14. data/.kokoro/populate-secrets.sh +77 -0
  15. data/.kokoro/release.cfg +33 -0
  16. data/.kokoro/release.sh +15 -0
  17. data/.kokoro/trampoline_v2.sh +489 -0
  18. data/.rubocop.yml +46 -0
  19. data/.toys/release.rb +18 -0
  20. data/.trampolinerc +48 -0
  21. data/.yardopts +11 -0
  22. data/CHANGELOG.md +55 -0
  23. data/CODE_OF_CONDUCT.md +40 -0
  24. data/CONTRIBUTING.md +79 -0
  25. data/Gemfile +9 -4
  26. data/LICENSE +6 -6
  27. data/README.md +66 -30
  28. data/Rakefile +79 -3
  29. data/SECURITY.md +7 -0
  30. data/acceptance/cases/associations/has_many_associations_test.rb +119 -0
  31. data/acceptance/cases/associations/has_many_through_associations_test.rb +63 -0
  32. data/acceptance/cases/associations/has_one_associations_test.rb +79 -0
  33. data/acceptance/cases/associations/has_one_through_associations_test.rb +98 -0
  34. data/acceptance/cases/interleaved_associations/has_many_associations_using_interleaved_test.rb +211 -0
  35. data/acceptance/cases/migration/change_schema_test.rb +433 -0
  36. data/acceptance/cases/migration/change_table_test.rb +115 -0
  37. data/acceptance/cases/migration/column_attributes_test.rb +122 -0
  38. data/acceptance/cases/migration/column_positioning_test.rb +48 -0
  39. data/acceptance/cases/migration/columns_test.rb +201 -0
  40. data/acceptance/cases/migration/command_recorder_test.rb +406 -0
  41. data/acceptance/cases/migration/create_join_table_test.rb +216 -0
  42. data/acceptance/cases/migration/ddl_batching_test.rb +80 -0
  43. data/acceptance/cases/migration/foreign_key_test.rb +297 -0
  44. data/acceptance/cases/migration/index_test.rb +211 -0
  45. data/acceptance/cases/migration/references_foreign_key_test.rb +259 -0
  46. data/acceptance/cases/migration/references_index_test.rb +135 -0
  47. data/acceptance/cases/migration/references_statements_test.rb +166 -0
  48. data/acceptance/cases/migration/rename_column_test.rb +96 -0
  49. data/acceptance/cases/models/calculation_query_test.rb +128 -0
  50. data/acceptance/cases/models/generated_column_test.rb +126 -0
  51. data/acceptance/cases/models/mutation_test.rb +122 -0
  52. data/acceptance/cases/models/query_test.rb +171 -0
  53. data/acceptance/cases/sessions/session_not_found_test.rb +121 -0
  54. data/acceptance/cases/transactions/optimistic_locking_test.rb +141 -0
  55. data/acceptance/cases/transactions/read_only_transactions_test.rb +130 -0
  56. data/acceptance/cases/transactions/read_write_transactions_test.rb +248 -0
  57. data/acceptance/cases/type/all_types_test.rb +172 -0
  58. data/acceptance/cases/type/binary_test.rb +59 -0
  59. data/acceptance/cases/type/boolean_test.rb +31 -0
  60. data/acceptance/cases/type/date_test.rb +32 -0
  61. data/acceptance/cases/type/date_time_test.rb +30 -0
  62. data/acceptance/cases/type/float_test.rb +27 -0
  63. data/acceptance/cases/type/integer_test.rb +44 -0
  64. data/acceptance/cases/type/json_test.rb +34 -0
  65. data/acceptance/cases/type/numeric_test.rb +27 -0
  66. data/acceptance/cases/type/string_test.rb +79 -0
  67. data/acceptance/cases/type/text_test.rb +30 -0
  68. data/acceptance/cases/type/time_test.rb +87 -0
  69. data/acceptance/models/account.rb +13 -0
  70. data/acceptance/models/address.rb +9 -0
  71. data/acceptance/models/album.rb +12 -0
  72. data/acceptance/models/all_types.rb +8 -0
  73. data/acceptance/models/author.rb +11 -0
  74. data/acceptance/models/club.rb +12 -0
  75. data/acceptance/models/comment.rb +9 -0
  76. data/acceptance/models/customer.rb +9 -0
  77. data/acceptance/models/department.rb +9 -0
  78. data/acceptance/models/firm.rb +10 -0
  79. data/acceptance/models/member.rb +13 -0
  80. data/acceptance/models/member_type.rb +9 -0
  81. data/acceptance/models/membership.rb +10 -0
  82. data/acceptance/models/organization.rb +9 -0
  83. data/acceptance/models/post.rb +10 -0
  84. data/acceptance/models/singer.rb +10 -0
  85. data/acceptance/models/track.rb +20 -0
  86. data/acceptance/models/transaction.rb +9 -0
  87. data/acceptance/schema/schema.rb +147 -0
  88. data/acceptance/test_helper.rb +261 -0
  89. data/activerecord-spanner-adapter.gemspec +32 -17
  90. data/assets/solidus-db.png +0 -0
  91. data/benchmarks/README.md +17 -0
  92. data/benchmarks/Rakefile +14 -0
  93. data/benchmarks/application.rb +308 -0
  94. data/benchmarks/config/database.yml +8 -0
  95. data/benchmarks/config/environment.rb +12 -0
  96. data/benchmarks/db/migrate/01_create_tables.rb +25 -0
  97. data/benchmarks/db/schema.rb +29 -0
  98. data/benchmarks/models/album.rb +9 -0
  99. data/benchmarks/models/singer.rb +9 -0
  100. data/bin/console +6 -7
  101. data/examples/rails/README.md +262 -0
  102. data/examples/snippets/README.md +29 -0
  103. data/examples/snippets/Rakefile +57 -0
  104. data/examples/snippets/array-data-type/README.md +45 -0
  105. data/examples/snippets/array-data-type/Rakefile +13 -0
  106. data/examples/snippets/array-data-type/application.rb +45 -0
  107. data/examples/snippets/array-data-type/config/database.yml +8 -0
  108. data/examples/snippets/array-data-type/db/migrate/01_create_tables.rb +24 -0
  109. data/examples/snippets/array-data-type/db/schema.rb +26 -0
  110. data/examples/snippets/array-data-type/db/seeds.rb +5 -0
  111. data/examples/snippets/array-data-type/models/entity_with_array_types.rb +18 -0
  112. data/examples/snippets/bin/create_emulator_instance.rb +18 -0
  113. data/examples/snippets/bulk-insert/README.md +21 -0
  114. data/examples/snippets/bulk-insert/Rakefile +13 -0
  115. data/examples/snippets/bulk-insert/application.rb +64 -0
  116. data/examples/snippets/bulk-insert/config/database.yml +8 -0
  117. data/examples/snippets/bulk-insert/db/migrate/01_create_tables.rb +21 -0
  118. data/examples/snippets/bulk-insert/db/schema.rb +26 -0
  119. data/examples/snippets/bulk-insert/db/seeds.rb +5 -0
  120. data/examples/snippets/bulk-insert/models/album.rb +9 -0
  121. data/examples/snippets/bulk-insert/models/singer.rb +9 -0
  122. data/examples/snippets/commit-timestamp/README.md +18 -0
  123. data/examples/snippets/commit-timestamp/Rakefile +13 -0
  124. data/examples/snippets/commit-timestamp/application.rb +53 -0
  125. data/examples/snippets/commit-timestamp/config/database.yml +8 -0
  126. data/examples/snippets/commit-timestamp/db/migrate/01_create_tables.rb +26 -0
  127. data/examples/snippets/commit-timestamp/db/schema.rb +29 -0
  128. data/examples/snippets/commit-timestamp/db/seeds.rb +5 -0
  129. data/examples/snippets/commit-timestamp/models/album.rb +9 -0
  130. data/examples/snippets/commit-timestamp/models/singer.rb +9 -0
  131. data/examples/snippets/config/environment.rb +21 -0
  132. data/examples/snippets/create-records/README.md +12 -0
  133. data/examples/snippets/create-records/Rakefile +13 -0
  134. data/examples/snippets/create-records/application.rb +42 -0
  135. data/examples/snippets/create-records/config/database.yml +8 -0
  136. data/examples/snippets/create-records/db/migrate/01_create_tables.rb +21 -0
  137. data/examples/snippets/create-records/db/schema.rb +26 -0
  138. data/examples/snippets/create-records/db/seeds.rb +5 -0
  139. data/examples/snippets/create-records/models/album.rb +9 -0
  140. data/examples/snippets/create-records/models/singer.rb +9 -0
  141. data/examples/snippets/date-data-type/README.md +19 -0
  142. data/examples/snippets/date-data-type/Rakefile +13 -0
  143. data/examples/snippets/date-data-type/application.rb +35 -0
  144. data/examples/snippets/date-data-type/config/database.yml +8 -0
  145. data/examples/snippets/date-data-type/db/migrate/01_create_tables.rb +20 -0
  146. data/examples/snippets/date-data-type/db/schema.rb +21 -0
  147. data/examples/snippets/date-data-type/db/seeds.rb +16 -0
  148. data/examples/snippets/date-data-type/models/singer.rb +8 -0
  149. data/examples/snippets/generated-column/README.md +41 -0
  150. data/examples/snippets/generated-column/Rakefile +13 -0
  151. data/examples/snippets/generated-column/application.rb +37 -0
  152. data/examples/snippets/generated-column/config/database.yml +8 -0
  153. data/examples/snippets/generated-column/db/migrate/01_create_tables.rb +23 -0
  154. data/examples/snippets/generated-column/db/schema.rb +21 -0
  155. data/examples/snippets/generated-column/db/seeds.rb +18 -0
  156. data/examples/snippets/generated-column/models/singer.rb +8 -0
  157. data/examples/snippets/hints/README.md +19 -0
  158. data/examples/snippets/hints/Rakefile +13 -0
  159. data/examples/snippets/hints/application.rb +47 -0
  160. data/examples/snippets/hints/config/database.yml +8 -0
  161. data/examples/snippets/hints/db/migrate/01_create_tables.rb +23 -0
  162. data/examples/snippets/hints/db/schema.rb +28 -0
  163. data/examples/snippets/hints/db/seeds.rb +29 -0
  164. data/examples/snippets/hints/models/album.rb +9 -0
  165. data/examples/snippets/hints/models/singer.rb +9 -0
  166. data/examples/snippets/migrations/README.md +43 -0
  167. data/examples/snippets/migrations/Rakefile +13 -0
  168. data/examples/snippets/migrations/application.rb +26 -0
  169. data/examples/snippets/migrations/config/database.yml +8 -0
  170. data/examples/snippets/migrations/db/migrate/01_create_tables.rb +28 -0
  171. data/examples/snippets/migrations/db/schema.rb +33 -0
  172. data/examples/snippets/migrations/db/seeds.rb +5 -0
  173. data/examples/snippets/migrations/models/album.rb +10 -0
  174. data/examples/snippets/migrations/models/singer.rb +10 -0
  175. data/examples/snippets/migrations/models/track.rb +9 -0
  176. data/examples/snippets/mutations/README.md +34 -0
  177. data/examples/snippets/mutations/Rakefile +13 -0
  178. data/examples/snippets/mutations/application.rb +47 -0
  179. data/examples/snippets/mutations/config/database.yml +8 -0
  180. data/examples/snippets/mutations/db/migrate/01_create_tables.rb +22 -0
  181. data/examples/snippets/mutations/db/schema.rb +27 -0
  182. data/examples/snippets/mutations/db/seeds.rb +25 -0
  183. data/examples/snippets/mutations/models/album.rb +9 -0
  184. data/examples/snippets/mutations/models/singer.rb +9 -0
  185. data/examples/snippets/optimistic-locking/README.md +12 -0
  186. data/examples/snippets/optimistic-locking/Rakefile +13 -0
  187. data/examples/snippets/optimistic-locking/application.rb +48 -0
  188. data/examples/snippets/optimistic-locking/config/database.yml +8 -0
  189. data/examples/snippets/optimistic-locking/db/migrate/01_create_tables.rb +26 -0
  190. data/examples/snippets/optimistic-locking/db/schema.rb +29 -0
  191. data/examples/snippets/optimistic-locking/db/seeds.rb +25 -0
  192. data/examples/snippets/optimistic-locking/models/album.rb +9 -0
  193. data/examples/snippets/optimistic-locking/models/singer.rb +9 -0
  194. data/examples/snippets/partitioned-dml/README.md +16 -0
  195. data/examples/snippets/partitioned-dml/Rakefile +13 -0
  196. data/examples/snippets/partitioned-dml/application.rb +48 -0
  197. data/examples/snippets/partitioned-dml/config/database.yml +8 -0
  198. data/examples/snippets/partitioned-dml/db/migrate/01_create_tables.rb +21 -0
  199. data/examples/snippets/partitioned-dml/db/schema.rb +26 -0
  200. data/examples/snippets/partitioned-dml/db/seeds.rb +29 -0
  201. data/examples/snippets/partitioned-dml/models/album.rb +9 -0
  202. data/examples/snippets/partitioned-dml/models/singer.rb +9 -0
  203. data/examples/snippets/quickstart/README.md +26 -0
  204. data/examples/snippets/quickstart/Rakefile +13 -0
  205. data/examples/snippets/quickstart/application.rb +51 -0
  206. data/examples/snippets/quickstart/config/database.yml +8 -0
  207. data/examples/snippets/quickstart/db/migrate/01_create_tables.rb +21 -0
  208. data/examples/snippets/quickstart/db/schema.rb +26 -0
  209. data/examples/snippets/quickstart/db/seeds.rb +24 -0
  210. data/examples/snippets/quickstart/models/album.rb +9 -0
  211. data/examples/snippets/quickstart/models/singer.rb +9 -0
  212. data/examples/snippets/read-only-transactions/README.md +13 -0
  213. data/examples/snippets/read-only-transactions/Rakefile +13 -0
  214. data/examples/snippets/read-only-transactions/application.rb +77 -0
  215. data/examples/snippets/read-only-transactions/config/database.yml +8 -0
  216. data/examples/snippets/read-only-transactions/db/migrate/01_create_tables.rb +21 -0
  217. data/examples/snippets/read-only-transactions/db/schema.rb +26 -0
  218. data/examples/snippets/read-only-transactions/db/seeds.rb +24 -0
  219. data/examples/snippets/read-only-transactions/models/album.rb +9 -0
  220. data/examples/snippets/read-only-transactions/models/singer.rb +9 -0
  221. data/examples/snippets/read-write-transactions/README.md +12 -0
  222. data/examples/snippets/read-write-transactions/Rakefile +13 -0
  223. data/examples/snippets/read-write-transactions/application.rb +39 -0
  224. data/examples/snippets/read-write-transactions/config/database.yml +8 -0
  225. data/examples/snippets/read-write-transactions/db/migrate/01_create_tables.rb +22 -0
  226. data/examples/snippets/read-write-transactions/db/schema.rb +27 -0
  227. data/examples/snippets/read-write-transactions/db/seeds.rb +25 -0
  228. data/examples/snippets/read-write-transactions/models/album.rb +9 -0
  229. data/examples/snippets/read-write-transactions/models/singer.rb +9 -0
  230. data/examples/snippets/stale-reads/README.md +27 -0
  231. data/examples/snippets/stale-reads/Rakefile +13 -0
  232. data/examples/snippets/stale-reads/application.rb +63 -0
  233. data/examples/snippets/stale-reads/config/database.yml +8 -0
  234. data/examples/snippets/stale-reads/db/migrate/01_create_tables.rb +21 -0
  235. data/examples/snippets/stale-reads/db/schema.rb +26 -0
  236. data/examples/snippets/stale-reads/db/seeds.rb +24 -0
  237. data/examples/snippets/stale-reads/models/album.rb +9 -0
  238. data/examples/snippets/stale-reads/models/singer.rb +9 -0
  239. data/examples/snippets/timestamp-data-type/README.md +17 -0
  240. data/examples/snippets/timestamp-data-type/Rakefile +13 -0
  241. data/examples/snippets/timestamp-data-type/application.rb +42 -0
  242. data/examples/snippets/timestamp-data-type/config/database.yml +8 -0
  243. data/examples/snippets/timestamp-data-type/db/migrate/01_create_tables.rb +21 -0
  244. data/examples/snippets/timestamp-data-type/db/schema.rb +21 -0
  245. data/examples/snippets/timestamp-data-type/db/seeds.rb +6 -0
  246. data/examples/snippets/timestamp-data-type/models/meeting.rb +19 -0
  247. data/examples/solidus/README.md +172 -0
  248. data/lib/active_record/connection_adapters/spanner/database_statements.rb +244 -266
  249. data/lib/active_record/connection_adapters/spanner/quoting.rb +42 -50
  250. data/lib/active_record/connection_adapters/spanner/schema_cache.rb +43 -0
  251. data/lib/active_record/connection_adapters/spanner/schema_creation.rb +125 -9
  252. data/lib/active_record/connection_adapters/spanner/schema_definitions.rb +122 -0
  253. data/lib/active_record/connection_adapters/spanner/schema_dumper.rb +19 -0
  254. data/lib/active_record/connection_adapters/spanner/schema_statements.rb +553 -139
  255. data/lib/active_record/connection_adapters/spanner/type_metadata.rb +37 -0
  256. data/lib/active_record/connection_adapters/spanner_adapter.rb +185 -78
  257. data/lib/active_record/tasks/spanner_database_tasks.rb +74 -0
  258. data/lib/active_record/type/spanner/array.rb +32 -0
  259. data/lib/active_record/type/spanner/bytes.rb +26 -0
  260. data/lib/active_record/type/spanner/spanner_active_record_converter.rb +33 -0
  261. data/lib/active_record/type/spanner/time.rb +37 -0
  262. data/lib/activerecord-spanner-adapter.rb +23 -0
  263. data/lib/activerecord_spanner_adapter/base.rb +238 -0
  264. data/lib/activerecord_spanner_adapter/connection.rb +350 -0
  265. data/lib/activerecord_spanner_adapter/errors.rb +13 -0
  266. data/lib/activerecord_spanner_adapter/foreign_key.rb +29 -0
  267. data/lib/activerecord_spanner_adapter/index/column.rb +38 -0
  268. data/lib/activerecord_spanner_adapter/index.rb +80 -0
  269. data/lib/activerecord_spanner_adapter/information_schema.rb +262 -0
  270. data/lib/activerecord_spanner_adapter/primary_key.rb +31 -0
  271. data/lib/activerecord_spanner_adapter/table/column.rb +59 -0
  272. data/lib/activerecord_spanner_adapter/table.rb +61 -0
  273. data/lib/activerecord_spanner_adapter/transaction.rb +154 -0
  274. data/lib/activerecord_spanner_adapter/version.rb +9 -0
  275. data/lib/arel/visitors/spanner.rb +111 -0
  276. data/lib/spanner_client_ext.rb +107 -0
  277. data/renovate.json +5 -0
  278. metadata +405 -34
  279. data/.travis.yml +0 -5
  280. data/lib/active_record/connection_adapters/spanner/client.rb +0 -190
  281. data/lib/active_record/connection_adapters/spanner.rb +0 -10
  282. data/lib/activerecord-spanner-adapter/version.rb +0 -3
@@ -0,0 +1,98 @@
1
+ # Copyright 2020 Google LLC
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+
7
+ # frozen_string_literal: true
8
+
9
+ require "test_helper"
10
+ require "models/member"
11
+ require "models/membership"
12
+ require "models/member_type"
13
+ require "models/club"
14
+
15
+ module ActiveRecord
16
+ module Associations
17
+ class HasOneThroughTest < SpannerAdapter::TestCase
18
+ include SpannerAdapter::Associations::TestHelper
19
+
20
+ attr_accessor :club, :member, :member_type
21
+
22
+ def setup
23
+ super
24
+
25
+ @club = Club.create name: "Club - 1"
26
+ @member_type = MemberType.create name: "MemberType - 1"
27
+ @member = Member.create name: "Member - 1"
28
+ end
29
+
30
+ def teardown
31
+ Member.destroy_all
32
+ Club.destroy_all
33
+ Membership.destroy_all
34
+ MemberType.destroy_all
35
+ end
36
+
37
+ def test_has_one_through
38
+ member.club = club
39
+ member.reload
40
+ assert_equal club, member.club
41
+ end
42
+
43
+ def test_creating_association_creates_through_record
44
+ member.club = club
45
+
46
+ assert_equal member.id, member.membership.member_id
47
+ assert_equal club.id, member.membership.club.id
48
+ assert_equal club, member.club
49
+ end
50
+
51
+ def test_set_record_to_nil_should_delete_association
52
+ member.club = club
53
+ member.reload
54
+ assert_equal club, member.club
55
+
56
+ member.club = nil
57
+ member.reload
58
+ assert_nil member.membership
59
+ assert_nil member.club
60
+ end
61
+
62
+ def test_set_record_after_delete_association
63
+ member.club = club
64
+ member.reload
65
+ assert_equal club, member.club
66
+
67
+ member.club = nil
68
+ member.reload
69
+ assert_nil member.membership
70
+ assert_nil member.club
71
+
72
+ club = Club.create name: "Club - 2"
73
+ member.club = club
74
+ member.reload
75
+ assert_equal club, member.club
76
+ end
77
+
78
+ def test_has_one_through_eager_loading
79
+ member.club = club
80
+
81
+ members = Member.includes(:club).all.to_a
82
+ assert_equal 1, members.size
83
+ assert_not_nil assert_no_queries { members[0].club }
84
+ end
85
+
86
+ def test_has_one_through_with_where_condition
87
+ member.favourite_club = club
88
+ membership = member.membership
89
+ membership.favourite = true
90
+ membership.save
91
+
92
+ member.reload
93
+
94
+ assert_equal member.favourite_club, club
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,211 @@
1
+ # Copyright 2021 Google LLC
2
+ #
3
+ # Use of this source code is governed by an MIT-style
4
+ # license that can be found in the LICENSE file or at
5
+ # https://opensource.org/licenses/MIT.
6
+
7
+ # frozen_string_literal: true
8
+
9
+ require "test_helper"
10
+ require "models/singer"
11
+ require "models/album"
12
+ require "models/track"
13
+
14
+ module ActiveRecord
15
+ module Associations
16
+ class HasManyUsingInterleavedTest < SpannerAdapter::TestCase
17
+ include SpannerAdapter::Associations::TestHelper
18
+
19
+ attr_accessor :singer, :album1, :album2
20
+
21
+ def setup
22
+ super
23
+
24
+ @singer = Singer.create first_name: "FirstName1", last_name: "LastName1"
25
+
26
+ @album2 = Album.create title: "Title2", singer: singer
27
+ @album1 = Album.create title: "Title1", singer: singer
28
+
29
+ @track2_1 = Track.create title: "Title2_1", album: album2, duration: 3.6
30
+ @track2_2 = Track.create title: "Title2_2", album: album2, duration: 3.3
31
+ @track1_1 = Track.create title: "Title1_1", album: album1, duration: 4.5
32
+ @track1_2 = Track.create title: "Title1_2", album: album1
33
+ end
34
+
35
+ def teardown
36
+ Album.destroy_all
37
+ Singer.destroy_all
38
+ end
39
+
40
+ def test_has_many
41
+ assert_equal 2, singer.albums.count
42
+ assert_equal singer.albums.pluck(:title).sort, %w[Title1 Title2]
43
+
44
+ assert_equal 4, singer.tracks.count
45
+ assert_equal singer.tracks.pluck(:title).sort, %w[Title1_1 Title1_2 Title2_1 Title2_2]
46
+
47
+ assert_equal 2, album1.tracks.count
48
+ assert_equal album1.tracks.pluck(:title).sort, %w[Title1_1 Title1_2]
49
+ assert_equal 2, album2.tracks.count
50
+ assert_equal album2.tracks.pluck(:title).sort, %w[Title2_1 Title2_2]
51
+ end
52
+
53
+ def test_finding_using_associated_fields
54
+ assert_equal Album.where(singerid: singer.id).to_a, singer.albums.to_a
55
+ assert_equal Track.where(singerid: singer.id).to_a, singer.tracks.to_a
56
+ end
57
+
58
+ def test_successful_build_association
59
+ album = singer.albums.build title: "New Title"
60
+ assert album.save
61
+
62
+ singer.reload
63
+ assert_equal album, singer.albums.find(album.id)
64
+ end
65
+
66
+ def test_successful_build_nested_association
67
+ track = album1.tracks.build title: "New Title", duration: 4.45
68
+ assert track.save
69
+
70
+ album1.reload
71
+ assert_equal track, album1.tracks.find(track.id)
72
+ end
73
+
74
+ def test_create_and_destroy_associated_records
75
+ singer2 = Singer.new first_name: "First", last_name: "Last"
76
+ singer2.albums.build title: "New Title 1"
77
+ singer2.albums.build title: "New Title 2"
78
+ singer2.save!
79
+
80
+ singer2.reload
81
+
82
+ assert_equal 2, singer2.albums.count
83
+ assert_equal 4, Album.count
84
+
85
+ singer2.albums.destroy_all
86
+ singer2.reload
87
+
88
+ assert_equal 0, singer2.albums.count
89
+ assert_equal 2, Album.count
90
+ end
91
+
92
+ def test_create_and_destroy_nested_associated_records
93
+ album3 = Album.new singer: singer, title: "Title 3"
94
+ album3.tracks.build title: "Title3_1", duration: 2.5, singer: singer
95
+ album3.tracks.build title: "Title3_2", singer: singer
96
+ album3.save!
97
+
98
+ album3.reload
99
+
100
+ assert_equal 2, album3.tracks.count
101
+ assert_equal 6, singer.tracks.count
102
+ assert_equal 6, Track.count
103
+
104
+ album3.tracks.destroy_all
105
+ album3.reload
106
+
107
+ assert_equal 0, album3.tracks.count
108
+ assert_equal 4, Track.count
109
+ end
110
+
111
+ def test_create_and_delete_associated_records
112
+ singer2 = Singer.new first_name: "First", last_name: "Last"
113
+ singer2.albums.build title: "Album - 11"
114
+ singer2.albums.build title: "Album - 12"
115
+ singer2.save!
116
+
117
+ singer2.reload
118
+
119
+ assert_equal 2, singer2.albums.count
120
+ assert_equal 4, Album.count
121
+
122
+ assert_equal 2, singer2.albums.delete_all
123
+ singer2.reload
124
+
125
+ assert_equal 0, singer2.albums.count
126
+ assert_equal 2, Album.count
127
+ end
128
+
129
+ def test_create_and_delete_nested_associated_records
130
+ album3 = Album.new title: "Album 3", singer: singer
131
+ album3.tracks.build title: "Track - 31", singer: singer
132
+ album3.tracks.build title: "Track - 32", singer: singer
133
+ album3.save!
134
+
135
+ album3.reload
136
+
137
+ assert_equal 2, album3.tracks.count
138
+ assert_equal 6, Track.count
139
+
140
+ assert_equal 2, album3.tracks.delete_all
141
+ album3.reload
142
+
143
+ assert_equal 0, album3.tracks.count
144
+ assert_equal 4, Track.count
145
+ end
146
+
147
+ def test_update_associated_records
148
+ count = singer.albums.update_all title: "Title - Update"
149
+ assert_equal singer.albums.count, count
150
+
151
+ singer.reload
152
+ singer.albums.each do |album|
153
+ assert_equal "Title - Update", album.title
154
+ end
155
+ end
156
+
157
+ def test_update_nested_associated_records
158
+ count = album1.tracks.update_all title: "Title - Update", duration: 6.626
159
+ assert_equal album1.tracks.count, count
160
+
161
+ album1.reload
162
+ album1.tracks.each do |track|
163
+ assert_equal "Title - Update", track.title
164
+ assert_equal 6.626, track.duration
165
+ end
166
+ end
167
+
168
+ def test_fetch_associated_record_with_order
169
+ albums = singer.albums.order title: :desc
170
+ assert_equal %w[Title2 Title1], albums.pluck(:title)
171
+
172
+ albums = singer.albums.order title: :asc
173
+ assert_equal %w[Title1 Title2], albums.pluck(:title)
174
+ end
175
+
176
+ def test_fetch_nested_associated_record_with_order
177
+ tracks = album1.tracks.order duration: :desc
178
+ assert_equal [4.5, nil], tracks.pluck(:duration)
179
+
180
+ tracks = album1.tracks.order duration: :asc
181
+ assert_equal [nil, 4.5], tracks.pluck(:duration)
182
+ end
183
+
184
+ def test_set_counter_cache
185
+ singer.tracks.create! title: "New Title 1", album: album1
186
+ singer.tracks.create! title: "New Title 2", album: album2
187
+
188
+ singer.reload
189
+ assert_equal 6, singer.tracks_count
190
+ end
191
+
192
+ def test_cascade_destroy
193
+ assert_equal 4, singer.tracks.count
194
+
195
+ assert album1.destroy
196
+
197
+ singer.reload
198
+ assert_equal 2, singer.tracks.count
199
+ end
200
+
201
+ def test_cascade_delete
202
+ assert_equal 4, singer.tracks.count
203
+
204
+ assert album1.delete
205
+
206
+ singer.reload
207
+ assert_equal 2, singer.tracks.count
208
+ end
209
+ end
210
+ end
211
+ end