active_cached_resource 0.0.1.pre

Sign up to get free protection for your applications and to get access to all the features.
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