active_cached_resource 0.0.1.pre

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 (340) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.rubocop.yml +22 -0
  4. data/.standard.yml +2 -0
  5. data/CHANGELOG.md +5 -0
  6. data/README.md +45 -0
  7. data/Rakefile +21 -0
  8. data/example/consumer/.dockerignore +41 -0
  9. data/example/consumer/.gitattributes +9 -0
  10. data/example/consumer/.gitignore +36 -0
  11. data/example/consumer/.kamal/hooks/docker-setup.sample +3 -0
  12. data/example/consumer/.kamal/hooks/post-deploy.sample +14 -0
  13. data/example/consumer/.kamal/hooks/post-proxy-reboot.sample +3 -0
  14. data/example/consumer/.kamal/hooks/pre-build.sample +51 -0
  15. data/example/consumer/.kamal/hooks/pre-connect.sample +47 -0
  16. data/example/consumer/.kamal/hooks/pre-deploy.sample +109 -0
  17. data/example/consumer/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  18. data/example/consumer/.kamal/secrets +17 -0
  19. data/example/consumer/Dockerfile +65 -0
  20. data/example/consumer/Gemfile +17 -0
  21. data/example/consumer/Rakefile +6 -0
  22. data/example/consumer/app/controllers/application_controller.rb +2 -0
  23. data/example/consumer/app/controllers/concerns/.keep +0 -0
  24. data/example/consumer/app/jobs/application_job.rb +7 -0
  25. data/example/consumer/app/mailers/application_mailer.rb +4 -0
  26. data/example/consumer/app/models/application_record.rb +3 -0
  27. data/example/consumer/app/models/concerns/.keep +0 -0
  28. data/example/consumer/app/models/person.rb +9 -0
  29. data/example/consumer/app/views/layouts/mailer.html.erb +13 -0
  30. data/example/consumer/app/views/layouts/mailer.text.erb +1 -0
  31. data/example/consumer/bin/brakeman +7 -0
  32. data/example/consumer/bin/bundle +109 -0
  33. data/example/consumer/bin/dev +2 -0
  34. data/example/consumer/bin/docker-entrypoint +14 -0
  35. data/example/consumer/bin/jobs +6 -0
  36. data/example/consumer/bin/kamal +27 -0
  37. data/example/consumer/bin/rails +4 -0
  38. data/example/consumer/bin/rake +4 -0
  39. data/example/consumer/bin/rubocop +8 -0
  40. data/example/consumer/bin/setup +34 -0
  41. data/example/consumer/bin/thrust +5 -0
  42. data/example/consumer/config/application.rb +20 -0
  43. data/example/consumer/config/boot.rb +3 -0
  44. data/example/consumer/config/cache.yml +16 -0
  45. data/example/consumer/config/credentials.yml.enc +1 -0
  46. data/example/consumer/config/database.yml +14 -0
  47. data/example/consumer/config/deploy.yml +116 -0
  48. data/example/consumer/config/environment.rb +5 -0
  49. data/example/consumer/config/environments/development.rb +64 -0
  50. data/example/consumer/config/environments/production.rb +85 -0
  51. data/example/consumer/config/environments/test.rb +50 -0
  52. data/example/consumer/config/initializers/cors.rb +16 -0
  53. data/example/consumer/config/initializers/filter_parameter_logging.rb +8 -0
  54. data/example/consumer/config/initializers/inflections.rb +16 -0
  55. data/example/consumer/config/locales/en.yml +31 -0
  56. data/example/consumer/config/puma.rb +41 -0
  57. data/example/consumer/config/queue.yml +18 -0
  58. data/example/consumer/config/recurring.yml +10 -0
  59. data/example/consumer/config/routes.rb +10 -0
  60. data/example/consumer/config.ru +6 -0
  61. data/example/consumer/db/cache_schema.rb +14 -0
  62. data/example/consumer/db/queue_schema.rb +129 -0
  63. data/example/consumer/db/seeds.rb +0 -0
  64. data/example/consumer/lib/tasks/.keep +0 -0
  65. data/example/consumer/log/.keep +0 -0
  66. data/example/consumer/public/robots.txt +1 -0
  67. data/example/consumer/script/.keep +0 -0
  68. data/example/consumer/storage/.keep +0 -0
  69. data/example/consumer/tmp/.keep +0 -0
  70. data/example/consumer/tmp/cache/.keep +0 -0
  71. data/example/consumer/tmp/pids/.keep +0 -0
  72. data/example/consumer/tmp/storage/.keep +0 -0
  73. data/example/consumer/vendor/.keep +0 -0
  74. data/example/provider/.dockerignore +41 -0
  75. data/example/provider/.gitattributes +9 -0
  76. data/example/provider/.gitignore +32 -0
  77. data/example/provider/.kamal/hooks/docker-setup.sample +3 -0
  78. data/example/provider/.kamal/hooks/post-deploy.sample +14 -0
  79. data/example/provider/.kamal/hooks/post-proxy-reboot.sample +3 -0
  80. data/example/provider/.kamal/hooks/pre-build.sample +51 -0
  81. data/example/provider/.kamal/hooks/pre-connect.sample +47 -0
  82. data/example/provider/.kamal/hooks/pre-deploy.sample +109 -0
  83. data/example/provider/.kamal/hooks/pre-proxy-reboot.sample +3 -0
  84. data/example/provider/.kamal/secrets +17 -0
  85. data/example/provider/Dockerfile +65 -0
  86. data/example/provider/Gemfile +14 -0
  87. data/example/provider/Rakefile +6 -0
  88. data/example/provider/app/controllers/application_controller.rb +2 -0
  89. data/example/provider/app/controllers/concerns/.keep +0 -0
  90. data/example/provider/app/controllers/people_controller.rb +68 -0
  91. data/example/provider/app/jobs/application_job.rb +7 -0
  92. data/example/provider/app/mailers/application_mailer.rb +4 -0
  93. data/example/provider/app/models/address.rb +3 -0
  94. data/example/provider/app/models/application_record.rb +3 -0
  95. data/example/provider/app/models/company.rb +3 -0
  96. data/example/provider/app/models/concerns/.keep +0 -0
  97. data/example/provider/app/models/person.rb +6 -0
  98. data/example/provider/app/views/layouts/mailer.html.erb +13 -0
  99. data/example/provider/app/views/layouts/mailer.text.erb +1 -0
  100. data/example/provider/bin/brakeman +7 -0
  101. data/example/provider/bin/bundle +109 -0
  102. data/example/provider/bin/dev +2 -0
  103. data/example/provider/bin/docker-entrypoint +14 -0
  104. data/example/provider/bin/jobs +6 -0
  105. data/example/provider/bin/kamal +27 -0
  106. data/example/provider/bin/rails +4 -0
  107. data/example/provider/bin/rake +4 -0
  108. data/example/provider/bin/rubocop +8 -0
  109. data/example/provider/bin/setup +34 -0
  110. data/example/provider/bin/thrust +5 -0
  111. data/example/provider/config/application.rb +44 -0
  112. data/example/provider/config/boot.rb +3 -0
  113. data/example/provider/config/cache.yml +16 -0
  114. data/example/provider/config/credentials.yml.enc +1 -0
  115. data/example/provider/config/database.yml +20 -0
  116. data/example/provider/config/deploy.yml +116 -0
  117. data/example/provider/config/environment.rb +5 -0
  118. data/example/provider/config/environments/development.rb +64 -0
  119. data/example/provider/config/environments/production.rb +85 -0
  120. data/example/provider/config/environments/test.rb +50 -0
  121. data/example/provider/config/initializers/cors.rb +16 -0
  122. data/example/provider/config/initializers/filter_parameter_logging.rb +8 -0
  123. data/example/provider/config/initializers/inflections.rb +16 -0
  124. data/example/provider/config/locales/en.yml +31 -0
  125. data/example/provider/config/puma.rb +41 -0
  126. data/example/provider/config/queue.yml +18 -0
  127. data/example/provider/config/recurring.yml +10 -0
  128. data/example/provider/config/routes.rb +4 -0
  129. data/example/provider/config.ru +6 -0
  130. data/example/provider/db/cache_schema.rb +14 -0
  131. data/example/provider/db/migrate/20241202183937_create_people.rb +11 -0
  132. data/example/provider/db/migrate/20241202183955_create_addresses.rb +13 -0
  133. data/example/provider/db/migrate/20241202184017_create_companies.rb +14 -0
  134. data/example/provider/db/queue_schema.rb +129 -0
  135. data/example/provider/db/schema.rb +47 -0
  136. data/example/provider/db/seeds.rb +18 -0
  137. data/example/provider/lib/tasks/.keep +0 -0
  138. data/example/provider/log/.keep +0 -0
  139. data/example/provider/public/robots.txt +1 -0
  140. data/example/provider/script/.keep +0 -0
  141. data/example/provider/storage/.keep +0 -0
  142. data/example/provider/tmp/.keep +0 -0
  143. data/example/provider/tmp/pids/.keep +0 -0
  144. data/example/provider/tmp/storage/.keep +0 -0
  145. data/example/provider/vendor/.keep +0 -0
  146. data/lib/active_cached_resource/caching.rb +176 -0
  147. data/lib/active_cached_resource/caching_strategies/active_support_cache.rb +31 -0
  148. data/lib/active_cached_resource/caching_strategies/base.rb +114 -0
  149. data/lib/active_cached_resource/caching_strategies/sql_cache.rb +32 -0
  150. data/lib/active_cached_resource/configuration.rb +50 -0
  151. data/lib/active_cached_resource/logger.rb +22 -0
  152. data/lib/active_cached_resource/model.rb +33 -0
  153. data/lib/active_cached_resource/version.rb +12 -0
  154. data/lib/active_cached_resource.rb +64 -0
  155. data/lib/activeresource/.gitignore +15 -0
  156. data/lib/activeresource/README.md +283 -0
  157. data/lib/activeresource/examples/performance.rb +72 -0
  158. data/lib/activeresource/lib/active_resource/active_job_serializer.rb +26 -0
  159. data/lib/activeresource/lib/active_resource/associations/builder/association.rb +32 -0
  160. data/lib/activeresource/lib/active_resource/associations/builder/belongs_to.rb +16 -0
  161. data/lib/activeresource/lib/active_resource/associations/builder/has_many.rb +14 -0
  162. data/lib/activeresource/lib/active_resource/associations/builder/has_one.rb +14 -0
  163. data/lib/activeresource/lib/active_resource/associations.rb +175 -0
  164. data/lib/activeresource/lib/active_resource/base.rb +1741 -0
  165. data/lib/activeresource/lib/active_resource/callbacks.rb +22 -0
  166. data/lib/activeresource/lib/active_resource/collection.rb +214 -0
  167. data/lib/activeresource/lib/active_resource/connection.rb +298 -0
  168. data/lib/activeresource/lib/active_resource/custom_methods.rb +129 -0
  169. data/lib/activeresource/lib/active_resource/exceptions.rb +98 -0
  170. data/lib/activeresource/lib/active_resource/formats/json_format.rb +28 -0
  171. data/lib/activeresource/lib/active_resource/formats/xml_format.rb +27 -0
  172. data/lib/activeresource/lib/active_resource/formats.rb +24 -0
  173. data/lib/activeresource/lib/active_resource/http_mock.rb +386 -0
  174. data/lib/activeresource/lib/active_resource/inheriting_hash.rb +34 -0
  175. data/lib/activeresource/lib/active_resource/log_subscriber.rb +26 -0
  176. data/lib/activeresource/lib/active_resource/railtie.rb +31 -0
  177. data/lib/activeresource/lib/active_resource/reflection.rb +78 -0
  178. data/lib/activeresource/lib/active_resource/schema.rb +60 -0
  179. data/lib/activeresource/lib/active_resource/singleton.rb +111 -0
  180. data/lib/activeresource/lib/active_resource/threadsafe_attributes.rb +65 -0
  181. data/lib/activeresource/lib/active_resource/validations.rb +176 -0
  182. data/lib/activeresource/lib/active_resource.rb +49 -0
  183. data/lib/activeresource/lib/activeresource.rb +3 -0
  184. data/lib/activeresource/test/abstract_unit.rb +153 -0
  185. data/lib/activeresource/test/cases/active_job_serializer_test.rb +53 -0
  186. data/lib/activeresource/test/cases/association_test.rb +104 -0
  187. data/lib/activeresource/test/cases/associations/builder/belongs_to_test.rb +42 -0
  188. data/lib/activeresource/test/cases/associations/builder/has_many_test.rb +28 -0
  189. data/lib/activeresource/test/cases/associations/builder/has_one_test.rb +28 -0
  190. data/lib/activeresource/test/cases/authorization_test.rb +276 -0
  191. data/lib/activeresource/test/cases/base/custom_methods_test.rb +155 -0
  192. data/lib/activeresource/test/cases/base/equality_test.rb +53 -0
  193. data/lib/activeresource/test/cases/base/load_test.rb +249 -0
  194. data/lib/activeresource/test/cases/base/schema_test.rb +428 -0
  195. data/lib/activeresource/test/cases/base_errors_test.rb +129 -0
  196. data/lib/activeresource/test/cases/base_test.rb +1622 -0
  197. data/lib/activeresource/test/cases/callbacks_test.rb +155 -0
  198. data/lib/activeresource/test/cases/collection_test.rb +172 -0
  199. data/lib/activeresource/test/cases/connection_test.rb +357 -0
  200. data/lib/activeresource/test/cases/finder_test.rb +217 -0
  201. data/lib/activeresource/test/cases/format_test.rb +137 -0
  202. data/lib/activeresource/test/cases/http_mock_test.rb +213 -0
  203. data/lib/activeresource/test/cases/inheritence_test.rb +19 -0
  204. data/lib/activeresource/test/cases/inheriting_hash_test.rb +25 -0
  205. data/lib/activeresource/test/cases/log_subscriber_test.rb +63 -0
  206. data/lib/activeresource/test/cases/reflection_test.rb +65 -0
  207. data/lib/activeresource/test/cases/validations_test.rb +78 -0
  208. data/lib/activeresource/test/fixtures/address.rb +20 -0
  209. data/lib/activeresource/test/fixtures/beast.rb +16 -0
  210. data/lib/activeresource/test/fixtures/comment.rb +5 -0
  211. data/lib/activeresource/test/fixtures/customer.rb +5 -0
  212. data/lib/activeresource/test/fixtures/inventory.rb +14 -0
  213. data/lib/activeresource/test/fixtures/person.rb +15 -0
  214. data/lib/activeresource/test/fixtures/pet.rb +6 -0
  215. data/lib/activeresource/test/fixtures/post.rb +5 -0
  216. data/lib/activeresource/test/fixtures/product.rb +11 -0
  217. data/lib/activeresource/test/fixtures/project.rb +19 -0
  218. data/lib/activeresource/test/fixtures/proxy.rb +6 -0
  219. data/lib/activeresource/test/fixtures/sound.rb +11 -0
  220. data/lib/activeresource/test/fixtures/street_address.rb +6 -0
  221. data/lib/activeresource/test/fixtures/subscription_plan.rb +7 -0
  222. data/lib/activeresource/test/fixtures/weather.rb +21 -0
  223. data/lib/activeresource/test/setter_trap.rb +28 -0
  224. data/lib/activeresource/test/singleton_test.rb +138 -0
  225. data/lib/activeresource/test/threadsafe_attributes_test.rb +91 -0
  226. data/lib/generators/active_cached_resource/install_generator.rb +31 -0
  227. data/lib/generators/active_cached_resource/templates/migration.erb +16 -0
  228. data/sorbet/config +4 -0
  229. data/sorbet/rbi/annotations/.gitattributes +1 -0
  230. data/sorbet/rbi/annotations/activemodel.rbi +89 -0
  231. data/sorbet/rbi/annotations/activesupport.rbi +457 -0
  232. data/sorbet/rbi/annotations/minitest.rbi +119 -0
  233. data/sorbet/rbi/annotations/rainbow.rbi +269 -0
  234. data/sorbet/rbi/dsl/.gitattributes +1 -0
  235. data/sorbet/rbi/dsl/active_support/callbacks.rbi +21 -0
  236. data/sorbet/rbi/gems/.gitattributes +1 -0
  237. data/sorbet/rbi/gems/actioncable@8.0.0.rbi +252 -0
  238. data/sorbet/rbi/gems/actionmailbox@8.0.0.rbi +9 -0
  239. data/sorbet/rbi/gems/actionmailer@8.0.0.rbi +9 -0
  240. data/sorbet/rbi/gems/actionpack@8.0.0.rbi +20909 -0
  241. data/sorbet/rbi/gems/actiontext@8.0.0.rbi +9 -0
  242. data/sorbet/rbi/gems/actionview@8.0.0.rbi +16207 -0
  243. data/sorbet/rbi/gems/activejob@8.0.0.rbi +9 -0
  244. data/sorbet/rbi/gems/activemodel-serializers-xml@1.0.3.rbi +166 -0
  245. data/sorbet/rbi/gems/activemodel@8.0.0.rbi +6857 -0
  246. data/sorbet/rbi/gems/activerecord@8.0.0.rbi +42896 -0
  247. data/sorbet/rbi/gems/activeresource@6.1.4.rbi +3944 -0
  248. data/sorbet/rbi/gems/activestorage@8.0.0.rbi +9 -0
  249. data/sorbet/rbi/gems/activesupport@8.0.0.rbi +21251 -0
  250. data/sorbet/rbi/gems/ast@2.4.2.rbi +585 -0
  251. data/sorbet/rbi/gems/base64@0.2.0.rbi +509 -0
  252. data/sorbet/rbi/gems/benchmark@0.4.0.rbi +618 -0
  253. data/sorbet/rbi/gems/bigdecimal@3.1.8.rbi +78 -0
  254. data/sorbet/rbi/gems/builder@3.3.0.rbi +9 -0
  255. data/sorbet/rbi/gems/bump@0.10.0.rbi +169 -0
  256. data/sorbet/rbi/gems/byebug@11.1.3.rbi +3607 -0
  257. data/sorbet/rbi/gems/coderay@1.1.3.rbi +3427 -0
  258. data/sorbet/rbi/gems/concurrent-ruby@1.3.4.rbi +11645 -0
  259. data/sorbet/rbi/gems/connection_pool@2.4.1.rbi +9 -0
  260. data/sorbet/rbi/gems/crass@1.0.6.rbi +623 -0
  261. data/sorbet/rbi/gems/date@3.4.0.rbi +75 -0
  262. data/sorbet/rbi/gems/diff-lcs@1.5.1.rbi +1131 -0
  263. data/sorbet/rbi/gems/docile@1.4.1.rbi +377 -0
  264. data/sorbet/rbi/gems/drb@2.2.1.rbi +1347 -0
  265. data/sorbet/rbi/gems/erubi@1.13.0.rbi +150 -0
  266. data/sorbet/rbi/gems/globalid@1.2.1.rbi +9 -0
  267. data/sorbet/rbi/gems/i18n@1.14.6.rbi +2359 -0
  268. data/sorbet/rbi/gems/io-console@0.7.2.rbi +9 -0
  269. data/sorbet/rbi/gems/json@2.8.2.rbi +1901 -0
  270. data/sorbet/rbi/gems/language_server-protocol@3.17.0.3.rbi +14238 -0
  271. data/sorbet/rbi/gems/lint_roller@1.1.0.rbi +240 -0
  272. data/sorbet/rbi/gems/logger@1.6.1.rbi +920 -0
  273. data/sorbet/rbi/gems/loofah@2.23.1.rbi +1081 -0
  274. data/sorbet/rbi/gems/mail@2.8.1.rbi +9 -0
  275. data/sorbet/rbi/gems/marcel@1.0.4.rbi +9 -0
  276. data/sorbet/rbi/gems/method_source@1.1.0.rbi +304 -0
  277. data/sorbet/rbi/gems/mini_mime@1.1.5.rbi +9 -0
  278. data/sorbet/rbi/gems/minitest@5.25.2.rbi +1547 -0
  279. data/sorbet/rbi/gems/net-imap@0.5.1.rbi +9 -0
  280. data/sorbet/rbi/gems/net-pop@0.1.2.rbi +9 -0
  281. data/sorbet/rbi/gems/net-protocol@0.2.2.rbi +292 -0
  282. data/sorbet/rbi/gems/net-smtp@0.5.0.rbi +9 -0
  283. data/sorbet/rbi/gems/netrc@0.11.0.rbi +159 -0
  284. data/sorbet/rbi/gems/nio4r@2.7.4.rbi +9 -0
  285. data/sorbet/rbi/gems/nokogiri@1.16.7.rbi +7311 -0
  286. data/sorbet/rbi/gems/parallel@1.26.3.rbi +291 -0
  287. data/sorbet/rbi/gems/parser@3.3.6.0.rbi +5519 -0
  288. data/sorbet/rbi/gems/prism@1.2.0.rbi +39085 -0
  289. data/sorbet/rbi/gems/pry-byebug@3.10.1.rbi +1151 -0
  290. data/sorbet/rbi/gems/pry@0.14.2.rbi +10076 -0
  291. data/sorbet/rbi/gems/psych@5.2.0.rbi +1785 -0
  292. data/sorbet/rbi/gems/racc@1.8.1.rbi +162 -0
  293. data/sorbet/rbi/gems/rack-session@2.0.0.rbi +727 -0
  294. data/sorbet/rbi/gems/rack-test@2.1.0.rbi +747 -0
  295. data/sorbet/rbi/gems/rack@3.1.8.rbi +4905 -0
  296. data/sorbet/rbi/gems/rackup@2.2.1.rbi +230 -0
  297. data/sorbet/rbi/gems/rails-dom-testing@2.2.0.rbi +758 -0
  298. data/sorbet/rbi/gems/rails-html-sanitizer@1.6.0.rbi +785 -0
  299. data/sorbet/rbi/gems/rails@8.0.0.rbi +9 -0
  300. data/sorbet/rbi/gems/railties@8.0.0.rbi +6287 -0
  301. data/sorbet/rbi/gems/rainbow@3.1.1.rbi +403 -0
  302. data/sorbet/rbi/gems/rake@13.2.1.rbi +3091 -0
  303. data/sorbet/rbi/gems/rbi@0.2.1.rbi +4535 -0
  304. data/sorbet/rbi/gems/rdoc@6.8.1.rbi +12572 -0
  305. data/sorbet/rbi/gems/regexp_parser@2.9.2.rbi +3772 -0
  306. data/sorbet/rbi/gems/reline@0.5.12.rbi +2416 -0
  307. data/sorbet/rbi/gems/rexml@3.3.9.rbi +4858 -0
  308. data/sorbet/rbi/gems/rspec-core@3.13.2.rbi +11287 -0
  309. data/sorbet/rbi/gems/rspec-expectations@3.13.3.rbi +8183 -0
  310. data/sorbet/rbi/gems/rspec-mocks@3.13.2.rbi +5341 -0
  311. data/sorbet/rbi/gems/rspec-support@3.13.1.rbi +1630 -0
  312. data/sorbet/rbi/gems/rspec@3.13.0.rbi +83 -0
  313. data/sorbet/rbi/gems/rubocop-ast@1.36.1.rbi +7303 -0
  314. data/sorbet/rbi/gems/rubocop-performance@1.21.1.rbi +9 -0
  315. data/sorbet/rbi/gems/rubocop@1.65.1.rbi +58170 -0
  316. data/sorbet/rbi/gems/ruby-progressbar@1.13.0.rbi +1318 -0
  317. data/sorbet/rbi/gems/securerandom@0.3.2.rbi +395 -0
  318. data/sorbet/rbi/gems/simplecov-html@0.13.1.rbi +225 -0
  319. data/sorbet/rbi/gems/simplecov@0.22.0.rbi +2149 -0
  320. data/sorbet/rbi/gems/simplecov_json_formatter@0.1.4.rbi +9 -0
  321. data/sorbet/rbi/gems/spoom@1.5.0.rbi +4932 -0
  322. data/sorbet/rbi/gems/standard-custom@1.0.2.rbi +9 -0
  323. data/sorbet/rbi/gems/standard-performance@1.4.0.rbi +9 -0
  324. data/sorbet/rbi/gems/standard@1.40.0.rbi +929 -0
  325. data/sorbet/rbi/gems/stringio@3.1.2.rbi +9 -0
  326. data/sorbet/rbi/gems/tapioca@0.16.4.rbi +3597 -0
  327. data/sorbet/rbi/gems/thor@1.3.2.rbi +4378 -0
  328. data/sorbet/rbi/gems/timeout@0.4.2.rbi +151 -0
  329. data/sorbet/rbi/gems/tzinfo@2.0.6.rbi +5918 -0
  330. data/sorbet/rbi/gems/unicode-display_width@2.6.0.rbi +66 -0
  331. data/sorbet/rbi/gems/uri@1.0.2.rbi +2377 -0
  332. data/sorbet/rbi/gems/useragent@0.16.10.rbi +9 -0
  333. data/sorbet/rbi/gems/websocket-driver@0.7.6.rbi +9 -0
  334. data/sorbet/rbi/gems/websocket-extensions@0.1.5.rbi +9 -0
  335. data/sorbet/rbi/gems/yard-sorbet@0.9.0.rbi +435 -0
  336. data/sorbet/rbi/gems/yard@0.9.37.rbi +18504 -0
  337. data/sorbet/rbi/gems/zeitwerk@2.7.1.rbi +9 -0
  338. data/sorbet/tapioca/config.yml +13 -0
  339. data/sorbet/tapioca/require.rb +12 -0
  340. metadata +543 -0
@@ -0,0 +1,1622 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "abstract_unit"
4
+ require "fixtures/person"
5
+ require "fixtures/customer"
6
+ require "fixtures/street_address"
7
+ require "fixtures/sound"
8
+ require "fixtures/beast"
9
+ require "fixtures/proxy"
10
+ require "fixtures/address"
11
+ require "fixtures/subscription_plan"
12
+ require "fixtures/post"
13
+ require "fixtures/comment"
14
+ require "fixtures/product"
15
+ require "fixtures/inventory"
16
+ require "active_support/json"
17
+ require "active_support/core_ext/hash/conversions"
18
+ require "mocha/minitest"
19
+
20
+ class BaseTest < ActiveSupport::TestCase
21
+ def setup
22
+ setup_response # find me in abstract_unit
23
+ @original_person_site = Person.site
24
+ @original_person_proxy = Person.proxy
25
+ end
26
+
27
+ def teardown
28
+ Person.site = @original_person_site
29
+ Person.proxy = @original_person_proxy
30
+ end
31
+
32
+ ########################################################################
33
+ # Tests relating to setting up the API-connection configuration
34
+ ########################################################################
35
+
36
+ def test_site_accessor_accepts_uri_or_string_argument
37
+ site = URI.parse("http://localhost")
38
+
39
+ assert_nothing_raised { Person.site = "http://localhost" }
40
+ assert_equal site, Person.site
41
+
42
+ assert_nothing_raised { Person.site = site }
43
+ assert_equal site, Person.site
44
+ end
45
+
46
+ def test_should_use_site_prefix_and_credentials
47
+ assert_equal "http://foo:bar@beast.caboo.se", Forum.site.to_s
48
+ assert_equal "http://foo:bar@beast.caboo.se/forums/:forum_id", Topic.site.to_s
49
+ end
50
+
51
+ def test_site_variable_can_be_reset
52
+ actor = Class.new(ActiveResource::Base)
53
+ assert_nil actor.site
54
+ actor.site = "http://localhost:31337"
55
+ actor.site = nil
56
+ assert_nil actor.site
57
+ end
58
+
59
+ def test_proxy_accessor_accepts_uri_or_string_argument
60
+ proxy = URI.parse("http://localhost")
61
+
62
+ assert_nothing_raised { Person.proxy = "http://localhost" }
63
+ assert_equal proxy, Person.proxy
64
+
65
+ assert_nothing_raised { Person.proxy = proxy }
66
+ assert_equal proxy, Person.proxy
67
+ end
68
+
69
+ def test_should_use_proxy_prefix_and_credentials
70
+ assert_equal "http://user:password@proxy.local:3000", ProxyResource.proxy.to_s
71
+ end
72
+
73
+ def test_proxy_variable_can_be_reset
74
+ actor = Class.new(ActiveResource::Base)
75
+ assert_nil actor.site
76
+ actor.proxy = "http://localhost:31337"
77
+ actor.proxy = nil
78
+ assert_nil actor.site
79
+ end
80
+
81
+ def test_should_accept_setting_user
82
+ Forum.user = "david"
83
+ assert_equal("david", Forum.user)
84
+ assert_equal("david", Forum.connection.user)
85
+ end
86
+
87
+ def test_should_accept_setting_password
88
+ Forum.password = "test123"
89
+ assert_equal("test123", Forum.password)
90
+ assert_equal("test123", Forum.connection.password)
91
+ end
92
+
93
+ def test_should_accept_setting_bearer_token
94
+ Forum.bearer_token = "token123"
95
+ assert_equal("token123", Forum.bearer_token)
96
+ assert_equal("token123", Forum.connection.bearer_token)
97
+ end
98
+
99
+ def test_should_accept_setting_auth_type
100
+ Forum.auth_type = :digest
101
+ assert_equal(:digest, Forum.auth_type)
102
+ assert_equal(:digest, Forum.connection.auth_type)
103
+
104
+ Forum.auth_type = :bearer
105
+ assert_equal(:bearer, Forum.auth_type)
106
+ assert_equal(:bearer, Forum.connection.auth_type)
107
+ end
108
+
109
+ def test_should_accept_setting_timeout
110
+ Forum.timeout = 5
111
+ assert_equal(5, Forum.timeout)
112
+ assert_equal(5, Forum.connection.timeout)
113
+ end
114
+
115
+ def test_should_accept_setting_open_timeout
116
+ Forum.open_timeout = 5
117
+ assert_equal(5, Forum.open_timeout)
118
+ assert_equal(5, Forum.connection.open_timeout)
119
+ end
120
+
121
+ def test_should_accept_setting_read_timeout
122
+ Forum.read_timeout = 5
123
+ assert_equal(5, Forum.read_timeout)
124
+ assert_equal(5, Forum.connection.read_timeout)
125
+ end
126
+
127
+ def test_should_accept_setting_ssl_options
128
+ expected = { verify: 1 }
129
+ Forum.ssl_options = expected
130
+ assert_equal(expected, Forum.ssl_options)
131
+ assert_equal(expected, Forum.connection.ssl_options)
132
+ end
133
+
134
+ def test_user_variable_can_be_reset
135
+ actor = Class.new(ActiveResource::Base)
136
+ actor.site = "http://cinema"
137
+ assert_nil actor.user
138
+ actor.user = "username"
139
+ actor.user = nil
140
+ assert_nil actor.user
141
+ assert_nil actor.connection.user
142
+ end
143
+
144
+ def test_password_variable_can_be_reset
145
+ actor = Class.new(ActiveResource::Base)
146
+ actor.site = "http://cinema"
147
+ assert_nil actor.password
148
+ actor.password = "username"
149
+ actor.password = nil
150
+ assert_nil actor.password
151
+ assert_nil actor.connection.password
152
+ end
153
+
154
+ def test_bearer_token_variable_can_be_reset
155
+ actor = Class.new(ActiveResource::Base)
156
+ actor.site = "http://cinema"
157
+ assert_nil actor.bearer_token
158
+ actor.bearer_token = "token"
159
+ actor.bearer_token = nil
160
+ assert_nil actor.bearer_token
161
+ assert_nil actor.connection.bearer_token
162
+ end
163
+
164
+ def test_timeout_variable_can_be_reset
165
+ actor = Class.new(ActiveResource::Base)
166
+ actor.site = "http://cinema"
167
+ assert_nil actor.timeout
168
+ actor.timeout = 5
169
+ actor.timeout = nil
170
+ assert_nil actor.timeout
171
+ assert_nil actor.connection.timeout
172
+ end
173
+
174
+ def test_open_timeout_variable_can_be_reset
175
+ actor = Class.new(ActiveResource::Base)
176
+ actor.site = "http://cinema"
177
+ assert_nil actor.open_timeout
178
+ actor.open_timeout = 5
179
+ actor.open_timeout = nil
180
+ assert_nil actor.open_timeout
181
+ assert_nil actor.connection.open_timeout
182
+ end
183
+
184
+ def test_read_timeout_variable_can_be_reset
185
+ actor = Class.new(ActiveResource::Base)
186
+ actor.site = "http://cinema"
187
+ assert_nil actor.read_timeout
188
+ actor.read_timeout = 5
189
+ actor.read_timeout = nil
190
+ assert_nil actor.read_timeout
191
+ assert_nil actor.connection.read_timeout
192
+ end
193
+
194
+ def test_ssl_options_hash_can_be_reset
195
+ # SSL options are nil, resulting in an empty hash on the connection.
196
+ actor = Class.new(ActiveResource::Base)
197
+ actor.site = "https://cinema"
198
+ assert_nil actor.ssl_options
199
+ connection = actor.connection
200
+ assert_equal Hash.new, connection.ssl_options
201
+
202
+ # Setting SSL options wipes the connection.
203
+ actor.ssl_options = { foo: 5 }
204
+ assert_not_equal connection, actor.connection
205
+ connection = actor.connection
206
+ assert_equal 5, connection.ssl_options[:foo]
207
+
208
+ # Setting SSL options to nil also wipes the connection.
209
+ actor.ssl_options = nil
210
+ assert_not_equal connection, actor.connection
211
+ assert_equal Hash.new, actor.connection.ssl_options
212
+ end
213
+
214
+ def test_credentials_from_site_are_decoded
215
+ actor = Class.new(ActiveResource::Base)
216
+ actor.site = "http://my%40email.com:%31%32%33@cinema"
217
+ assert_equal("my@email.com", actor.user)
218
+ assert_equal("123", actor.password)
219
+ end
220
+
221
+ def test_site_reader_uses_superclass_site_until_written
222
+ # Superclass is Object so returns nil.
223
+ assert_nil ActiveResource::Base.site
224
+ assert_nil Class.new(ActiveResource::Base).site
225
+
226
+ # Subclass uses superclass site.
227
+ actor = Class.new(Person)
228
+ assert_equal Person.site, actor.site
229
+
230
+ # Subclass returns frozen superclass copy.
231
+ assert_not Person.site.frozen?
232
+ assert actor.site.frozen?
233
+
234
+ # Changing subclass site doesn't change superclass site.
235
+ actor.site = "http://localhost:31337"
236
+ assert_not_equal Person.site, actor.site
237
+
238
+ # Changed subclass site is not frozen.
239
+ assert_not actor.site.frozen?
240
+
241
+ # Changing superclass site doesn't overwrite subclass site.
242
+ Person.site = "http://somewhere.else"
243
+ assert_not_equal Person.site, actor.site
244
+
245
+ # Changing superclass site after subclassing changes subclass site.
246
+ jester = Class.new(actor)
247
+ actor.site = "http://nomad"
248
+ assert_equal actor.site, jester.site
249
+ assert jester.site.frozen?
250
+
251
+ # Subclasses are always equal to superclass site when not overridden
252
+ fruit = Class.new(ActiveResource::Base)
253
+ apple = Class.new(fruit)
254
+
255
+ fruit.site = "http://market"
256
+ assert_equal fruit.site, apple.site, "subclass did not adopt changes from parent class"
257
+
258
+ fruit.site = "http://supermarket"
259
+ assert_equal fruit.site, apple.site, "subclass did not adopt changes from parent class"
260
+ end
261
+
262
+ def test_proxy_reader_uses_superclass_site_until_written
263
+ # Superclass is Object so returns nil.
264
+ assert_nil ActiveResource::Base.proxy
265
+ assert_nil Class.new(ActiveResource::Base).proxy
266
+
267
+ Person.proxy = "http://proxy.local"
268
+
269
+ # Subclass uses superclass proxy.
270
+ actor = Class.new(Person)
271
+ assert_equal Person.proxy, actor.proxy
272
+
273
+ # Subclass returns frozen superclass copy.
274
+ assert_not Person.proxy.frozen?
275
+ assert actor.proxy.frozen?
276
+
277
+ # Changing subclass proxy doesn't change superclass site.
278
+ actor.proxy = "http://localhost:31337"
279
+ assert_not_equal Person.proxy, actor.proxy
280
+
281
+ # Changed subclass proxy is not frozen.
282
+ assert_not actor.proxy.frozen?
283
+
284
+ # Changing superclass proxy doesn't overwrite subclass site.
285
+ Person.proxy = "http://somewhere.else"
286
+ assert_not_equal Person.proxy, actor.proxy
287
+
288
+ # Changing superclass proxy after subclassing changes subclass site.
289
+ jester = Class.new(actor)
290
+ actor.proxy = "http://nomad"
291
+ assert_equal actor.proxy, jester.proxy
292
+ assert jester.proxy.frozen?
293
+
294
+ # Subclasses are always equal to superclass proxy when not overridden
295
+ fruit = Class.new(ActiveResource::Base)
296
+ apple = Class.new(fruit)
297
+
298
+ fruit.proxy = "http://market"
299
+ assert_equal fruit.proxy, apple.proxy, "subclass did not adopt changes from parent class"
300
+
301
+ fruit.proxy = "http://supermarket"
302
+ assert_equal fruit.proxy, apple.proxy, "subclass did not adopt changes from parent class"
303
+ end
304
+
305
+ def test_user_reader_uses_superclass_user_until_written
306
+ # Superclass is Object so returns nil.
307
+ assert_nil ActiveResource::Base.user
308
+ assert_nil Class.new(ActiveResource::Base).user
309
+ person_user = Person.user
310
+ Person.user = "anonymous".dup
311
+
312
+ # Subclass uses superclass user.
313
+ actor = Class.new(Person)
314
+ assert_equal Person.user, actor.user
315
+
316
+ # Subclass returns frozen superclass copy.
317
+ assert_not Person.user.frozen?
318
+ assert actor.user.frozen?
319
+
320
+ # Changing subclass user doesn't change superclass user.
321
+ actor.user = "david"
322
+ assert_not_equal Person.user, actor.user
323
+
324
+ # Changing superclass user doesn't overwrite subclass user.
325
+ Person.user = "john"
326
+ assert_not_equal Person.user, actor.user
327
+
328
+ # Changing superclass user after subclassing changes subclass user.
329
+ jester = Class.new(actor)
330
+ actor.user = "john.doe"
331
+ assert_equal actor.user, jester.user
332
+
333
+ # Subclasses are always equal to superclass user when not overridden
334
+ fruit = Class.new(ActiveResource::Base)
335
+ apple = Class.new(fruit)
336
+
337
+ fruit.user = "manager"
338
+ assert_equal fruit.user, apple.user, "subclass did not adopt changes from parent class"
339
+
340
+ fruit.user = "client"
341
+ assert_equal fruit.user, apple.user, "subclass did not adopt changes from parent class"
342
+ ensure
343
+ Person.user = person_user
344
+ end
345
+
346
+ def test_password_reader_uses_superclass_password_until_written
347
+ # Superclass is Object so returns nil.
348
+ assert_nil ActiveResource::Base.password
349
+ assert_nil Class.new(ActiveResource::Base).password
350
+ Person.password = "my-password".dup
351
+
352
+ # Subclass uses superclass password.
353
+ actor = Class.new(Person)
354
+ assert_equal Person.password, actor.password
355
+
356
+ # Subclass returns frozen superclass copy.
357
+ assert_not Person.password.frozen?
358
+ assert actor.password.frozen?
359
+
360
+ # Changing subclass password doesn't change superclass password.
361
+ actor.password = "secret"
362
+ assert_not_equal Person.password, actor.password
363
+
364
+ # Changing superclass password doesn't overwrite subclass password.
365
+ Person.password = "super-secret"
366
+ assert_not_equal Person.password, actor.password
367
+
368
+ # Changing superclass password after subclassing changes subclass password.
369
+ jester = Class.new(actor)
370
+ actor.password = "even-more-secret"
371
+ assert_equal actor.password, jester.password
372
+
373
+ # Subclasses are always equal to superclass password when not overridden
374
+ fruit = Class.new(ActiveResource::Base)
375
+ apple = Class.new(fruit)
376
+
377
+ fruit.password = "mega-secret"
378
+ assert_equal fruit.password, apple.password, "subclass did not adopt changes from parent class"
379
+
380
+ fruit.password = "ok-password"
381
+ assert_equal fruit.password, apple.password, "subclass did not adopt changes from parent class"
382
+ end
383
+
384
+ def test_bearer_token_reader_uses_superclass_bearer_token_until_written
385
+ # Superclass is Object so returns nil.
386
+ assert_nil ActiveResource::Base.bearer_token
387
+ assert_nil Class.new(ActiveResource::Base).bearer_token
388
+ Person.bearer_token = "my-token".dup
389
+
390
+ # Subclass uses superclass bearer_token.
391
+ actor = Class.new(Person)
392
+ assert_equal Person.bearer_token, actor.bearer_token
393
+
394
+ # Subclass returns frozen superclass copy.
395
+ assert_not Person.bearer_token.frozen?
396
+ assert actor.bearer_token.frozen?
397
+
398
+ # Changing subclass bearer_token doesn't change superclass bearer_token.
399
+ actor.bearer_token = "token123"
400
+ assert_not_equal Person.bearer_token, actor.bearer_token
401
+
402
+ # Changing superclass bearer_token doesn't overwrite subclass bearer_token.
403
+ Person.bearer_token = "super-secret-token"
404
+ assert_not_equal Person.bearer_token, actor.bearer_token
405
+
406
+ # Changing superclass bearer_token after subclassing changes subclass bearer_token.
407
+ jester = Class.new(actor)
408
+ actor.bearer_token = "super-secret-token123"
409
+ assert_equal actor.bearer_token, jester.bearer_token
410
+
411
+ # Subclasses are always equal to superclass bearer_token when not overridden
412
+ fruit = Class.new(ActiveResource::Base)
413
+ apple = Class.new(fruit)
414
+
415
+ fruit.bearer_token = "mega-secret-token"
416
+ assert_equal fruit.bearer_token, apple.bearer_token, "subclass did not adopt changes from parent class"
417
+
418
+ fruit.bearer_token = "ok-token"
419
+ assert_equal fruit.bearer_token, apple.bearer_token, "subclass did not adopt changes from parent class"
420
+
421
+ Person.bearer_token = nil
422
+ end
423
+
424
+ def test_timeout_reader_uses_superclass_timeout_until_written
425
+ # Superclass is Object so returns nil.
426
+ assert_nil ActiveResource::Base.timeout
427
+ assert_nil Class.new(ActiveResource::Base).timeout
428
+ Person.timeout = 5
429
+
430
+ # Subclass uses superclass timeout.
431
+ actor = Class.new(Person)
432
+ assert_equal Person.timeout, actor.timeout
433
+
434
+ # Changing subclass timeout doesn't change superclass timeout.
435
+ actor.timeout = 10
436
+ assert_not_equal Person.timeout, actor.timeout
437
+
438
+ # Changing superclass timeout doesn't overwrite subclass timeout.
439
+ Person.timeout = 15
440
+ assert_not_equal Person.timeout, actor.timeout
441
+
442
+ # Changing superclass timeout after subclassing changes subclass timeout.
443
+ jester = Class.new(actor)
444
+ actor.timeout = 20
445
+ assert_equal actor.timeout, jester.timeout
446
+
447
+ # Subclasses are always equal to superclass timeout when not overridden.
448
+ fruit = Class.new(ActiveResource::Base)
449
+ apple = Class.new(fruit)
450
+
451
+ fruit.timeout = 25
452
+ assert_equal fruit.timeout, apple.timeout, "subclass did not adopt changes from parent class"
453
+
454
+ fruit.timeout = 30
455
+ assert_equal fruit.timeout, apple.timeout, "subclass did not adopt changes from parent class"
456
+ end
457
+
458
+ def test_open_and_read_timeout_readers_uses_superclass_timeout_until_written
459
+ # Superclass is Object so returns nil.
460
+ assert_nil ActiveResource::Base.open_timeout
461
+ assert_nil Class.new(ActiveResource::Base).open_timeout
462
+ assert_nil ActiveResource::Base.read_timeout
463
+ assert_nil Class.new(ActiveResource::Base).read_timeout
464
+ Person.open_timeout = 5
465
+ Person.read_timeout = 5
466
+
467
+ # Subclass uses superclass open and read timeouts.
468
+ actor = Class.new(Person)
469
+ assert_equal Person.open_timeout, actor.open_timeout
470
+ assert_equal Person.read_timeout, actor.read_timeout
471
+
472
+ # Changing subclass open and read timeouts doesn't change superclass timeouts.
473
+ actor.open_timeout = 10
474
+ actor.read_timeout = 10
475
+ assert_not_equal Person.open_timeout, actor.open_timeout
476
+ assert_not_equal Person.read_timeout, actor.read_timeout
477
+
478
+ # Changing superclass open and read timeouts doesn't overwrite subclass timeouts.
479
+ Person.open_timeout = 15
480
+ Person.read_timeout = 15
481
+ assert_not_equal Person.open_timeout, actor.open_timeout
482
+ assert_not_equal Person.read_timeout, actor.read_timeout
483
+
484
+ # Changing superclass open and read timeouts after subclassing changes subclass timeouts.
485
+ jester = Class.new(actor)
486
+ actor.open_timeout = 20
487
+ actor.read_timeout = 20
488
+ assert_equal actor.open_timeout, jester.open_timeout
489
+ assert_equal actor.read_timeout, jester.read_timeout
490
+
491
+ # Subclasses are always equal to superclass open and read timeouts when not overridden.
492
+ fruit = Class.new(ActiveResource::Base)
493
+ apple = Class.new(fruit)
494
+
495
+ fruit.open_timeout = 25
496
+ fruit.read_timeout = 25
497
+ assert_equal fruit.open_timeout, apple.open_timeout, "subclass did not adopt changes from parent class"
498
+ assert_equal fruit.read_timeout, apple.read_timeout, "subclass did not adopt changes from parent class"
499
+
500
+ fruit.open_timeout = 30
501
+ fruit.read_timeout = 30
502
+ assert_equal fruit.open_timeout, apple.open_timeout, "subclass did not adopt changes from parent class"
503
+ assert_equal fruit.read_timeout, apple.read_timeout, "subclass did not adopt changes from parent class"
504
+ end
505
+
506
+ def test_primary_key_uses_superclass_primary_key_until_written
507
+ # Superclass is Object so defaults to 'id'
508
+ assert_equal "id", ActiveResource::Base.primary_key
509
+ assert_equal "id", Class.new(ActiveResource::Base).primary_key
510
+ Person.primary_key = :first
511
+
512
+ # Subclass uses superclass primary_key
513
+ actor = Class.new(Person)
514
+ assert_equal Person.primary_key, actor.primary_key
515
+
516
+ # Changing subclass primary_key doesn't change superclass primary_key
517
+ actor.primary_key = :second
518
+ assert_not_equal Person.primary_key, actor.primary_key
519
+
520
+ # Changing superclass primary_key doesn't overwrite subclass primary_key
521
+ Person.primary_key = :third
522
+ assert_not_equal Person.primary_key, actor.primary_key
523
+
524
+ # Changing superclass primary_key after subclassing changes subclass primary_key
525
+ jester = Class.new(actor)
526
+ actor.primary_key = :fourth
527
+ assert_equal actor.primary_key, jester.primary_key
528
+
529
+ # Subclass primary_keys are always equal to superclass primary_key when not overridden
530
+ fruit = Class.new(ActiveResource::Base)
531
+ apple = Class.new(fruit)
532
+
533
+ fruit.primary_key = :fifth
534
+ assert_equal fruit.primary_key, apple.primary_key, "subclass did not adopt changes from parent class"
535
+
536
+ fruit.primary_key = :sixth
537
+ assert_equal fruit.primary_key, apple.primary_key, "subclass did not adopt changes from parent class"
538
+
539
+ # Reset the primary key for subsequent tests
540
+ Person.primary_key = "id"
541
+ end
542
+
543
+ def test_ssl_options_reader_uses_superclass_ssl_options_until_written
544
+ # Superclass is Object so returns nil.
545
+ assert_nil ActiveResource::Base.ssl_options
546
+ assert_nil Class.new(ActiveResource::Base).ssl_options
547
+ Person.ssl_options = { foo: "bar" }
548
+
549
+ # Subclass uses superclass ssl_options.
550
+ actor = Class.new(Person)
551
+ assert_equal Person.ssl_options, actor.ssl_options
552
+
553
+ # Changing subclass ssl_options doesn't change superclass ssl_options.
554
+ actor.ssl_options = { baz: "" }
555
+ assert_not_equal Person.ssl_options, actor.ssl_options
556
+
557
+ # Changing superclass ssl_options doesn't overwrite subclass ssl_options.
558
+ Person.ssl_options = { color: "blue" }
559
+ assert_not_equal Person.ssl_options, actor.ssl_options
560
+
561
+ # Changing superclass ssl_options after subclassing changes subclass ssl_options.
562
+ jester = Class.new(actor)
563
+ actor.ssl_options = { color: "red" }
564
+ assert_equal actor.ssl_options, jester.ssl_options
565
+
566
+ # Subclasses are always equal to superclass ssl_options when not overridden.
567
+ fruit = Class.new(ActiveResource::Base)
568
+ apple = Class.new(fruit)
569
+
570
+ fruit.ssl_options = { alpha: "betas" }
571
+ assert_equal fruit.ssl_options, apple.ssl_options, "subclass did not adopt changes from parent class"
572
+
573
+ fruit.ssl_options = { omega: "moos" }
574
+ assert_equal fruit.ssl_options, apple.ssl_options, "subclass did not adopt changes from parent class"
575
+ end
576
+
577
+ def test_updating_baseclass_site_object_wipes_descendent_cached_connection_objects
578
+ # Subclasses are always equal to superclass site when not overridden
579
+ fruit = Class.new(ActiveResource::Base)
580
+ apple = Class.new(fruit)
581
+
582
+ fruit.site = "http://market"
583
+ assert_equal fruit.connection.site, apple.connection.site
584
+ first_connection = apple.connection.object_id
585
+
586
+ fruit.site = "http://supermarket"
587
+ assert_equal fruit.connection.site, apple.connection.site
588
+ second_connection = apple.connection.object_id
589
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
590
+ end
591
+
592
+ def test_updating_baseclass_user_wipes_descendent_cached_connection_objects
593
+ # Subclasses are always equal to superclass user when not overridden
594
+ fruit = Class.new(ActiveResource::Base)
595
+ apple = Class.new(fruit)
596
+ fruit.site = "http://market"
597
+
598
+ fruit.user = "david"
599
+ assert_equal fruit.connection.user, apple.connection.user
600
+ first_connection = apple.connection.object_id
601
+
602
+ fruit.user = "john"
603
+ assert_equal fruit.connection.user, apple.connection.user
604
+ second_connection = apple.connection.object_id
605
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
606
+ end
607
+
608
+ def test_updating_baseclass_password_wipes_descendent_cached_connection_objects
609
+ # Subclasses are always equal to superclass password when not overridden
610
+ fruit = Class.new(ActiveResource::Base)
611
+ apple = Class.new(fruit)
612
+ fruit.site = "http://market"
613
+
614
+ fruit.password = "secret"
615
+ assert_equal fruit.connection.password, apple.connection.password
616
+ first_connection = apple.connection.object_id
617
+
618
+ fruit.password = "supersecret"
619
+ assert_equal fruit.connection.password, apple.connection.password
620
+ second_connection = apple.connection.object_id
621
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
622
+ end
623
+
624
+ def test_updating_baseclass_bearer_token_wipes_descendent_cached_connection_objects
625
+ # Subclasses are always equal to superclass bearer_token when not overridden
626
+ fruit = Class.new(ActiveResource::Base)
627
+ apple = Class.new(fruit)
628
+ fruit.site = "http://market"
629
+
630
+ fruit.bearer_token = "my-token"
631
+ assert_equal fruit.connection.bearer_token, apple.connection.bearer_token
632
+ first_connection = apple.connection.object_id
633
+
634
+ fruit.bearer_token = "another-token"
635
+ assert_equal fruit.connection.bearer_token, apple.connection.bearer_token
636
+ second_connection = apple.connection.object_id
637
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
638
+ end
639
+
640
+ def test_updating_baseclass_timeout_wipes_descendent_cached_connection_objects
641
+ # Subclasses are always equal to superclass timeout when not overridden
642
+ fruit = Class.new(ActiveResource::Base)
643
+ apple = Class.new(fruit)
644
+ fruit.site = "http://market"
645
+
646
+ fruit.timeout = 5
647
+ assert_equal fruit.connection.timeout, apple.connection.timeout
648
+ first_connection = apple.connection.object_id
649
+
650
+ fruit.timeout = 10
651
+ assert_equal fruit.connection.timeout, apple.connection.timeout
652
+ second_connection = apple.connection.object_id
653
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
654
+ end
655
+
656
+ def test_updating_baseclass_read_and_open_timeouts_wipes_descendent_cached_connection_objects
657
+ # Subclasses are always equal to superclass timeout when not overridden
658
+ fruit = Class.new(ActiveResource::Base)
659
+ apple = Class.new(fruit)
660
+ fruit.site = "http://market"
661
+
662
+ fruit.open_timeout = 1
663
+ fruit.read_timeout = 5
664
+ assert_equal fruit.connection.open_timeout, apple.connection.open_timeout
665
+ assert_equal fruit.connection.read_timeout, apple.connection.read_timeout
666
+ first_connection = apple.connection.object_id
667
+
668
+ fruit.open_timeout = 2
669
+ fruit.read_timeout = 10
670
+ assert_equal fruit.connection.open_timeout, apple.connection.open_timeout
671
+ assert_equal fruit.connection.read_timeout, apple.connection.read_timeout
672
+ second_connection = apple.connection.object_id
673
+ assert_not_equal(first_connection, second_connection, "Connection should be re-created")
674
+ end
675
+
676
+ def test_header_inheritance
677
+ fruit = Class.new(ActiveResource::Base)
678
+ apple = Class.new(fruit)
679
+ fruit.site = "http://market"
680
+
681
+ fruit.headers["key"] = "value"
682
+ assert_equal "value", apple.headers["key"]
683
+ end
684
+
685
+ def test_header_inheritance_set_at_multiple_points
686
+ fruit = Class.new(ActiveResource::Base)
687
+ apple = Class.new(fruit)
688
+ fruit.site = "http://market"
689
+
690
+ fruit.headers["key"] = "value"
691
+ assert_equal "value", apple.headers["key"]
692
+
693
+ apple.headers["key2"] = "value2"
694
+ fruit.headers["key3"] = "value3"
695
+
696
+ assert_equal "value", apple.headers["key"]
697
+ assert_equal "value2", apple.headers["key2"]
698
+ assert_equal "value3", apple.headers["key3"]
699
+ end
700
+
701
+ def test_header_inheritance_should_not_leak_upstream
702
+ fruit = Class.new(ActiveResource::Base)
703
+ apple = Class.new(fruit)
704
+ fruit.site = "http://market"
705
+
706
+ fruit.headers["key"] = "value"
707
+
708
+ apple.headers["key2"] = "value2"
709
+ assert_nil fruit.headers["key2"]
710
+ end
711
+
712
+ def test_header_inheritance_can_override_upstream
713
+ fruit = Class.new(ActiveResource::Base)
714
+ apple = Class.new(fruit)
715
+ fruit.site = "http://market"
716
+
717
+ fruit.headers["key"] = "fruit-value"
718
+ assert_equal "fruit-value", apple.headers["key"]
719
+
720
+ apple.headers["key"] = "apple-value"
721
+ assert_equal "apple-value", apple.headers["key"]
722
+ assert_equal "fruit-value", fruit.headers["key"]
723
+ end
724
+
725
+
726
+ def test_header_inheritance_should_not_override_upstream_on_read
727
+ fruit = Class.new(ActiveResource::Base)
728
+ apple = Class.new(fruit)
729
+ fruit.site = "http://market"
730
+
731
+ fruit.headers["key"] = "value"
732
+ assert_equal "value", apple.headers["key"]
733
+
734
+ fruit.headers["key"] = "new-value"
735
+ assert_equal "new-value", apple.headers["key"]
736
+ end
737
+
738
+ def test_header_should_be_copied_to_main_thread_if_not_defined
739
+ fruit = Class.new(ActiveResource::Base)
740
+
741
+ Thread.new do
742
+ fruit.site = "http://market"
743
+ assert_equal "http://market", fruit.site.to_s
744
+
745
+ fruit.headers["key"] = "value"
746
+ assert_equal "value", fruit.headers["key"]
747
+ end.join
748
+
749
+ assert_equal "http://market", fruit.site.to_s
750
+ assert_equal "value", fruit.headers["key"]
751
+ end
752
+
753
+ def test_connection_should_use_connection_class
754
+ apple = Class.new(ActiveResource::Base)
755
+ orange = Class.new(ActiveResource::Base)
756
+ telephone = Class.new(ActiveResource::Connection)
757
+ orange.connection_class = telephone
758
+ apple.site = orange.site = "https://some-site.com/api"
759
+
760
+ assert_equal ActiveResource::Connection, apple.connection.class
761
+ assert_equal telephone, orange.connection.class
762
+ end
763
+
764
+ ########################################################################
765
+ # Tests for setting up remote URLs for a given model (including adding
766
+ # parameters appropriately)
767
+ ########################################################################
768
+ def test_collection_name
769
+ assert_equal "people", Person.collection_name
770
+ end
771
+
772
+ def test_collection_path
773
+ assert_equal "/people.json", Person.collection_path
774
+ end
775
+
776
+ def test_collection_path_with_parameters
777
+ assert_equal "/people.json?gender=male", Person.collection_path(gender: "male")
778
+ assert_equal "/people.json?gender=false", Person.collection_path(gender: false)
779
+ assert_equal "/people.json?gender=", Person.collection_path(gender: nil)
780
+
781
+ assert_equal "/people.json?gender=male", Person.collection_path("gender" => "male")
782
+
783
+ # Use includes? because ordering of param hash is not guaranteed
784
+ assert Person.collection_path(gender: "male", student: true).include?("/people.json?")
785
+ assert Person.collection_path(gender: "male", student: true).include?("gender=male")
786
+ assert Person.collection_path(gender: "male", student: true).include?("student=true")
787
+
788
+ assert_equal "/people.json?name%5B%5D=bob&name%5B%5D=your+uncle%2Bme&name%5B%5D=&name%5B%5D=false", Person.collection_path(name: ["bob", "your uncle+me", nil, false])
789
+ assert_equal "/people.json?struct%5Ba%5D%5B%5D=2&struct%5Ba%5D%5B%5D=1&struct%5Bb%5D=fred", Person.collection_path(struct: { :a => [2, 1], "b" => "fred" })
790
+ end
791
+
792
+ def test_custom_element_path
793
+ assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, person_id: 1)
794
+ assert_equal "/people/1/addresses/1.json", StreetAddress.element_path(1, "person_id" => 1)
795
+ assert_equal "/people/Greg/addresses/1.json", StreetAddress.element_path(1, "person_id" => "Greg")
796
+ assert_equal "/people/ann%20mary/addresses/ann+mary.json", StreetAddress.element_path(:'ann mary', "person_id" => "ann mary")
797
+ end
798
+
799
+ def test_custom_element_path_without_required_prefix_param
800
+ assert_raise ActiveResource::MissingPrefixParam do
801
+ StreetAddress.element_path(1)
802
+ end
803
+ end
804
+
805
+ def test_module_element_path
806
+ assert_equal "/sounds/1.json", Asset::Sound.element_path(1)
807
+ end
808
+
809
+ def test_module_element_url
810
+ assert_equal "http://37s.sunrise.i:3000/sounds/1.json", Asset::Sound.element_url(1)
811
+ end
812
+
813
+ def test_custom_element_path_with_redefined_to_param
814
+ Person.module_eval do
815
+ alias_method :original_to_param_element_path, :to_param
816
+ def to_param
817
+ name
818
+ end
819
+ end
820
+
821
+ # Class method.
822
+ assert_equal "/people/Greg.json", Person.element_path("Greg")
823
+
824
+ # Protected Instance method.
825
+ assert_equal "/people/Greg.json", Person.find("Greg").send(:element_path)
826
+
827
+ ensure
828
+ # revert back to original
829
+ Person.module_eval do
830
+ # save the 'new' to_param so we don't get a warning about discarding the method
831
+ alias_method :element_path_to_param, :to_param
832
+ alias_method :to_param, :original_to_param_element_path
833
+ end
834
+ end
835
+
836
+ def test_custom_element_path_with_parameters
837
+ assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, person_id: 1, type: "work")
838
+ assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, "person_id" => 1, :type => "work")
839
+ assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, type: "work", person_id: 1)
840
+ assert_equal "/people/1/addresses/1.json?type%5B%5D=work&type%5B%5D=play+time", StreetAddress.element_path(1, person_id: 1, type: ["work", "play time"])
841
+ end
842
+
843
+ def test_custom_element_path_with_prefix_and_parameters
844
+ assert_equal "/people/1/addresses/1.json?type=work", StreetAddress.element_path(1, { person_id: 1 }, { type: "work" })
845
+ end
846
+
847
+ def test_custom_collection_path_without_required_prefix_param
848
+ assert_raise ActiveResource::MissingPrefixParam do
849
+ StreetAddress.collection_path
850
+ end
851
+ end
852
+
853
+ def test_custom_collection_path
854
+ assert_equal "/people/1/addresses.json", StreetAddress.collection_path(person_id: 1)
855
+ assert_equal "/people/1/addresses.json", StreetAddress.collection_path("person_id" => 1)
856
+ end
857
+
858
+ def test_custom_collection_path_with_parameters
859
+ assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path(person_id: 1, type: "work")
860
+ assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path("person_id" => 1, :type => "work")
861
+ end
862
+
863
+ def test_custom_collection_path_with_prefix_and_parameters
864
+ assert_equal "/people/1/addresses.json?type=work", StreetAddress.collection_path({ person_id: 1 }, { type: "work" })
865
+ end
866
+
867
+ def test_custom_element_name
868
+ assert_equal "address", StreetAddress.element_name
869
+ end
870
+
871
+ def test_custom_collection_name
872
+ assert_equal "addresses", StreetAddress.collection_name
873
+ end
874
+
875
+ def test_prefix
876
+ assert_equal "/", Person.prefix
877
+ assert_equal Set.new, Person.__send__(:prefix_parameters)
878
+ end
879
+
880
+ def test_set_prefix
881
+ SetterTrap.rollback_sets(Person) do |person_class|
882
+ person_class.prefix = "the_prefix"
883
+ assert_equal "the_prefix", person_class.prefix
884
+ end
885
+ end
886
+
887
+ def test_set_prefix_with_inline_keys
888
+ SetterTrap.rollback_sets(Person) do |person_class|
889
+ person_class.prefix = "the_prefix:the_param"
890
+ assert_equal "the_prefixthe_param_value", person_class.prefix(the_param: "the_param_value")
891
+ end
892
+ end
893
+
894
+ def test_set_prefix_twice_should_clear_params
895
+ SetterTrap.rollback_sets(Person) do |person_class|
896
+ person_class.prefix = "the_prefix/:the_param1"
897
+ assert_equal Set.new([:the_param1]), person_class.prefix_parameters
898
+ person_class.prefix = "the_prefix/:the_param2"
899
+ assert_equal Set.new([:the_param2]), person_class.prefix_parameters
900
+ person_class.prefix = "the_prefix/:the_param1/other_prefix/:the_param2"
901
+ assert_equal Set.new([:the_param2, :the_param1]), person_class.prefix_parameters
902
+ end
903
+ end
904
+
905
+ def test_set_prefix_with_default_value
906
+ SetterTrap.rollback_sets(Person) do |person_class|
907
+ person_class.set_prefix
908
+ assert_equal "/", person_class.prefix
909
+ end
910
+ end
911
+
912
+ def test_custom_prefix
913
+ assert_equal "/people//", StreetAddress.prefix
914
+ assert_equal "/people/1/", StreetAddress.prefix(person_id: 1)
915
+ assert_equal [:person_id].to_set, StreetAddress.__send__(:prefix_parameters)
916
+ end
917
+
918
+
919
+ ########################################################################
920
+ # Tests basic CRUD functions (find/save/create etc)
921
+ ########################################################################
922
+ def test_respond_to
923
+ matz = Person.find(1)
924
+ assert_respond_to matz, :name
925
+ assert_respond_to matz, :name=
926
+ assert_respond_to matz, :name?
927
+ assert_not matz.respond_to?(:super_scalable_stuff)
928
+ end
929
+
930
+ def test_custom_header
931
+ Person.headers["key"] = "value"
932
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(4) }
933
+ ensure
934
+ Person.headers.delete("key")
935
+ end
936
+
937
+ def test_build_with_custom_header
938
+ Person.headers["key"] = "value"
939
+ ActiveResource::HttpMock.respond_to do |mock|
940
+ mock.get "/people/new.json", {}, Person.new.to_json
941
+ mock.get "/people/new.json", { "key" => "value" }, Person.new.to_json, 404
942
+ end
943
+ assert_raise(ActiveResource::ResourceNotFound) { Person.build }
944
+ ensure
945
+ Person.headers.delete("key")
946
+ end
947
+
948
+ def test_build_without_attributes_for_prefix_call
949
+ ActiveResource::HttpMock.respond_to do |mock|
950
+ mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
951
+ end
952
+ assert_raise(ActiveResource::InvalidRequestError) { StreetAddress.build }
953
+ end
954
+
955
+ def test_build_with_attributes_for_prefix_call
956
+ ActiveResource::HttpMock.respond_to do |mock|
957
+ mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
958
+ end
959
+ assert_nothing_raised { StreetAddress.build(person_id: 1) }
960
+ end
961
+
962
+ def test_build_with_non_prefix_attributes
963
+ ActiveResource::HttpMock.respond_to do |mock|
964
+ mock.get "/people/1/addresses/new.json", {}, StreetAddress.new.to_json
965
+ end
966
+ assert_nothing_raised do
967
+ address = StreetAddress.build(person_id: 1, city: "Toronto")
968
+ assert_equal "Toronto", address.city
969
+ end
970
+ end
971
+
972
+ def test_save
973
+ rick = Person.new
974
+ assert rick.save
975
+ assert_equal "5", rick.id
976
+ end
977
+
978
+ def test_save!
979
+ rick = Person.new
980
+ assert rick.save!
981
+ assert_equal "5", rick.id
982
+ end
983
+
984
+ def test_id_from_response
985
+ p = Person.new
986
+ resp = { "Location" => "/foo/bar/1" }
987
+ assert_equal "1", p.__send__(:id_from_response, resp)
988
+
989
+ resp["Location"] += ".json"
990
+ assert_equal "1", p.__send__(:id_from_response, resp)
991
+ end
992
+
993
+ def test_id_from_response_without_location
994
+ p = Person.new
995
+ resp = {}
996
+ assert_nil p.__send__(:id_from_response, resp)
997
+ end
998
+
999
+ def test_not_persisted_with_no_body_and_positive_content_length
1000
+ resp = ActiveResource::Response.new(nil)
1001
+ resp["Content-Length"] = "100"
1002
+ Person.connection.expects(:post).returns(resp)
1003
+ assert_not Person.create.persisted?
1004
+ end
1005
+
1006
+ def test_not_persisted_with_body_and_zero_content_length
1007
+ resp = ActiveResource::Response.new(@rick)
1008
+ resp["Content-Length"] = "0"
1009
+ Person.connection.expects(:post).returns(resp)
1010
+ assert_not Person.create.persisted?
1011
+ end
1012
+
1013
+ # These response codes aren't allowed to have bodies per HTTP spec
1014
+ def test_not_persisted_with_empty_response_codes
1015
+ [100, 101, 204, 304].each do |status_code|
1016
+ resp = ActiveResource::Response.new(@rick, status_code)
1017
+ Person.connection.expects(:post).returns(resp)
1018
+ assert_not Person.create.persisted?
1019
+ end
1020
+ end
1021
+
1022
+ # Content-Length is not required by HTTP 1.1, so we should read
1023
+ # the body anyway in its absence.
1024
+ def test_persisted_with_no_content_length
1025
+ resp = ActiveResource::Response.new(@rick)
1026
+ resp["Content-Length"] = nil
1027
+ Person.connection.expects(:post).returns(resp)
1028
+ assert Person.create.persisted?
1029
+ end
1030
+
1031
+ def test_create_with_custom_prefix
1032
+ matzs_house = StreetAddress.new(person_id: 1)
1033
+ matzs_house.save
1034
+ assert_equal "5", matzs_house.id
1035
+ end
1036
+
1037
+ # Test that loading a resource preserves its prefix_options.
1038
+ def test_load_preserves_prefix_options
1039
+ address = StreetAddress.find(1, params: { person_id: 1 })
1040
+ ryan = Person.new(id: 1, name: "Ryan", address: address)
1041
+ assert_equal address.prefix_options, ryan.address.prefix_options
1042
+ end
1043
+
1044
+ def test_reload_works_with_prefix_options
1045
+ address = StreetAddress.find(1, params: { person_id: 1 })
1046
+ assert_equal address, address.reload
1047
+ end
1048
+
1049
+ def test_reload_with_redefined_to_param
1050
+ Person.module_eval do
1051
+ alias_method :original_to_param_reload, :to_param
1052
+ def to_param
1053
+ name
1054
+ end
1055
+ end
1056
+
1057
+ person = Person.find("Greg")
1058
+ assert_equal person, person.reload
1059
+
1060
+ ensure
1061
+ # revert back to original
1062
+ Person.module_eval do
1063
+ # save the 'new' to_param so we don't get a warning about discarding the method
1064
+ alias_method :reload_to_param, :to_param
1065
+ alias_method :to_param, :original_to_param_reload
1066
+ end
1067
+ end
1068
+
1069
+ def test_reload_works_without_prefix_options
1070
+ person = Person.find(:first)
1071
+ assert_equal person, person.reload
1072
+ end
1073
+
1074
+ def test_create
1075
+ rick = Person.create(name: "Rick")
1076
+ assert rick.valid?
1077
+ assert_not rick.new?
1078
+ assert_equal "5", rick.id
1079
+
1080
+ # test additional attribute returned on create
1081
+ assert_equal 25, rick.age
1082
+
1083
+ # Test that save exceptions get bubbled up too
1084
+ ActiveResource::HttpMock.respond_to do |mock|
1085
+ mock.post "/people.json", {}, nil, 409
1086
+ end
1087
+ assert_raise(ActiveResource::ResourceConflict) { Person.create(name: "Rick") }
1088
+ end
1089
+
1090
+ def test_create_without_location
1091
+ ActiveResource::HttpMock.respond_to do |mock|
1092
+ mock.post "/people.json", {}, nil, 201
1093
+ end
1094
+ person = Person.create(name: "Rick")
1095
+ assert_nil person.id
1096
+ end
1097
+
1098
+ def test_create!
1099
+ rick = Person.create(name: "Rick")
1100
+ rick_bang = Person.create!(name: "Rick")
1101
+
1102
+ assert_equal rick.id, rick_bang.id
1103
+ assert_equal rick.age, rick_bang.age
1104
+
1105
+ ActiveResource::HttpMock.respond_to do |mock|
1106
+ mock.post "/people.json", {}, nil, 422
1107
+ end
1108
+ assert_raise(ActiveResource::ResourceInvalid) { Person.create!(name: "Rick") }
1109
+ end
1110
+
1111
+ def test_clone
1112
+ matz = Person.find(1)
1113
+ matz_c = matz.clone
1114
+ assert matz_c.new?
1115
+ matz.attributes.each do |k, v|
1116
+ assert_equal v, matz_c.send(k) if k != Person.primary_key
1117
+ end
1118
+ end
1119
+
1120
+ def test_nested_clone
1121
+ addy = StreetAddress.find(1, params: { person_id: 1 })
1122
+ addy_c = addy.clone
1123
+ assert addy_c.new?
1124
+ addy.attributes.each do |k, v|
1125
+ assert_equal v, addy_c.send(k) if k != StreetAddress.primary_key
1126
+ end
1127
+ assert_equal addy.prefix_options, addy_c.prefix_options
1128
+ end
1129
+
1130
+ def test_complex_clone
1131
+ matz = Person.find(1)
1132
+ matz.address = StreetAddress.find(1, params: { person_id: matz.id })
1133
+ matz.non_ar_hash = { not: "an ARes instance" }
1134
+ matz.non_ar_arr = ["not", "ARes"]
1135
+ matz_c = matz.clone
1136
+ assert matz_c.new?
1137
+ assert_raise(NoMethodError) { matz_c.address }
1138
+ assert_equal matz.non_ar_hash, matz_c.non_ar_hash
1139
+ assert_equal matz.non_ar_arr, matz_c.non_ar_arr
1140
+
1141
+ # Test that actual copy, not just reference copy
1142
+ matz.non_ar_hash[:not] = "changed"
1143
+ assert_not_equal matz.non_ar_hash, matz_c.non_ar_hash
1144
+ end
1145
+
1146
+ def test_update
1147
+ matz = Person.find(:first)
1148
+ matz.name = "David"
1149
+ assert_kind_of Person, matz
1150
+ assert_equal "David", matz.name
1151
+ assert_equal true, matz.save
1152
+ end
1153
+
1154
+ def test_update_with_custom_prefix_with_specific_id
1155
+ addy = StreetAddress.find(1, params: { person_id: 1 })
1156
+ addy.street = "54321 Street"
1157
+ assert_kind_of StreetAddress, addy
1158
+ assert_equal "54321 Street", addy.street
1159
+ addy.save
1160
+ end
1161
+
1162
+ def test_update_with_custom_prefix_without_specific_id
1163
+ addy = StreetAddress.find(:first, params: { person_id: 1 })
1164
+ addy.street = "54321 Lane"
1165
+ assert_kind_of StreetAddress, addy
1166
+ assert_equal "54321 Lane", addy.street
1167
+ addy.save
1168
+ end
1169
+
1170
+ def test_update_conflict
1171
+ ActiveResource::HttpMock.respond_to do |mock|
1172
+ mock.get "/people/2.json", {}, @david
1173
+ mock.put "/people/2.json", @default_request_headers, nil, 409
1174
+ end
1175
+ assert_raise(ActiveResource::ResourceConflict) { Person.find(2).save }
1176
+ end
1177
+
1178
+
1179
+ ######
1180
+ # update_attribute(s)(!)
1181
+
1182
+ def test_update_attribute_as_symbol
1183
+ matz = Person.first
1184
+ matz.expects(:save).returns(true)
1185
+
1186
+ assert_equal "Matz", matz.name
1187
+ assert matz.update_attribute(:name, "David")
1188
+ assert_equal "David", matz.name
1189
+ end
1190
+
1191
+ def test_update_attribute_as_string
1192
+ matz = Person.first
1193
+ matz.expects(:save).returns(true)
1194
+
1195
+ assert_equal "Matz", matz.name
1196
+ assert matz.update_attribute("name", "David")
1197
+ assert_equal "David", matz.name
1198
+ end
1199
+
1200
+
1201
+ def test_update_attributes_as_symbols
1202
+ addy = StreetAddress.first(params: { person_id: 1 })
1203
+ addy.expects(:save).returns(true)
1204
+
1205
+ assert_equal "12345 Street", addy.street
1206
+ assert_equal "Australia", addy.country
1207
+ assert addy.update_attributes(street: "54321 Street", country: "USA")
1208
+ assert_equal "54321 Street", addy.street
1209
+ assert_equal "USA", addy.country
1210
+ end
1211
+
1212
+ def test_update_attributes_as_strings
1213
+ addy = StreetAddress.first(params: { person_id: 1 })
1214
+ addy.expects(:save).returns(true)
1215
+
1216
+ assert_equal "12345 Street", addy.street
1217
+ assert_equal "Australia", addy.country
1218
+ assert addy.update_attributes("street" => "54321 Street", "country" => "USA")
1219
+ assert_equal "54321 Street", addy.street
1220
+ assert_equal "USA", addy.country
1221
+ end
1222
+
1223
+
1224
+ #####
1225
+ # Mayhem and destruction
1226
+
1227
+ def test_destroy
1228
+ assert Person.find(1).destroy
1229
+ ActiveResource::HttpMock.respond_to do |mock|
1230
+ mock.get "/people/1.json", {}, nil, 404
1231
+ end
1232
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(1).destroy }
1233
+ end
1234
+
1235
+ def test_destroy_with_custom_prefix
1236
+ assert StreetAddress.find(1, params: { person_id: 1 }).destroy
1237
+ ActiveResource::HttpMock.respond_to do |mock|
1238
+ mock.get "/people/1/addresses/1.json", {}, nil, 404
1239
+ end
1240
+ assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, params: { person_id: 1 }) }
1241
+ end
1242
+
1243
+ def test_destroy_with_410_gone
1244
+ assert Person.find(1).destroy
1245
+ ActiveResource::HttpMock.respond_to do |mock|
1246
+ mock.get "/people/1.json", {}, nil, 410
1247
+ end
1248
+ assert_raise(ActiveResource::ResourceGone) { Person.find(1).destroy }
1249
+ end
1250
+
1251
+ def test_delete
1252
+ assert Person.delete(1)
1253
+ ActiveResource::HttpMock.respond_to do |mock|
1254
+ mock.get "/people/1.json", {}, nil, 404
1255
+ end
1256
+ assert_raise(ActiveResource::ResourceNotFound) { Person.find(1) }
1257
+ end
1258
+
1259
+ def test_delete_with_custom_prefix
1260
+ assert StreetAddress.delete(1, person_id: 1)
1261
+ ActiveResource::HttpMock.respond_to do |mock|
1262
+ mock.get "/people/1/addresses/1.json", {}, nil, 404
1263
+ end
1264
+ assert_raise(ActiveResource::ResourceNotFound) { StreetAddress.find(1, params: { person_id: 1 }) }
1265
+ end
1266
+
1267
+ def test_delete_with_410_gone
1268
+ assert Person.delete(1)
1269
+ ActiveResource::HttpMock.respond_to do |mock|
1270
+ mock.get "/people/1.json", {}, nil, 410
1271
+ end
1272
+ assert_raise(ActiveResource::ResourceGone) { Person.find(1) }
1273
+ end
1274
+
1275
+ def test_delete_with_custom_header
1276
+ Person.headers["key"] = "value"
1277
+ ActiveResource::HttpMock.respond_to do |mock|
1278
+ mock.delete "/people/1.json", {}, nil, 200
1279
+ mock.delete "/people/1.json", { "key" => "value" }, nil, 404
1280
+ end
1281
+ assert_raise(ActiveResource::ResourceNotFound) { Person.delete(1) }
1282
+ ensure
1283
+ Person.headers.delete("key")
1284
+ end
1285
+
1286
+ ########################################################################
1287
+ # Tests the more miscellaneous helper methods
1288
+ ########################################################################
1289
+ def test_exists
1290
+ # Class method.
1291
+ assert_equal false, Person.exists?(nil)
1292
+ assert_equal true, Person.exists?(1)
1293
+ assert_equal false, Person.exists?(99)
1294
+
1295
+ # Instance method.
1296
+ assert_equal false, Person.new.exists?
1297
+ assert_equal true, Person.find(1).exists?
1298
+ assert_equal false, Person.new(id: 99).exists?
1299
+
1300
+ # Nested class method.
1301
+ assert_equal true, StreetAddress.exists?(1, params: { person_id: 1 })
1302
+ assert_equal false, StreetAddress.exists?(1, params: { person_id: 2 })
1303
+ assert_equal false, StreetAddress.exists?(2, params: { person_id: 1 })
1304
+
1305
+ # Nested instance method.
1306
+ assert_equal true, StreetAddress.find(1, params: { person_id: 1 }).exists?
1307
+ assert_equal false, StreetAddress.new(id: 1, person_id: 2).exists?
1308
+ assert_equal false, StreetAddress.new(id: 2, person_id: 1).exists?
1309
+ end
1310
+
1311
+ def test_exists_with_redefined_to_param
1312
+ Person.module_eval do
1313
+ alias_method :original_to_param_exists, :to_param
1314
+ def to_param
1315
+ name
1316
+ end
1317
+ end
1318
+
1319
+ # Class method.
1320
+ assert Person.exists?("Greg")
1321
+
1322
+ # Instance method.
1323
+ assert Person.find("Greg").exists?
1324
+
1325
+ # Nested class method.
1326
+ assert StreetAddress.exists?(1, params: { person_id: Person.find("Greg").to_param })
1327
+
1328
+ # Nested instance method.
1329
+ assert StreetAddress.find(1, params: { person_id: Person.find("Greg").to_param }).exists?
1330
+
1331
+ ensure
1332
+ # revert back to original
1333
+ Person.module_eval do
1334
+ # save the 'new' to_param so we don't get a warning about discarding the method
1335
+ alias_method :exists_to_param, :to_param
1336
+ alias_method :to_param, :original_to_param_exists
1337
+ end
1338
+ end
1339
+
1340
+ def test_exists_without_http_mock
1341
+ http = Net::HTTP.new(Person.site.host, Person.site.port)
1342
+ ActiveResource::Connection.any_instance.expects(:http).returns(http)
1343
+ http.expects(:request).returns(ActiveResource::Response.new(""))
1344
+
1345
+ assert Person.exists?("not-mocked")
1346
+ end
1347
+
1348
+ def test_exists_with_410_gone
1349
+ ActiveResource::HttpMock.respond_to do |mock|
1350
+ mock.head "/people/1.json", {}, nil, 410
1351
+ end
1352
+
1353
+ assert_not Person.exists?(1)
1354
+ end
1355
+
1356
+ def test_exists_with_204_no_content
1357
+ ActiveResource::HttpMock.respond_to do |mock|
1358
+ mock.head "/people/1.json", {}, nil, 204
1359
+ end
1360
+
1361
+ assert Person.exists?(1)
1362
+ end
1363
+
1364
+ def test_read_attribute_for_serialization
1365
+ joe = Person.find(6)
1366
+ joe.singleton_class.class_eval do
1367
+ def non_attribute_field
1368
+ "foo"
1369
+ end
1370
+
1371
+ def id
1372
+ "bar"
1373
+ end
1374
+ end
1375
+
1376
+ assert_equal joe.read_attribute_for_serialization(:id), 6
1377
+ assert_equal joe.read_attribute_for_serialization(:name), "Joe"
1378
+ assert_equal joe.read_attribute_for_serialization(:likes_hats), true
1379
+ assert_equal joe.read_attribute_for_serialization(:non_attribute_field), "foo"
1380
+ end
1381
+
1382
+ def test_to_xml
1383
+ Person.format = :xml
1384
+ matz = Person.find(1)
1385
+ encode = matz.encode
1386
+ xml = matz.to_xml
1387
+
1388
+ assert_equal encode, xml
1389
+ assert xml.include?('<?xml version="1.0" encoding="UTF-8"?>')
1390
+ assert xml.include?("<name>Matz</name>")
1391
+ assert xml.include?('<id type="integer">1</id>')
1392
+ ensure
1393
+ Person.format = :json
1394
+ end
1395
+
1396
+ def test_to_xml_with_element_name
1397
+ Person.format = :xml
1398
+ old_elem_name = Person.element_name
1399
+ matz = Person.find(1)
1400
+ Person.element_name = "ruby_creator"
1401
+ encode = matz.encode
1402
+ xml = matz.to_xml
1403
+
1404
+ assert_equal encode, xml
1405
+ assert xml.include?('<?xml version="1.0" encoding="UTF-8"?>')
1406
+ assert xml.include?("<ruby-creator>")
1407
+ assert xml.include?("<name>Matz</name>")
1408
+ assert xml.include?('<id type="integer">1</id>')
1409
+ assert xml.include?("</ruby-creator>")
1410
+ ensure
1411
+ Person.format = :json
1412
+ Person.element_name = old_elem_name
1413
+ end
1414
+
1415
+ def test_to_xml_with_private_method_name_as_attribute
1416
+ Person.format = :xml
1417
+
1418
+ customer = Customer.new(foo: "foo")
1419
+ customer.singleton_class.class_eval do
1420
+ def foo
1421
+ "bar"
1422
+ end
1423
+ private :foo
1424
+ end
1425
+
1426
+ assert_not customer.to_xml.include?("<foo>bar</foo>")
1427
+ assert customer.to_xml.include?("<foo>foo</foo>")
1428
+ ensure
1429
+ Person.format = :json
1430
+ end
1431
+
1432
+ def test_to_json
1433
+ joe = Person.find(6)
1434
+ encode = joe.encode
1435
+ json = joe.to_json
1436
+
1437
+ assert_equal encode, json
1438
+ assert_match %r{^\{"person":\{}, json
1439
+ assert_match %r{"id":6}, json
1440
+ assert_match %r{"name":"Joe"}, json
1441
+ assert_match %r{\}\}$}, json
1442
+ end
1443
+
1444
+ def test_to_json_without_root
1445
+ ActiveResource::Base.include_root_in_json = false
1446
+ joe = Person.find(6)
1447
+ encode = joe.encode
1448
+ json = joe.to_json
1449
+
1450
+ assert_equal encode, json
1451
+ assert_match %r{^\{"id":6}, json
1452
+ assert_match %r{"name":"Joe"}, json
1453
+ assert_match %r{\}$}, json
1454
+ ensure
1455
+ ActiveResource::Base.include_root_in_json = true
1456
+ end
1457
+
1458
+ def test_to_json_with_element_name
1459
+ old_elem_name = Person.element_name
1460
+ joe = Person.find(6)
1461
+ Person.element_name = "ruby_creator"
1462
+ encode = joe.encode
1463
+ json = joe.to_json
1464
+
1465
+ assert_equal encode, json
1466
+ assert_match %r{^\{"ruby_creator":\{}, json
1467
+ assert_match %r{"id":6}, json
1468
+ assert_match %r{"name":"Joe"}, json
1469
+ assert_match %r{\}\}$}, json
1470
+ ensure
1471
+ Person.element_name = old_elem_name
1472
+ end
1473
+
1474
+ def test_to_param_quacks_like_active_record
1475
+ new_person = Person.new
1476
+ assert_nil new_person.to_param
1477
+ matz = Person.find(1)
1478
+ assert_equal "1", matz.to_param
1479
+ end
1480
+
1481
+ def test_to_key_quacks_like_active_record
1482
+ new_person = Person.new
1483
+ assert_nil new_person.to_key
1484
+ matz = Person.find(1)
1485
+ assert_equal [1], matz.to_key
1486
+ end
1487
+
1488
+ def test_parse_deep_nested_resources
1489
+ luis = Customer.find(1)
1490
+ assert_kind_of Customer, luis
1491
+ luis.friends.each do |friend|
1492
+ assert_kind_of Customer::Friend, friend
1493
+ friend.brothers.each do |brother|
1494
+ assert_kind_of Customer::Friend::Brother, brother
1495
+ brother.children.each do |child|
1496
+ assert_kind_of Customer::Friend::Brother::Child, child
1497
+ end
1498
+ end
1499
+ end
1500
+ end
1501
+
1502
+ def test_persisted_nested_resources_from_response
1503
+ luis = Customer.find(1)
1504
+ luis.friends.each do |friend|
1505
+ assert_not friend.new?
1506
+ friend.brothers.each do |brother|
1507
+ assert_not brother.new?
1508
+ brother.children.each do |child|
1509
+ assert_not child.new?
1510
+ end
1511
+ end
1512
+ end
1513
+ end
1514
+
1515
+ def test_parse_resource_with_given_has_one_resources
1516
+ Customer.send(:has_one, :mother, class_name: "external/person")
1517
+ luis = Customer.find(1)
1518
+ assert_kind_of External::Person, luis.mother
1519
+ end
1520
+
1521
+ def test_parse_resources_with_given_has_many_resources
1522
+ Customer.send(:has_many, :enemies, class_name: "external/person")
1523
+ luis = Customer.find(1)
1524
+ luis.enemies.each do |enemy|
1525
+ assert_kind_of External::Person, enemy
1526
+ end
1527
+ end
1528
+
1529
+ def test_parse_resources_with_has_many_makes_get_request_on_nested_route
1530
+ Post.send(:has_many, :comments)
1531
+ post = Post.find(1)
1532
+ post.comments.each do |comment|
1533
+ assert_kind_of Comment, comment
1534
+ end
1535
+ end
1536
+
1537
+ def test_parse_resource_with_has_one_makes_get_request_on_child_route
1538
+ Product.send(:has_one, :inventory)
1539
+ product = Product.find(1)
1540
+ assert product.inventory.status == ActiveSupport::JSON.decode(@inventory)["status"]
1541
+ end
1542
+
1543
+ def test_parse_non_singleton_resource_with_has_one_makes_get_request_on_child_route
1544
+ accepts = { "Accept" => "application/json" }
1545
+ ActiveResource::HttpMock.respond_to do |mock|
1546
+ mock.get "/posts/1.json", accepts, @post
1547
+ mock.get "/posts/1/author.json", accepts, @matz
1548
+ end
1549
+
1550
+ Post.send(:has_one, :author, class_name: "Person")
1551
+ post = Post.find(1)
1552
+ assert post.author.name == ActiveSupport::JSON.decode(@matz)["person"]["name"]
1553
+ end
1554
+
1555
+ def test_with_custom_formatter
1556
+ addresses = [{ id: "1", street: "1 Infinite Loop", city: "Cupertino", state: "CA" }].to_xml(root: :addresses)
1557
+
1558
+ ActiveResource::HttpMock.respond_to do |mock|
1559
+ mock.get "/addresses.xml", {}, addresses, 200
1560
+ end
1561
+
1562
+ # late bind the site
1563
+ AddressResource.site = "http://localhost"
1564
+ addresses = AddressResource.find(:all)
1565
+
1566
+ assert_equal "Cupertino, CA", addresses.first.city_state
1567
+ end
1568
+
1569
+ def test_create_with_custom_primary_key
1570
+ silver_plan = { plan: { code: "silver", price: 5.00 } }.to_json
1571
+
1572
+ ActiveResource::HttpMock.respond_to do |mock|
1573
+ mock.post "/plans.json", {}, silver_plan, 201, "Location" => "/plans/silver.json"
1574
+ end
1575
+
1576
+ plan = SubscriptionPlan.new(code: "silver", price: 5.00)
1577
+ assert plan.new?
1578
+
1579
+ plan.save!
1580
+ assert_not plan.new?
1581
+ end
1582
+
1583
+ def test_update_with_custom_primary_key
1584
+ silver_plan = { plan: { code: "silver", price: 5.00 } }.to_json
1585
+ silver_plan_updated = { plan: { code: "silver", price: 10.00 } }.to_json
1586
+
1587
+ ActiveResource::HttpMock.respond_to do |mock|
1588
+ mock.get "/plans/silver.json", {}, silver_plan
1589
+ mock.put "/plans/silver.json", {}, silver_plan_updated, 201, "Location" => "/plans/silver.json"
1590
+ end
1591
+
1592
+ plan = SubscriptionPlan.find("silver")
1593
+ assert_not plan.new?
1594
+ assert_equal 5.00, plan.price
1595
+
1596
+ # update price
1597
+ plan.price = 10.00
1598
+ plan.save!
1599
+ assert_equal 10.00, plan.price
1600
+ end
1601
+
1602
+ def test_namespacing
1603
+ sound = Asset::Sound.find(1)
1604
+ assert_equal "Asset::Sound::Author", sound.author.class.to_s
1605
+ end
1606
+
1607
+ def test_paths_with_format
1608
+ assert_equal "/customers.json", Customer.collection_path
1609
+ assert_equal "/customers/1.json", Customer.element_path(1)
1610
+ assert_equal "/customers/new.json", Customer.new_element_path
1611
+ end
1612
+
1613
+ def test_paths_without_format
1614
+ ActiveResource::Base.include_format_in_path = false
1615
+ assert_equal "/customers", Customer.collection_path
1616
+ assert_equal "/customers/1", Customer.element_path(1)
1617
+ assert_equal "/customers/new", Customer.new_element_path
1618
+
1619
+ ensure
1620
+ ActiveResource::Base.include_format_in_path = true
1621
+ end
1622
+ end