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,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/array/wrap"
4
+
5
+ module ActiveResource
6
+ module Callbacks
7
+ extend ActiveSupport::Concern
8
+
9
+ CALLBACKS = [
10
+ :before_validation, :after_validation, :before_save, :around_save, :after_save,
11
+ :before_create, :around_create, :after_create, :before_update, :around_update,
12
+ :after_update, :before_destroy, :around_destroy, :after_destroy
13
+ ]
14
+
15
+ included do
16
+ extend ActiveModel::Callbacks
17
+ include ActiveModel::Validations::Callbacks
18
+
19
+ define_model_callbacks :save, :create, :update, :destroy
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,214 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/module/delegation"
4
+ require "active_support/inflector"
5
+
6
+ module ActiveResource # :nodoc:
7
+ class Collection # :nodoc:
8
+ include Enumerable
9
+ delegate :to_yaml, *Array.public_instance_methods(false), to: :request_resources!
10
+
11
+ attr_accessor :resource_class, :query_params, :path_params
12
+ attr_writer :prefix_options
13
+ attr_reader :from
14
+
15
+ # ActiveResource::Collection is a wrapper to handle parsing index responses that
16
+ # do not directly map to Rails conventions.
17
+ #
18
+ # You can define a custom class that inherits from ActiveResource::Collection
19
+ # in order to to set the elements instance.
20
+ #
21
+ # GET /posts.json delivers following response body:
22
+ # {
23
+ # posts: [
24
+ # {
25
+ # title: "ActiveResource now has associations",
26
+ # body: "Lorem Ipsum"
27
+ # },
28
+ # {...}
29
+ # ],
30
+ # next_page: "/posts.json?page=2"
31
+ # }
32
+ #
33
+ # A Post class can be setup to handle it with:
34
+ #
35
+ # class Post < ActiveResource::Base
36
+ # self.site = "http://example.com"
37
+ # self.collection_parser = PostCollection
38
+ # end
39
+ #
40
+ # And the collection parser:
41
+ #
42
+ # class PostCollection < ActiveResource::Collection
43
+ # attr_accessor :next_page
44
+ # def parse_response(parsed = {})
45
+ # @elements = parsed['posts']
46
+ # @next_page = parsed['next_page']
47
+ # end
48
+ # end
49
+ #
50
+ # The result from a find method that returns multiple entries will now be a
51
+ # PostParser instance. ActiveResource::Collection includes Enumerable and
52
+ # instances can be iterated over just like an array.
53
+ # @posts = Post.find(:all) # => PostCollection:xxx
54
+ # @posts.next_page # => "/posts.json?page=2"
55
+ # @posts.map(&:id) # =>[1, 3, 5 ...]
56
+ #
57
+ # The ActiveResource::Collection#parse_response method will receive the ActiveResource::Formats parsed result
58
+ # and should set @elements.
59
+ def initialize(elements = [], from = nil)
60
+ @from = from
61
+ @elements = elements
62
+ @requested = false
63
+ # This can get called without a response, so parse only if response is present
64
+ parse_response(@elements) if @elements.present?
65
+ end
66
+
67
+ # Processes and sets the collection elements. This method assigns the provided `elements`
68
+ # (or an empty array if none provided) to the `@elements` instance variable.
69
+ #
70
+ # ==== Arguments
71
+ #
72
+ # +elements+ (Array<Object>) - An optional array of resources to be set as the collection elements.
73
+ # Defaults to an empty array.
74
+ #
75
+ # This method is called after fetching the resource and can be overridden by subclasses to
76
+ # handle any specific response format of the API.
77
+ def parse_response(elements)
78
+ @elements = elements || []
79
+ end
80
+
81
+ # Returns the prefix options for the collection, which are used for constructing the resource path.
82
+ #
83
+ # ==== Returns
84
+ #
85
+ # [Hash] The prefix options for the collection.
86
+ def prefix_options
87
+ @prefix_options || {}
88
+ end
89
+
90
+ # Refreshes the collection by re-fetching the resources from the API.
91
+ #
92
+ # ==== Returns
93
+ #
94
+ # [Array<Object>] The collection of resources retrieved from the API.
95
+ def refresh
96
+ @requested = false
97
+ request_resources!
98
+ end
99
+
100
+ # Executes the request to fetch the collection of resources from the API and returns the collection.
101
+ #
102
+ # ==== Returns
103
+ #
104
+ # [ActiveResource::Collection] The collection of resources.
105
+ def call
106
+ request_resources!
107
+ self
108
+ end
109
+
110
+ # Checks if the collection has been requested.
111
+ #
112
+ # ==== Returns
113
+ #
114
+ # [Boolean] true if the collection has been requested, false otherwise.
115
+ def requested?
116
+ @requested
117
+ end
118
+
119
+ # Returns the first resource in the collection, or creates a new resource using the provided
120
+ # attributes if the collection is empty.
121
+ #
122
+ # ==== Arguments
123
+ #
124
+ # +attributes+ (Hash) - The attributes for creating the resource.
125
+ #
126
+ # ==== Returns
127
+ #
128
+ # [Object] The first resource, or a newly created resource if none exist.
129
+ #
130
+ # ==== Example
131
+ # post = PostCollection.where(title: "New Post").first_or_create
132
+ # # => Post instance with title "New Post"
133
+ def first_or_create(attributes = {})
134
+ first || resource_class.create(query_params.update(attributes))
135
+ rescue NoMethodError
136
+ raise "Cannot create resource from resource type: #{resource_class.inspect}"
137
+ end
138
+
139
+ # Returns the first resource in the collection, or initializes a new resource using the provided
140
+ # attributes if the collection is empty.
141
+ #
142
+ # ==== Arguments
143
+ #
144
+ # +attributes+ (Hash) - The attributes for initializing the resource.
145
+ #
146
+ # ==== Returns
147
+ #
148
+ # [Object] The first resource, or a newly initialized resource if none exist.
149
+ #
150
+ # ==== Example
151
+ # post = PostCollection.where(title: "New Post").first_or_initialize
152
+ # # => Post instance with title "New Post"
153
+ def first_or_initialize(attributes = {})
154
+ first || resource_class.new(query_params.update(attributes))
155
+ rescue NoMethodError
156
+ raise "Cannot build resource from resource type: #{resource_class.inspect}"
157
+ end
158
+
159
+ # Filters the collection based on the provided clauses (query parameters).
160
+ #
161
+ # ==== Arguments
162
+ #
163
+ # +clauses+ (Hash) - A hash of query parameters used to filter the collection.
164
+ #
165
+ # ==== Returns
166
+ #
167
+ # [ActiveResource::Collection] A new collection filtered by the specified clauses.
168
+ #
169
+ # ==== Example
170
+ # filtered_posts = PostCollection.where(title: "Post 1")
171
+ # # => PostCollection:xxx (filtered collection)
172
+ def where(clauses = {})
173
+ raise ArgumentError, "expected a clauses Hash, got #{clauses.inspect}" unless clauses.is_a? Hash
174
+ new_clauses = query_params.merge(clauses)
175
+ resource_class.where(new_clauses)
176
+ end
177
+
178
+ private
179
+ def query_string(options)
180
+ "?#{options.to_query}" unless options.nil? || options.empty?
181
+ end
182
+
183
+ # Requests resources from the API and parses the response. The resources are then mapped to their respective
184
+ # resource class instances.
185
+ #
186
+ # ==== Returns
187
+ #
188
+ # [Array<Object>] The collection of resources retrieved from the API.
189
+ def request_resources!
190
+ return @elements if requested?
191
+ response =
192
+ case from
193
+ when Symbol
194
+ resource_class.get(from, path_params)
195
+ when String
196
+ path = "#{from}#{query_string(query_params)}"
197
+ resource_class.format.decode(resource_class.connection.get(path, resource_class.headers).body)
198
+ else
199
+ path = resource_class.collection_path(prefix_options, query_params)
200
+ resource_class.format.decode(resource_class.connection.get(path, resource_class.headers).body)
201
+ end
202
+
203
+ # Update the elements
204
+ parse_response(response)
205
+ @elements.map! { |e| resource_class.instantiate_record(e, prefix_options) }
206
+ rescue ActiveResource::ResourceNotFound
207
+ # Swallowing ResourceNotFound exceptions and return nothing - as per ActiveRecord.
208
+ # Needs to be empty array as Array methods are delegated
209
+ []
210
+ ensure
211
+ @requested = true
212
+ end
213
+ end
214
+ end
@@ -0,0 +1,298 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/benchmark"
4
+ require "active_support/core_ext/object/inclusion"
5
+ require "net/https"
6
+ require "date"
7
+ require "time"
8
+
9
+ module ActiveResource
10
+ # Class to handle connections to remote web services.
11
+ # This class is used by ActiveResource::Base to interface with REST
12
+ # services.
13
+ class Connection
14
+ HTTP_FORMAT_HEADER_NAMES = { get: "Accept",
15
+ put: "Content-Type",
16
+ post: "Content-Type",
17
+ patch: "Content-Type",
18
+ delete: "Accept",
19
+ head: "Accept"
20
+ }
21
+
22
+ attr_reader :site, :user, :password, :bearer_token, :auth_type, :timeout, :open_timeout, :read_timeout, :proxy, :ssl_options
23
+ attr_accessor :format, :logger
24
+
25
+ class << self
26
+ def requests
27
+ @@requests ||= []
28
+ end
29
+ end
30
+
31
+ # The +site+ parameter is required and will set the +site+
32
+ # attribute to the URI for the remote resource service.
33
+ def initialize(site, format = ActiveResource::Formats::JsonFormat, logger: nil)
34
+ raise ArgumentError, "Missing site URI" unless site
35
+ @proxy = @user = @password = @bearer_token = nil
36
+ self.site = site
37
+ self.format = format
38
+ self.logger = logger
39
+ end
40
+
41
+ # Set URI for remote service.
42
+ def site=(site)
43
+ @site = site.is_a?(URI) ? site : URI.parse(site)
44
+ @ssl_options ||= {} if @site.is_a?(URI::HTTPS)
45
+ @user = URI_PARSER.unescape(@site.user) if @site.user
46
+ @password = URI_PARSER.unescape(@site.password) if @site.password
47
+ end
48
+
49
+ # Set the proxy for remote service.
50
+ def proxy=(proxy)
51
+ @proxy = proxy.is_a?(URI) ? proxy : URI.parse(proxy)
52
+ end
53
+
54
+ # Sets the user for remote service.
55
+ attr_writer :user
56
+
57
+ # Sets the password for remote service.
58
+ attr_writer :password
59
+
60
+ # Sets the bearer token for remote service.
61
+ attr_writer :bearer_token
62
+
63
+ # Sets the auth type for remote service.
64
+ def auth_type=(auth_type)
65
+ @auth_type = legitimize_auth_type(auth_type)
66
+ end
67
+
68
+ # Sets the number of seconds after which HTTP requests to the remote service should time out.
69
+ attr_writer :timeout
70
+
71
+ # Sets the number of seconds after which HTTP connects to the remote service should time out.
72
+ attr_writer :open_timeout
73
+
74
+ # Sets the number of seconds after which HTTP read requests to the remote service should time out.
75
+ attr_writer :read_timeout
76
+
77
+ # Hash of options applied to Net::HTTP instance when +site+ protocol is 'https'.
78
+ attr_writer :ssl_options
79
+
80
+ # Executes a GET request.
81
+ # Used to get (find) resources.
82
+ def get(path, headers = {})
83
+ with_auth { request(:get, path, build_request_headers(headers, :get, self.site.merge(path))) }
84
+ end
85
+
86
+ # Executes a DELETE request (see HTTP protocol documentation if unfamiliar).
87
+ # Used to delete resources.
88
+ def delete(path, headers = {})
89
+ with_auth { request(:delete, path, build_request_headers(headers, :delete, self.site.merge(path))) }
90
+ end
91
+
92
+ # Executes a PATCH request (see HTTP protocol documentation if unfamiliar).
93
+ # Used to update resources.
94
+ def patch(path, body = "", headers = {})
95
+ with_auth { request(:patch, path, body.to_s, build_request_headers(headers, :patch, self.site.merge(path))) }
96
+ end
97
+
98
+ # Executes a PUT request (see HTTP protocol documentation if unfamiliar).
99
+ # Used to update resources.
100
+ def put(path, body = "", headers = {})
101
+ with_auth { request(:put, path, body.to_s, build_request_headers(headers, :put, self.site.merge(path))) }
102
+ end
103
+
104
+ # Executes a POST request.
105
+ # Used to create new resources.
106
+ def post(path, body = "", headers = {})
107
+ with_auth { request(:post, path, body.to_s, build_request_headers(headers, :post, self.site.merge(path))) }
108
+ end
109
+
110
+ # Executes a HEAD request.
111
+ # Used to obtain meta-information about resources, such as whether they exist and their size (via response headers).
112
+ def head(path, headers = {})
113
+ with_auth { request(:head, path, build_request_headers(headers, :head, self.site.merge(path))) }
114
+ end
115
+
116
+ private
117
+ # Makes a request to the remote service.
118
+ def request(method, path, *arguments)
119
+ result = ActiveSupport::Notifications.instrument("request.active_resource") do |payload|
120
+ payload[:method] = method
121
+ payload[:request_uri] = "#{site.scheme}://#{site.host}:#{site.port}#{path}"
122
+ payload[:result] = http.send(method, path, *arguments)
123
+ end
124
+ handle_response(result)
125
+ rescue Timeout::Error => e
126
+ raise TimeoutError.new(e.message)
127
+ rescue OpenSSL::SSL::SSLError => e
128
+ raise SSLError.new(e.message)
129
+ end
130
+
131
+ # Handles response and error codes from the remote service.
132
+ def handle_response(response)
133
+ case response.code.to_i
134
+ when 301, 302, 303, 307
135
+ raise(Redirection.new(response))
136
+ when 200...400
137
+ response
138
+ when 400
139
+ raise(BadRequest.new(response))
140
+ when 401
141
+ raise(UnauthorizedAccess.new(response))
142
+ when 402
143
+ raise(PaymentRequired.new(response))
144
+ when 403
145
+ raise(ForbiddenAccess.new(response))
146
+ when 404
147
+ raise(ResourceNotFound.new(response))
148
+ when 405
149
+ raise(MethodNotAllowed.new(response))
150
+ when 409
151
+ raise(ResourceConflict.new(response))
152
+ when 410
153
+ raise(ResourceGone.new(response))
154
+ when 412
155
+ raise(PreconditionFailed.new(response))
156
+ when 422
157
+ raise(ResourceInvalid.new(response))
158
+ when 429
159
+ raise(TooManyRequests.new(response))
160
+ when 401...500
161
+ raise(ClientError.new(response))
162
+ when 500...600
163
+ raise(ServerError.new(response))
164
+ else
165
+ raise(ConnectionError.new(response, "Unknown response code: #{response.code}"))
166
+ end
167
+ end
168
+
169
+ # Creates new Net::HTTP instance for communication with the
170
+ # remote service and resources.
171
+ def http
172
+ configure_http(new_http)
173
+ end
174
+
175
+ def new_http
176
+ if @proxy
177
+ user = URI_PARSER.unescape(@proxy.user) if @proxy.user
178
+ password = URI_PARSER.unescape(@proxy.password) if @proxy.password
179
+ Net::HTTP.new(@site.host, @site.port, @proxy.host, @proxy.port, user, password)
180
+ else
181
+ Net::HTTP.new(@site.host, @site.port)
182
+ end
183
+ end
184
+
185
+ def configure_http(http)
186
+ apply_ssl_options(http).tap do |https|
187
+ # Net::HTTP timeouts default to 60 seconds.
188
+ if defined? @timeout
189
+ https.open_timeout = @timeout
190
+ https.read_timeout = @timeout
191
+ end
192
+ https.open_timeout = @open_timeout if defined?(@open_timeout)
193
+ https.read_timeout = @read_timeout if defined?(@read_timeout)
194
+ end
195
+ end
196
+
197
+ def apply_ssl_options(http)
198
+ http.tap do |https|
199
+ # Skip config if site is already a https:// URI.
200
+ if defined? @ssl_options
201
+ http.use_ssl = true
202
+
203
+ # All the SSL options have corresponding http settings.
204
+ @ssl_options.each { |key, value| http.send "#{key}=", value }
205
+ end
206
+ end
207
+ end
208
+
209
+ def default_header
210
+ @default_header ||= {}
211
+ end
212
+
213
+ # Builds headers for request to remote service.
214
+ def build_request_headers(headers, http_method, uri)
215
+ authorization_header(http_method, uri).update(default_header).update(http_format_header(http_method)).update(headers.to_hash)
216
+ end
217
+
218
+ def response_auth_header
219
+ @response_auth_header ||= ""
220
+ end
221
+
222
+ def with_auth
223
+ retried ||= false
224
+ yield
225
+ rescue UnauthorizedAccess => e
226
+ raise if retried || auth_type != :digest
227
+ @response_auth_header = e.response["WWW-Authenticate"]
228
+ retried = true
229
+ retry
230
+ end
231
+
232
+ def authorization_header(http_method, uri)
233
+ if @user || @password
234
+ if auth_type == :digest
235
+ { "Authorization" => digest_auth_header(http_method, uri) }
236
+ else
237
+ { "Authorization" => "Basic " + ["#{@user}:#{@password}"].pack("m").delete("\r\n") }
238
+ end
239
+ elsif @bearer_token
240
+ { "Authorization" => "Bearer #{@bearer_token}" }
241
+ else
242
+ {}
243
+ end
244
+ end
245
+
246
+ def digest_auth_header(http_method, uri)
247
+ params = extract_params_from_response
248
+
249
+ request_uri = uri.path
250
+ request_uri << "?#{uri.query}" if uri.query
251
+
252
+ ha1 = Digest::MD5.hexdigest("#{@user}:#{params['realm']}:#{@password}")
253
+ ha2 = Digest::MD5.hexdigest("#{http_method.to_s.upcase}:#{request_uri}")
254
+
255
+ params["cnonce"] = client_nonce
256
+ request_digest = Digest::MD5.hexdigest([ha1, params["nonce"], "0", params["cnonce"], params["qop"], ha2].join(":"))
257
+ "Digest #{auth_attributes_for(uri, request_digest, params)}"
258
+ end
259
+
260
+ def client_nonce
261
+ Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
262
+ end
263
+
264
+ def extract_params_from_response
265
+ params = {}
266
+ if response_auth_header =~ /^(\w+) (.*)/
267
+ $2.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
268
+ end
269
+ params
270
+ end
271
+
272
+ def auth_attributes_for(uri, request_digest, params)
273
+ auth_attrs =
274
+ [
275
+ %Q(username="#{@user}"),
276
+ %Q(realm="#{params['realm']}"),
277
+ %Q(qop="#{params['qop']}"),
278
+ %Q(uri="#{uri.path}"),
279
+ %Q(nonce="#{params['nonce']}"),
280
+ 'nc="0"',
281
+ %Q(cnonce="#{params['cnonce']}"),
282
+ %Q(response="#{request_digest}")]
283
+
284
+ auth_attrs << %Q(opaque="#{params['opaque']}") unless params["opaque"].blank?
285
+ auth_attrs.join(", ")
286
+ end
287
+
288
+ def http_format_header(http_method)
289
+ { HTTP_FORMAT_HEADER_NAMES[http_method] => format.mime_type }
290
+ end
291
+
292
+ def legitimize_auth_type(auth_type)
293
+ return :basic if auth_type.nil?
294
+ auth_type = auth_type.to_sym
295
+ auth_type.in?([:basic, :digest, :bearer]) ? auth_type : :basic
296
+ end
297
+ end
298
+ end
@@ -0,0 +1,129 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "active_support/core_ext/object/blank"
4
+
5
+ module ActiveResource
6
+ # A module to support custom REST methods and sub-resources, allowing you to break out
7
+ # of the "default" REST methods with your own custom resource requests. For example,
8
+ # say you use Rails to expose a REST service and configure your routes with:
9
+ #
10
+ # map.resources :people, :new => { :register => :post },
11
+ # :member => { :promote => :put, :deactivate => :delete }
12
+ # :collection => { :active => :get }
13
+ #
14
+ # This route set creates routes for the following HTTP requests:
15
+ #
16
+ # POST /people/new/register.json # PeopleController.register
17
+ # PATCH/PUT /people/1/promote.json # PeopleController.promote with :id => 1
18
+ # DELETE /people/1/deactivate.json # PeopleController.deactivate with :id => 1
19
+ # GET /people/active.json # PeopleController.active
20
+ #
21
+ # Using this module, Active Resource can use these custom REST methods just like the
22
+ # standard methods.
23
+ #
24
+ # class Person < ActiveResource::Base
25
+ # self.site = "https://37s.sunrise.com"
26
+ # end
27
+ #
28
+ # Person.new(:name => 'Ryan').post(:register) # POST /people/new/register.json
29
+ # # => { :id => 1, :name => 'Ryan' }
30
+ #
31
+ # Person.find(1).put(:promote, :position => 'Manager') # PUT /people/1/promote.json
32
+ # Person.find(1).delete(:deactivate) # DELETE /people/1/deactivate.json
33
+ #
34
+ # Person.get(:active) # GET /people/active.json
35
+ # # => [{:id => 1, :name => 'Ryan'}, {:id => 2, :name => 'Joe'}]
36
+ #
37
+ module CustomMethods
38
+ extend ActiveSupport::Concern
39
+
40
+ included do
41
+ class << self
42
+ alias :orig_delete :delete
43
+
44
+ # Invokes a GET to a given custom REST method. For example:
45
+ #
46
+ # Person.get(:active) # GET /people/active.json
47
+ # # => [{:id => 1, :name => 'Ryan'}, {:id => 2, :name => 'Joe'}]
48
+ #
49
+ # Person.get(:active, :awesome => true) # GET /people/active.json?awesome=true
50
+ # # => [{:id => 1, :name => 'Ryan'}]
51
+ #
52
+ # Note: the objects returned from this method are not automatically converted
53
+ # into ActiveResource::Base instances - they are ordinary Hashes. If you are expecting
54
+ # ActiveResource::Base instances, use the <tt>find</tt> class method with the
55
+ # <tt>:from</tt> option. For example:
56
+ #
57
+ # Person.find(:all, :from => :active)
58
+ def get(custom_method_name, options = {})
59
+ hashified = format.decode(connection.get(custom_method_collection_url(custom_method_name, options), headers).body)
60
+ derooted = Formats.remove_root(hashified)
61
+ derooted.is_a?(Array) ? derooted.map { |e| Formats.remove_root(e) } : derooted
62
+ end
63
+
64
+ def post(custom_method_name, options = {}, body = "")
65
+ connection.post(custom_method_collection_url(custom_method_name, options), body, headers)
66
+ end
67
+
68
+ def patch(custom_method_name, options = {}, body = "")
69
+ connection.patch(custom_method_collection_url(custom_method_name, options), body, headers)
70
+ end
71
+
72
+ def put(custom_method_name, options = {}, body = "")
73
+ connection.put(custom_method_collection_url(custom_method_name, options), body, headers)
74
+ end
75
+
76
+ def delete(custom_method_name, options = {})
77
+ # Need to jump through some hoops to retain the original class 'delete' method
78
+ if custom_method_name.is_a?(Symbol)
79
+ connection.delete(custom_method_collection_url(custom_method_name, options), headers)
80
+ else
81
+ orig_delete(custom_method_name, options)
82
+ end
83
+ end
84
+ end
85
+ end
86
+
87
+ module ClassMethods
88
+ def custom_method_collection_url(method_name, options = {})
89
+ prefix_options, query_options = split_options(options)
90
+ "#{prefix(prefix_options)}#{collection_name}/#{method_name}#{format_extension}#{query_string(query_options)}"
91
+ end
92
+ end
93
+
94
+ def get(method_name, options = {})
95
+ self.class.format.decode(connection.get(custom_method_element_url(method_name, options), self.class.headers).body)
96
+ end
97
+
98
+ def post(method_name, options = {}, body = nil)
99
+ request_body = body.blank? ? encode : body
100
+ if new?
101
+ connection.post(custom_method_new_element_url(method_name, options), request_body, self.class.headers)
102
+ else
103
+ connection.post(custom_method_element_url(method_name, options), request_body, self.class.headers)
104
+ end
105
+ end
106
+
107
+ def patch(method_name, options = {}, body = "")
108
+ connection.patch(custom_method_element_url(method_name, options), body, self.class.headers)
109
+ end
110
+
111
+ def put(method_name, options = {}, body = "")
112
+ connection.put(custom_method_element_url(method_name, options), body, self.class.headers)
113
+ end
114
+
115
+ def delete(method_name, options = {})
116
+ connection.delete(custom_method_element_url(method_name, options), self.class.headers)
117
+ end
118
+
119
+
120
+ private
121
+ def custom_method_element_url(method_name, options = {})
122
+ "#{self.class.prefix(prefix_options)}#{self.class.collection_name}/#{URI.encode_www_form_component(id.to_s)}/#{method_name}#{self.class.format_extension}#{self.class.__send__(:query_string, options)}"
123
+ end
124
+
125
+ def custom_method_new_element_url(method_name, options = {})
126
+ "#{self.class.prefix(prefix_options)}#{self.class.collection_name}/new/#{method_name}#{self.class.format_extension}#{self.class.__send__(:query_string, options)}"
127
+ end
128
+ end
129
+ end