iron_admin 0.5.0 → 0.6.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (451) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/config/iron_admin_manifest.js +12 -0
  3. data/app/components/iron_admin/dashboards/metric_card_component.html.haml +8 -3
  4. data/app/components/iron_admin/dashboards/metric_card_component.rb +21 -1
  5. data/app/components/iron_admin/form/belongs_to_component.rb +60 -6
  6. data/app/components/iron_admin/form/nested_form_component.html.haml +28 -0
  7. data/app/components/iron_admin/form/nested_form_component.rb +81 -0
  8. data/app/components/iron_admin/resources/data_table_component.html.haml +1 -1
  9. data/app/components/iron_admin/resources/data_table_component.rb +6 -0
  10. data/app/components/iron_admin/resources/show_field_component.rb +2 -0
  11. data/app/controllers/iron_admin/application_controller.rb +32 -1
  12. data/app/controllers/iron_admin/concerns/action_executable.rb +44 -0
  13. data/app/controllers/iron_admin/concerns/filterable.rb +84 -0
  14. data/app/controllers/iron_admin/concerns/json_params_coercion.rb +67 -0
  15. data/app/controllers/iron_admin/concerns/nested_permittable.rb +36 -0
  16. data/app/controllers/iron_admin/concerns/scopeable.rb +84 -0
  17. data/app/controllers/iron_admin/concerns/searchable.rb +13 -16
  18. data/app/controllers/iron_admin/exports_controller.rb +15 -11
  19. data/app/controllers/iron_admin/imports_controller.rb +83 -0
  20. data/app/controllers/iron_admin/live_controller.rb +12 -0
  21. data/app/controllers/iron_admin/resources_controller.rb +118 -117
  22. data/app/controllers/iron_admin/search_controller.rb +5 -5
  23. data/app/controllers/iron_admin/tools_controller.rb +63 -4
  24. data/app/helpers/iron_admin/application_helper.rb +33 -14
  25. data/app/helpers/iron_admin/field_display_helper.rb +160 -1
  26. data/app/javascript/iron_admin/controllers/cp_nested_form_controller.js +113 -0
  27. data/app/javascript/iron_admin/controllers/filter_operator_controller.js +10 -0
  28. data/app/javascript/iron_admin/index.js +4 -0
  29. data/app/views/iron_admin/dashboard/index.html.haml +7 -2
  30. data/app/views/iron_admin/form/_nested_row.html.haml +70 -0
  31. data/app/views/iron_admin/imports/new.html.haml +27 -0
  32. data/app/views/iron_admin/imports/preview.html.haml +31 -0
  33. data/app/views/iron_admin/resources/_form.html.haml +81 -5
  34. data/app/views/iron_admin/resources/action_form.html.haml +62 -0
  35. data/app/views/iron_admin/resources/bulk_action_form.html.haml +62 -0
  36. data/app/views/iron_admin/resources/index.html.haml +60 -18
  37. data/app/views/iron_admin/tools/action_form.html.haml +57 -0
  38. data/app/views/iron_admin/tools/show.html.haml +20 -1
  39. data/config/importmap.rb +2 -0
  40. data/config/locales/en.yml +36 -0
  41. data/config/routes.rb +7 -0
  42. data/docs/components/filter-components.md +60 -0
  43. data/docs/getting-started/quick-start.md +17 -1
  44. data/docs/guides/authentication.md +7 -6
  45. data/docs/guides/custom-adapters.md +628 -0
  46. data/docs/guides/extending.md +132 -3
  47. data/docs/guides/fields.md +1 -1
  48. data/docs/guides/resources.md +78 -2
  49. data/docs/guides/troubleshooting.md +29 -0
  50. data/docs/reference/routes.md +10 -0
  51. data/lib/generators/iron_admin/install/install_generator.rb +28 -4
  52. data/lib/generators/iron_admin/install_audit/install_audit_generator.rb +26 -10
  53. data/lib/iron_admin/action_field.rb +56 -0
  54. data/lib/iron_admin/adapters/active_record.rb +237 -0
  55. data/lib/iron_admin/adapters/base.rb +340 -0
  56. data/lib/iron_admin/adapters/http/column_descriptor.rb +10 -0
  57. data/lib/iron_admin/adapters/http/configuration.rb +27 -0
  58. data/lib/iron_admin/adapters/http/connection.rb +117 -0
  59. data/lib/iron_admin/adapters/http/model_proxy.rb +75 -0
  60. data/lib/iron_admin/adapters/http/query.rb +111 -0
  61. data/lib/iron_admin/adapters/http/record.rb +83 -0
  62. data/lib/iron_admin/adapters/http/type_inferrer.rb +51 -0
  63. data/lib/iron_admin/adapters/http.rb +241 -0
  64. data/lib/iron_admin/adapters/mongoid/association_wrapper.rb +74 -0
  65. data/lib/iron_admin/adapters/mongoid/column_descriptor.rb +10 -0
  66. data/lib/iron_admin/adapters/mongoid.rb +284 -0
  67. data/lib/iron_admin/adapters/registry.rb +44 -0
  68. data/lib/iron_admin/concerns/importable.rb +81 -0
  69. data/lib/iron_admin/concerns/live_updatable.rb +38 -0
  70. data/lib/iron_admin/concerns/nestable.rb +69 -0
  71. data/lib/iron_admin/concerns/soft_deletable.rb +61 -0
  72. data/lib/iron_admin/configuration.rb +20 -0
  73. data/lib/iron_admin/dashboard.rb +15 -20
  74. data/lib/iron_admin/engine.rb +28 -1
  75. data/lib/iron_admin/errors.rb +29 -0
  76. data/lib/iron_admin/field_inferrer.rb +61 -22
  77. data/lib/iron_admin/filters/active_record_query_builder.rb +63 -0
  78. data/lib/iron_admin/filters/base_query_builder.rb +55 -0
  79. data/lib/iron_admin/filters/http_query_builder.rb +39 -0
  80. data/lib/iron_admin/filters/mongoid_query_builder.rb +58 -0
  81. data/lib/iron_admin/filters/query_builder.rb +12 -0
  82. data/lib/iron_admin/import/column_mapper.rb +42 -0
  83. data/lib/iron_admin/import/import_preview.rb +10 -0
  84. data/lib/iron_admin/import/import_result.rb +10 -0
  85. data/lib/iron_admin/import/importer.rb +231 -0
  86. data/lib/iron_admin/import/parser/csv.rb +34 -0
  87. data/lib/iron_admin/import/parser/json.rb +36 -0
  88. data/lib/iron_admin/import/type_caster.rb +47 -0
  89. data/lib/iron_admin/live/broadcaster.rb +43 -0
  90. data/lib/iron_admin/live/poll_cache.rb +28 -0
  91. data/lib/iron_admin/live.rb +29 -0
  92. data/lib/iron_admin/nested_association.rb +15 -0
  93. data/lib/iron_admin/nested_attributes_validator.rb +25 -0
  94. data/lib/iron_admin/policy.rb +72 -13
  95. data/lib/iron_admin/resource.rb +148 -90
  96. data/lib/iron_admin/resource_registry.rb +77 -4
  97. data/lib/iron_admin/tool.rb +50 -0
  98. data/lib/iron_admin/tool_action.rb +73 -0
  99. data/lib/iron_admin/tool_context.rb +49 -0
  100. data/lib/iron_admin/version.rb +1 -1
  101. data/lib/iron_admin.rb +28 -0
  102. data/vendor/bundle/ruby/3.2.0/cache/addressable-2.9.0.gem +0 -0
  103. data/vendor/bundle/ruby/3.2.0/cache/crack-1.0.1.gem +0 -0
  104. data/vendor/bundle/ruby/3.2.0/cache/faraday-2.14.1.gem +0 -0
  105. data/vendor/bundle/ruby/3.2.0/cache/faraday-net_http-3.4.2.gem +0 -0
  106. data/vendor/bundle/ruby/3.2.0/cache/hashdiff-1.2.1.gem +0 -0
  107. data/vendor/bundle/ruby/3.2.0/cache/net-http-0.9.1.gem +0 -0
  108. data/vendor/bundle/ruby/3.2.0/cache/public_suffix-7.0.5.gem +0 -0
  109. data/vendor/bundle/ruby/3.2.0/cache/rexml-3.4.4.gem +0 -0
  110. data/vendor/bundle/ruby/3.2.0/cache/webmock-3.26.2.gem +0 -0
  111. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/bigdecimal.so +0 -0
  112. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/gem_make.out +6 -6
  113. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/bigdecimal-4.0.1/mkmf.log +25 -25
  114. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/date_core.so +0 -0
  115. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/gem_make.out +6 -6
  116. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/date-3.5.1/mkmf.log +4 -4
  117. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/erb/escape.so +0 -0
  118. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/gem_make.out +6 -6
  119. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/erb-6.0.1/mkmf.log +2 -2
  120. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/gem_make.out +6 -6
  121. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/io/console.so +0 -0
  122. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/io-console-0.8.2/mkmf.log +22 -22
  123. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/gem_make.out +6 -6
  124. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/json/ext/generator.so +0 -0
  125. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/json/ext/parser.so +0 -0
  126. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/json-2.18.1/mkmf.log +9 -9
  127. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/gem_make.out +6 -6
  128. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/mkmf.log +12 -12
  129. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/nio4r-2.7.5/nio4r_ext.so +0 -0
  130. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/gem_make.out +6 -6
  131. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/mkmf.log +6 -6
  132. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/prism-1.9.0/prism/prism.so +0 -0
  133. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/gem_make.out +6 -6
  134. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/mkmf.log +7 -7
  135. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/psych-5.3.1/psych.so +0 -0
  136. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/racc-1.8.1/gem_make.out +6 -6
  137. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/racc-1.8.1/racc/cparse.so +0 -0
  138. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/redcarpet-3.6.1/gem_make.out +6 -6
  139. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/redcarpet-3.6.1/redcarpet.so +0 -0
  140. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/gem_make.out +6 -6
  141. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/mkmf.log +2 -2
  142. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/stringio-3.2.0/stringio.so +0 -0
  143. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/websocket-driver-0.8.0/gem_make.out +6 -6
  144. data/vendor/bundle/ruby/3.2.0/extensions/x86_64-linux/3.2.0/websocket-driver-0.8.0/websocket_mask.so +0 -0
  145. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/CHANGELOG.md +326 -0
  146. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/LICENSE.txt +202 -0
  147. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/README.md +121 -0
  148. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna/native.rb +66 -0
  149. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna/pure.rb +4710 -0
  150. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/idna.rb +26 -0
  151. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/template.rb +1040 -0
  152. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/uri.rb +2602 -0
  153. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable/version.rb +31 -0
  154. data/vendor/bundle/ruby/3.2.0/gems/addressable-2.9.0/lib/addressable.rb +4 -0
  155. data/vendor/bundle/ruby/3.2.0/gems/bigdecimal-4.0.1/ext/bigdecimal/Makefile +3 -3
  156. data/vendor/bundle/ruby/3.2.0/gems/bigdecimal-4.0.1/lib/bigdecimal.so +0 -0
  157. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/History +58 -0
  158. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/LICENSE +20 -0
  159. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/README.md +43 -0
  160. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/json.rb +113 -0
  161. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/util.rb +17 -0
  162. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/version.rb +3 -0
  163. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack/xml.rb +240 -0
  164. data/vendor/bundle/ruby/3.2.0/gems/crack-1.0.1/lib/crack.rb +8 -0
  165. data/vendor/bundle/ruby/3.2.0/gems/date-3.5.1/ext/date/Makefile +3 -3
  166. data/vendor/bundle/ruby/3.2.0/gems/date-3.5.1/lib/date_core.so +0 -0
  167. data/vendor/bundle/ruby/3.2.0/gems/erb-6.0.1/ext/erb/escape/Makefile +3 -3
  168. data/vendor/bundle/ruby/3.2.0/gems/erb-6.0.1/lib/erb/escape.so +0 -0
  169. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/CHANGELOG.md +574 -0
  170. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/LICENSE.md +20 -0
  171. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/README.md +67 -0
  172. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/Rakefile +12 -0
  173. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/examples/client_spec.rb +119 -0
  174. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/examples/client_test.rb +144 -0
  175. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter/test.rb +311 -0
  176. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter.rb +101 -0
  177. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/adapter_registry.rb +30 -0
  178. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/connection.rb +565 -0
  179. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/encoders/flat_params_encoder.rb +105 -0
  180. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/encoders/nested_params_encoder.rb +183 -0
  181. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/error.rb +202 -0
  182. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/logging/formatter.rb +118 -0
  183. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/methods.rb +6 -0
  184. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/middleware.rb +72 -0
  185. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/middleware_registry.rb +83 -0
  186. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/connection_options.rb +23 -0
  187. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/env.rb +204 -0
  188. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/proxy_options.rb +38 -0
  189. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/request_options.rb +23 -0
  190. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options/ssl_options.rb +76 -0
  191. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/options.rb +219 -0
  192. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/parameters.rb +5 -0
  193. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/rack_builder.rb +248 -0
  194. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/authorization.rb +54 -0
  195. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/instrumentation.rb +58 -0
  196. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/json.rb +70 -0
  197. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request/url_encoded.rb +60 -0
  198. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/request.rb +139 -0
  199. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/json.rb +74 -0
  200. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/logger.rb +39 -0
  201. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response/raise_error.rb +83 -0
  202. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/response.rb +95 -0
  203. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils/headers.rb +150 -0
  204. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils/params_hash.rb +61 -0
  205. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/utils.rb +121 -0
  206. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday/version.rb +5 -0
  207. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/lib/faraday.rb +158 -0
  208. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/external_adapters/faraday_specs_setup.rb +14 -0
  209. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter/test_spec.rb +442 -0
  210. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter_registry_spec.rb +28 -0
  211. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/adapter_spec.rb +55 -0
  212. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/connection_spec.rb +841 -0
  213. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/error_spec.rb +175 -0
  214. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/middleware_registry_spec.rb +31 -0
  215. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/middleware_spec.rb +213 -0
  216. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/env_spec.rb +76 -0
  217. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/options_spec.rb +297 -0
  218. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/proxy_options_spec.rb +79 -0
  219. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/options/request_options_spec.rb +19 -0
  220. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/params_encoders/flat_spec.rb +42 -0
  221. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/params_encoders/nested_spec.rb +151 -0
  222. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/rack_builder_spec.rb +317 -0
  223. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/authorization_spec.rb +118 -0
  224. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/instrumentation_spec.rb +74 -0
  225. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/json_spec.rb +199 -0
  226. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request/url_encoded_spec.rb +93 -0
  227. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/request_spec.rb +110 -0
  228. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/json_spec.rb +206 -0
  229. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/logger_spec.rb +299 -0
  230. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response/raise_error_spec.rb +286 -0
  231. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/response_spec.rb +84 -0
  232. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/utils/headers_spec.rb +109 -0
  233. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday/utils_spec.rb +120 -0
  234. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/faraday_spec.rb +43 -0
  235. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/spec_helper.rb +133 -0
  236. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/disabling_stub.rb +14 -0
  237. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/fake_safe_buffer.rb +15 -0
  238. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/faraday_middleware_subclasses.rb +18 -0
  239. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/helper_methods.rb +96 -0
  240. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/adapter.rb +105 -0
  241. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/params_encoder.rb +18 -0
  242. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/shared_examples/request_method.rb +263 -0
  243. data/vendor/bundle/ruby/3.2.0/gems/faraday-2.14.1/spec/support/streaming_response_checker.rb +35 -0
  244. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/LICENSE.md +21 -0
  245. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/README.md +57 -0
  246. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/adapter/net_http.rb +206 -0
  247. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/net_http/version.rb +7 -0
  248. data/vendor/bundle/ruby/3.2.0/gems/faraday-net_http-3.4.2/lib/faraday/net_http.rb +10 -0
  249. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/Gemfile +8 -0
  250. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/LICENSE +19 -0
  251. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/README.md +323 -0
  252. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/Rakefile +18 -0
  253. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/changelog.md +127 -0
  254. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/hashdiff.gemspec +39 -0
  255. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/compare_hashes.rb +101 -0
  256. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/diff.rb +185 -0
  257. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/lcs.rb +66 -0
  258. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/lcs_compare_arrays.rb +32 -0
  259. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/linear_compare_array.rb +159 -0
  260. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/patch.rb +88 -0
  261. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/util.rb +155 -0
  262. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff/version.rb +5 -0
  263. data/vendor/bundle/ruby/3.2.0/gems/hashdiff-1.2.1/lib/hashdiff.rb +10 -0
  264. data/vendor/bundle/ruby/3.2.0/gems/io-console-0.8.2/ext/io/console/Makefile +3 -3
  265. data/vendor/bundle/ruby/3.2.0/gems/io-console-0.8.2/lib/io/console.so +0 -0
  266. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/ext/json/ext/generator/Makefile +3 -3
  267. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/ext/json/ext/parser/Makefile +3 -3
  268. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/lib/json/ext/generator.so +0 -0
  269. data/vendor/bundle/ruby/3.2.0/gems/json-2.18.1/lib/json/ext/parser.so +0 -0
  270. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/BSDL +22 -0
  271. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/COPYING +56 -0
  272. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/README.md +93 -0
  273. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/doc/net-http/examples.rdoc +31 -0
  274. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/doc/net-http/included_getters.rdoc +3 -0
  275. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/exceptions.rb +35 -0
  276. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/generic_request.rb +429 -0
  277. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/header.rb +985 -0
  278. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/proxy_delta.rb +17 -0
  279. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/request.rb +88 -0
  280. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/requests.rb +444 -0
  281. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/response.rb +739 -0
  282. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/responses.rb +1242 -0
  283. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http/status.rb +84 -0
  284. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/http.rb +2608 -0
  285. data/vendor/bundle/ruby/3.2.0/gems/net-http-0.9.1/lib/net/https.rb +23 -0
  286. data/vendor/bundle/ruby/3.2.0/gems/nio4r-2.7.5/ext/nio4r/Makefile +3 -3
  287. data/vendor/bundle/ruby/3.2.0/gems/nio4r-2.7.5/lib/nio4r_ext.so +0 -0
  288. data/vendor/bundle/ruby/3.2.0/gems/prism-1.9.0/ext/prism/Makefile +3 -3
  289. data/vendor/bundle/ruby/3.2.0/gems/prism-1.9.0/lib/prism/prism.so +0 -0
  290. data/vendor/bundle/ruby/3.2.0/gems/psych-5.3.1/ext/psych/Makefile +3 -3
  291. data/vendor/bundle/ruby/3.2.0/gems/psych-5.3.1/lib/psych.so +0 -0
  292. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/CHANGELOG.md +649 -0
  293. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/Gemfile +16 -0
  294. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/LICENSE.txt +22 -0
  295. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/README.md +231 -0
  296. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/SECURITY.md +24 -0
  297. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/data/list.txt +16298 -0
  298. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/domain.rb +235 -0
  299. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/errors.rb +41 -0
  300. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/list.rb +247 -0
  301. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/rule.rb +350 -0
  302. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix/version.rb +14 -0
  303. data/vendor/bundle/ruby/3.2.0/gems/public_suffix-7.0.5/lib/public_suffix.rb +177 -0
  304. data/vendor/bundle/ruby/3.2.0/gems/racc-1.8.1/ext/racc/cparse/Makefile +3 -3
  305. data/vendor/bundle/ruby/3.2.0/gems/racc-1.8.1/lib/racc/cparse.so +0 -0
  306. data/vendor/bundle/ruby/3.2.0/gems/redcarpet-3.6.1/ext/redcarpet/Makefile +3 -3
  307. data/vendor/bundle/ruby/3.2.0/gems/redcarpet-3.6.1/lib/redcarpet.so +0 -0
  308. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/LICENSE.txt +22 -0
  309. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/NEWS.md +843 -0
  310. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/README.md +57 -0
  311. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/context.rdoc +143 -0
  312. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/child.rdoc +87 -0
  313. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/document.rdoc +276 -0
  314. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/element.rdoc +602 -0
  315. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/node.rdoc +97 -0
  316. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/rdoc/parent.rdoc +267 -0
  317. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/child_toc.rdoc +12 -0
  318. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/document_toc.rdoc +30 -0
  319. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/element_toc.rdoc +55 -0
  320. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/master_toc.rdoc +135 -0
  321. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/node_toc.rdoc +16 -0
  322. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tasks/tocs/parent_toc.rdoc +25 -0
  323. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/doc/rexml/tutorial.rdoc +1358 -0
  324. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/attlistdecl.rb +63 -0
  325. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/attribute.rb +210 -0
  326. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/cdata.rb +68 -0
  327. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/child.rb +96 -0
  328. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/comment.rb +80 -0
  329. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/doctype.rb +306 -0
  330. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/document.rb +471 -0
  331. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/attlistdecl.rb +11 -0
  332. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/dtd.rb +47 -0
  333. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/elementdecl.rb +18 -0
  334. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/entitydecl.rb +57 -0
  335. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/dtd/notationdecl.rb +40 -0
  336. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/element.rb +2578 -0
  337. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/encoding.rb +48 -0
  338. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/entity.rb +142 -0
  339. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/default.rb +116 -0
  340. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/pretty.rb +142 -0
  341. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/formatters/transitive.rb +58 -0
  342. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/functions.rb +446 -0
  343. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/instruction.rb +79 -0
  344. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/light/node.rb +188 -0
  345. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/namespace.rb +63 -0
  346. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/node.rb +80 -0
  347. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/output.rb +30 -0
  348. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parent.rb +166 -0
  349. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parseexception.rb +53 -0
  350. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/baseparser.rb +949 -0
  351. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/lightparser.rb +59 -0
  352. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/pullparser.rb +213 -0
  353. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/sax2parser.rb +270 -0
  354. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/streamparser.rb +67 -0
  355. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/treeparser.rb +89 -0
  356. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/ultralightparser.rb +57 -0
  357. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/parsers/xpathparser.rb +739 -0
  358. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/quickpath.rb +267 -0
  359. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/rexml.rb +39 -0
  360. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/sax2listener.rb +98 -0
  361. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/security.rb +28 -0
  362. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/source.rb +388 -0
  363. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/streamlistener.rb +93 -0
  364. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/text.rb +420 -0
  365. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/undefinednamespaceexception.rb +9 -0
  366. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/relaxng.rb +540 -0
  367. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/validation.rb +144 -0
  368. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/validation/validationexception.rb +10 -0
  369. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xmldecl.rb +130 -0
  370. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xmltokens.rb +85 -0
  371. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xpath.rb +70 -0
  372. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml/xpath_parser.rb +980 -0
  373. data/vendor/bundle/ruby/3.2.0/gems/rexml-3.4.4/lib/rexml.rb +3 -0
  374. data/vendor/bundle/ruby/3.2.0/gems/stringio-3.2.0/ext/stringio/Makefile +3 -3
  375. data/vendor/bundle/ruby/3.2.0/gems/stringio-3.2.0/lib/stringio.so +0 -0
  376. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/CHANGELOG.md +2148 -0
  377. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/LICENSE +20 -0
  378. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/README.md +1229 -0
  379. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/api.rb +111 -0
  380. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/assertion_failure.rb +13 -0
  381. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/callback_registry.rb +37 -0
  382. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/config.rb +20 -0
  383. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/cucumber.rb +12 -0
  384. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/deprecation.rb +11 -0
  385. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/errors.rb +19 -0
  386. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/async_http_client_adapter.rb +228 -0
  387. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/curb_adapter.rb +354 -0
  388. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/em_http_request_adapter.rb +239 -0
  389. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/excon_adapter.rb +167 -0
  390. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_lib_adapter.rb +9 -0
  391. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_lib_adapter_registry.rb +21 -0
  392. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/client.rb +17 -0
  393. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/request.rb +28 -0
  394. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/response.rb +95 -0
  395. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/streamer.rb +44 -0
  396. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb/webmock.rb +77 -0
  397. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/http_rb_adapter.rb +39 -0
  398. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/httpclient_adapter.rb +260 -0
  399. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/manticore_adapter.rb +147 -0
  400. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/net_http.rb +310 -0
  401. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/net_http_response.rb +36 -0
  402. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/patron_adapter.rb +132 -0
  403. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/http_lib_adapters/typhoeus_hydra_adapter.rb +190 -0
  404. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/any_arg_matcher.rb +15 -0
  405. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_argument_matcher.rb +23 -0
  406. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_excluding_matcher.rb +17 -0
  407. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/matchers/hash_including_matcher.rb +19 -0
  408. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/minitest.rb +43 -0
  409. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rack_response.rb +73 -0
  410. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_body_diff.rb +66 -0
  411. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_execution_verifier.rb +79 -0
  412. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_pattern.rb +428 -0
  413. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_registry.rb +37 -0
  414. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_signature.rb +56 -0
  415. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_signature_snippet.rb +63 -0
  416. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/request_stub.rb +134 -0
  417. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/response.rb +161 -0
  418. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/responses_sequence.rb +42 -0
  419. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers/request_pattern_matcher.rb +80 -0
  420. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers/webmock_matcher.rb +69 -0
  421. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec/matchers.rb +29 -0
  422. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/rspec.rb +44 -0
  423. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/stub_registry.rb +84 -0
  424. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/stub_request_snippet.rb +40 -0
  425. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/test_unit.rb +22 -0
  426. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_counter.rb +45 -0
  427. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_keys_stringifier.rb +27 -0
  428. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/hash_validator.rb +19 -0
  429. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/headers.rb +77 -0
  430. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/json.rb +72 -0
  431. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/parse_error.rb +7 -0
  432. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/parsers/xml.rb +16 -0
  433. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/query_mapper.rb +283 -0
  434. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/uri.rb +113 -0
  435. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/values_stringifier.rb +22 -0
  436. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/util/version_checker.rb +113 -0
  437. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/version.rb +5 -0
  438. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock/webmock.rb +175 -0
  439. data/vendor/bundle/ruby/3.2.0/gems/webmock-3.26.2/lib/webmock.rb +61 -0
  440. data/vendor/bundle/ruby/3.2.0/gems/websocket-driver-0.8.0/ext/websocket-driver/Makefile +3 -3
  441. data/vendor/bundle/ruby/3.2.0/gems/websocket-driver-0.8.0/lib/websocket_mask.so +0 -0
  442. data/vendor/bundle/ruby/3.2.0/specifications/addressable-2.9.0.gemspec +29 -0
  443. data/vendor/bundle/ruby/3.2.0/specifications/crack-1.0.1.gemspec +27 -0
  444. data/vendor/bundle/ruby/3.2.0/specifications/faraday-2.14.1.gemspec +0 -0
  445. data/vendor/bundle/ruby/3.2.0/specifications/faraday-net_http-3.4.2.gemspec +26 -0
  446. data/vendor/bundle/ruby/3.2.0/specifications/hashdiff-1.2.1.gemspec +30 -0
  447. data/vendor/bundle/ruby/3.2.0/specifications/net-http-0.9.1.gemspec +27 -0
  448. data/vendor/bundle/ruby/3.2.0/specifications/public_suffix-7.0.5.gemspec +24 -0
  449. data/vendor/bundle/ruby/3.2.0/specifications/rexml-3.4.4.gemspec +25 -0
  450. data/vendor/bundle/ruby/3.2.0/specifications/webmock-3.26.2.gemspec +44 -0
  451. metadata +377 -2
@@ -0,0 +1,84 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IronAdmin
4
+ module Concerns
5
+ # Provides scope building and record finding methods for controllers.
6
+ # Extracts base_scope, record_scope, and find_record to keep controllers slim.
7
+ module Scopeable
8
+ extend ActiveSupport::Concern
9
+
10
+ private
11
+
12
+ def base_scope
13
+ scope = adapter.all
14
+ scope = IronAdmin.configuration.tenant_scope_block.call(scope) if IronAdmin.configuration.tenant_scope_block
15
+ scope
16
+ end
17
+
18
+ def collection_scope
19
+ scope = apply_scopes(apply_filters(base_scope))
20
+ scope = apply_search(scope)
21
+ scope = apply_sorting(scope)
22
+ apply_preloading(scope)
23
+ end
24
+
25
+ def record_scope
26
+ scope = base_scope
27
+ scope = adapter.unscope_column(scope, @resource_class.soft_delete_column) if @resource_class.soft_delete?
28
+ scope
29
+ end
30
+
31
+ def find_record(scope, id)
32
+ pk = adapter.primary_key
33
+
34
+ result = if pk.is_a?(Array)
35
+ ids = id.to_s.split("_")
36
+ raise IronAdmin::RecordNotFound if ids.size != pk.size
37
+
38
+ pk.zip(ids).reduce(scope) { |s, (col, val)| adapter.filter(s, col.to_sym, val) }.first
39
+ else
40
+ adapter.filter(scope, pk.to_sym, id).first
41
+ end
42
+
43
+ raise IronAdmin::RecordNotFound unless result
44
+
45
+ result
46
+ end
47
+
48
+ def current_scope_name
49
+ scope_name = params[:scope]
50
+ defined_scope = @resource_class.all_scopes.find { |s| s[:name].to_s == scope_name }
51
+ defined_scope ||= @resource_class.all_scopes.find { |s| s[:default] }
52
+ defined_scope&.dig(:name)&.to_s
53
+ end
54
+
55
+ def apply_scopes(scope)
56
+ defined_scope = @resource_class.all_scopes.find { |s| s[:name].to_s == params[:scope] }
57
+ defined_scope ||= @resource_class.all_scopes.find { |s| s[:default] }
58
+
59
+ return scope unless defined_scope
60
+
61
+ apply_resource_scope(scope, defined_scope[:scope])
62
+ end
63
+
64
+ def apply_resource_scope(scope, scope_body)
65
+ return scope.merge(scope_body) unless scope_body.respond_to?(:call)
66
+
67
+ scope_body.arity.zero? ? scope.instance_exec(&scope_body) : scope_body.call(scope)
68
+ end
69
+
70
+ def apply_sorting(scope)
71
+ sort_col = params[:sort].to_s
72
+ sort_col = IronAdmin.configuration.default_sort.to_s unless adapter.has_column?(sort_col)
73
+ valid_dir = %w[asc desc].include?(params[:direction].to_s.downcase)
74
+ sort_dir = valid_dir ? params[:direction] : IronAdmin.configuration.default_sort_direction
75
+ adapter.order_by(scope, sort_col, sort_dir)
76
+ end
77
+
78
+ def apply_preloading(scope)
79
+ preloads = @resource_class.preload_associations
80
+ preloads.any? ? adapter.preload(scope, preloads) : scope
81
+ end
82
+ end
83
+ end
84
+ end
@@ -29,38 +29,35 @@ module IronAdmin
29
29
  end
30
30
 
31
31
  def apply_field_search(scope, field, value)
32
- return scope unless @resource_class.model.column_names.include?(field)
32
+ return scope unless adapter.has_column?(field)
33
33
  return scope unless field_visible?(field.to_sym)
34
34
 
35
- conn = @resource_class.model.connection
36
- table = conn.quote_table_name(@resource_class.model.table_name)
37
- column = conn.quote_column_name(field)
38
- like_op = conn.adapter_name.downcase.include?("postgresql") ? "ILIKE" : "LIKE"
39
-
40
- if value.include?("..")
35
+ if value.include?("..") && range_search_column?(field)
41
36
  from_str, to_str = value.split("..", 2)
42
37
  from_date = parse_date(from_str)
43
38
  to_date = parse_date(to_str)
44
39
 
45
- return scope.where(field => from_date..to_date) if from_date && to_date
46
- return scope.where("#{table}.#{column} >= ?", from_date) if from_date
47
- return scope.where("#{table}.#{column} <= ?", to_date) if to_date
40
+ return adapter.filter(scope, field, from_date..to_date) if from_date && to_date
41
+ return adapter.filter(scope, field, from_date..) if from_date
42
+ return adapter.filter(scope, field, ..to_date) if to_date
48
43
 
49
44
  return scope
50
45
  end
51
46
 
52
- scope.where("#{table}.#{column} #{like_op} ?", "%#{value}%")
47
+ adapter.search_column(scope, field, value)
48
+ end
49
+
50
+ def range_search_column?(field)
51
+ adapter.columns.any? do |column|
52
+ column.name.to_s == field.to_s && column.type.in?(%i[date datetime])
53
+ end
53
54
  end
54
55
 
55
56
  def apply_general_search(scope, query)
56
57
  columns = visible_searchable_columns
57
58
  return scope if columns.empty?
58
59
 
59
- conn = @resource_class.model.connection
60
- table = conn.quote_table_name(@resource_class.model.table_name)
61
- like_operator = conn.adapter_name.downcase.include?("postgresql") ? "ILIKE" : "LIKE"
62
- conditions = columns.map { |col| "#{table}.#{conn.quote_column_name(col)} #{like_operator} :q" }
63
- scope.where(conditions.join(" OR "), q: "%#{query}%")
60
+ adapter.search_columns(scope, columns, query)
64
61
  end
65
62
 
66
63
  def visible_searchable_columns
@@ -9,13 +9,17 @@ module IronAdmin
9
9
  # @see IronAdmin::Resource#exports
10
10
  # @see IronAdmin::Resource#export_fields
11
11
  class ExportsController < ApplicationController
12
+ include Concerns::Filterable
13
+ include Concerns::Scopeable
14
+ include Concerns::Searchable
15
+
12
16
  before_action :set_resource_class
13
17
 
14
18
  # Exports resource data in the requested format.
15
19
  #
16
20
  # @return [void] Sends CSV file or renders JSON
17
21
  def show
18
- records = base_scope
22
+ records = collection_scope
19
23
  fields = export_fields
20
24
 
21
25
  respond_to do |format|
@@ -27,7 +31,7 @@ module IronAdmin
27
31
  end
28
32
 
29
33
  format.json do
30
- data = records.map { |r| fields.each_with_object({}) { |f, h| h[f.name] = safe_field_value(r, f) } }
34
+ data = records.map { |r| fields.each_with_object({}) { |f, h| h[f.name] = safe_field_value(r, f, :json) } }
31
35
  render json: data
32
36
  end
33
37
  end
@@ -40,10 +44,8 @@ module IronAdmin
40
44
  head(:not_found) and return unless @resource_class
41
45
  end
42
46
 
43
- def base_scope
44
- scope = @resource_class.model.all
45
- scope = IronAdmin.configuration.tenant_scope_block.call(scope) if IronAdmin.configuration.tenant_scope_block
46
- scope
47
+ def adapter
48
+ @resource_class.adapter
47
49
  end
48
50
 
49
51
  def export_fields
@@ -61,23 +63,25 @@ module IronAdmin
61
63
  require "csv"
62
64
  CSV.generate do |csv|
63
65
  csv << fields.map { |f| f.name.to_s.humanize }
64
- records.find_each do |record|
65
- csv << fields.map { |f| safe_field_value(record, f) }
66
+ adapter.find_each(records) do |record|
67
+ csv << fields.map { |f| safe_field_value(record, f, :csv) }
66
68
  end
67
69
  end
68
70
  end
69
71
 
70
- def safe_field_value(record, field)
72
+ def safe_field_value(record, field, format)
71
73
  return "[Error: field not found]" unless record.respond_to?(field.name)
72
74
 
73
75
  value = record.public_send(field.name)
74
- format_for_export(value, field)
76
+ format_for_export(value, field, format)
75
77
  rescue StandardError => e
76
78
  "[Error: #{e.message}]"
77
79
  end
78
80
 
79
- def format_for_export(value, field)
81
+ def format_for_export(value, field, format)
80
82
  return "" if value.nil?
83
+ return value if format == :json && value.is_a?(Hash)
84
+ return value if format == :json && value.is_a?(Array)
81
85
 
82
86
  case field.type
83
87
  when :datetime, :date then value.iso8601
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "ostruct"
4
+
5
+ module IronAdmin
6
+ class ImportsController < ApplicationController
7
+ before_action :set_resource_class
8
+ before_action :ensure_import_enabled
9
+ before_action :ensure_create_allowed
10
+
11
+ def new
12
+ @formats = @resource_class.import_formats
13
+ @fields = @resource_class.importable_fields(iron_admin_current_user)
14
+ end
15
+
16
+ def preview
17
+ return redirect_missing_file unless uploaded_file
18
+
19
+ @preview = importer.preview
20
+ @resource_name = @resource_class.resource_name
21
+ render :preview, formats: :html
22
+ rescue StandardError => e
23
+ redirect_to resource_import_path(@resource_class.resource_name), alert: e.message
24
+ end
25
+
26
+ def create
27
+ return redirect_missing_file unless uploaded_file
28
+
29
+ result = importer.execute!
30
+ redirect_to resources_path(@resource_class.resource_name),
31
+ notice: I18n.t(
32
+ "iron_admin.imports.create.success",
33
+ created: result.created_count,
34
+ updated: result.updated_count,
35
+ failed: result.failed_count
36
+ )
37
+ rescue StandardError => e
38
+ redirect_to resource_import_path(@resource_class.resource_name), alert: e.message
39
+ end
40
+
41
+ private
42
+
43
+ def set_resource_class
44
+ @resource_class = ResourceRegistry.find(params[:resource_name])
45
+ head(:not_found) and return unless @resource_class
46
+ end
47
+
48
+ def ensure_import_enabled
49
+ head(:not_found) and return unless @resource_class&.import_enabled?
50
+ end
51
+
52
+ def ensure_create_allowed
53
+ head(:forbidden) and return unless @resource_class.action_allowed?(:create)
54
+ end
55
+
56
+ def uploaded_file
57
+ params[:file]
58
+ end
59
+
60
+ def importer
61
+ Import::Importer.new(@resource_class, file: uploaded_file, format: import_format, context: import_context)
62
+ end
63
+
64
+ def import_format
65
+ params[:import_format].presence || params[:format].presence || uploaded_file_extension
66
+ end
67
+
68
+ def uploaded_file_extension
69
+ filename = uploaded_file&.original_filename
70
+ return unless filename
71
+
72
+ filename.split(".").last
73
+ end
74
+
75
+ def import_context
76
+ OpenStruct.new(current_user: iron_admin_current_user, controller: self)
77
+ end
78
+
79
+ def redirect_missing_file
80
+ redirect_to resource_import_path(@resource_class.resource_name), alert: I18n.t("iron_admin.imports.errors.missing_file")
81
+ end
82
+ end
83
+ end
@@ -0,0 +1,12 @@
1
+ # frozen_string_literal: true
2
+
3
+ module IronAdmin
4
+ class LiveController < ApplicationController
5
+ def show
6
+ return head(:not_found) unless IronAdmin::Live.polling?
7
+
8
+ render plain: IronAdmin::Live.poll_cache.fetch(params[:stream]).join,
9
+ content_type: Mime[:turbo_stream]
10
+ end
11
+ end
12
+ end
@@ -20,6 +20,11 @@ module IronAdmin
20
20
  #
21
21
  # @see IronAdmin::Resource
22
22
  class ResourcesController < ApplicationController
23
+ include Concerns::ActionExecutable
24
+ include Concerns::Filterable
25
+ include Concerns::JsonParamsCoercion
26
+ include Concerns::NestedPermittable
27
+ include Concerns::Scopeable
23
28
  include Concerns::Searchable
24
29
 
25
30
  before_action :set_resource_class
@@ -29,12 +34,7 @@ module IronAdmin
29
34
  #
30
35
  # @return [void]
31
36
  def index
32
- scope = apply_scopes(apply_filters(base_scope))
33
- scope = apply_search(scope)
34
- scope = apply_sorting(scope)
35
- scope = apply_preloading(scope)
36
-
37
- @pagy, @records = pagy(scope, limit: IronAdmin.configuration.per_page)
37
+ @pagy, @records = pagy(collection_scope, limit: IronAdmin.configuration.per_page)
38
38
  @fields = index_fields
39
39
  @current_scope = current_scope_name
40
40
  end
@@ -42,9 +42,9 @@ module IronAdmin
42
42
  # Shows a single record.
43
43
  #
44
44
  # @return [void]
45
- # @raise [ActiveRecord::RecordNotFound] if record doesn't exist
45
+ # @raise [IronAdmin::RecordNotFound] if record doesn't exist
46
46
  def show
47
- @record = record_scope.find(params[:id])
47
+ @record = find_record(record_scope, params[:id])
48
48
  @fields = @resource_class.resolved_fields
49
49
  end
50
50
 
@@ -52,16 +52,16 @@ module IronAdmin
52
52
  #
53
53
  # @return [void]
54
54
  def new
55
- @record = @resource_class.model.new
55
+ @record = adapter.build
56
56
  @fields = form_fields
57
57
  end
58
58
 
59
59
  # Renders the edit form for an existing record.
60
60
  #
61
61
  # @return [void]
62
- # @raise [ActiveRecord::RecordNotFound] if record doesn't exist
62
+ # @raise [IronAdmin::RecordNotFound] if record doesn't exist
63
63
  def edit
64
- @record = record_scope.find(params[:id])
64
+ @record = find_record(record_scope, params[:id])
65
65
  @fields = form_fields
66
66
  end
67
67
 
@@ -69,12 +69,12 @@ module IronAdmin
69
69
  #
70
70
  # @return [void]
71
71
  def create
72
- @record = @resource_class.model.new(resource_params)
72
+ @record = adapter.build(resource_params)
73
73
 
74
- if @record.save
74
+ if adapter.save(@record)
75
75
  emit_event(:create, @record)
76
76
  redirect_to resource_path(@resource_class.resource_name, @record),
77
- notice: I18n.t("iron_admin.resources.create.success", model: @resource_class.model.model_name.human)
77
+ notice: I18n.t("iron_admin.resources.create.success", model: adapter.human_name)
78
78
  else
79
79
  @fields = form_fields
80
80
  render :new, status: :unprocessable_content
@@ -84,15 +84,15 @@ module IronAdmin
84
84
  # Updates an existing record.
85
85
  #
86
86
  # @return [void]
87
- # @raise [ActiveRecord::RecordNotFound] if record doesn't exist
87
+ # @raise [IronAdmin::RecordNotFound] if record doesn't exist
88
88
  def update
89
- @record = record_scope.find(params[:id])
89
+ @record = find_record(record_scope, params[:id])
90
90
  purge_attachments(@record)
91
91
 
92
- if @record.update(resource_params)
92
+ if adapter.update(@record, resource_params)
93
93
  emit_event(:update, @record)
94
94
  redirect_to resource_path(@resource_class.resource_name, @record),
95
- notice: I18n.t("iron_admin.resources.update.success", model: @resource_class.model.model_name.human)
95
+ notice: I18n.t("iron_admin.resources.update.success", model: adapter.human_name)
96
96
  else
97
97
  @fields = form_fields
98
98
  render :edit, status: :unprocessable_content
@@ -102,34 +102,63 @@ module IronAdmin
102
102
  # Deletes a record.
103
103
  #
104
104
  # @return [void]
105
- # @raise [ActiveRecord::RecordNotFound] if record doesn't exist
105
+ # @raise [IronAdmin::RecordNotFound] if record doesn't exist
106
106
  def destroy
107
- @record = record_scope.find(params[:id])
108
- @record.destroy!
107
+ @record = find_record(record_scope, params[:id])
108
+ adapter.destroy!(@record)
109
109
  emit_event(:destroy, @record)
110
110
  redirect_to resources_path(@resource_class.resource_name),
111
- notice: I18n.t("iron_admin.resources.destroy.success", model: @resource_class.model.model_name.human)
111
+ notice: I18n.t("iron_admin.resources.destroy.success", model: adapter.human_name)
112
112
  end
113
113
 
114
- # Executes a custom action on a single record.
114
+ # Renders the action form for a single record action with form_fields.
115
115
  #
116
116
  # @return [void]
117
- def execute_action
118
- action = @resource_class.defined_actions.find { |a| a[:name].to_s == params[:action_name] }
117
+ def action_form
118
+ @action = find_single_record_action
119
+ return unless @action
120
+
121
+ return unless prepare_action_record?(@action)
122
+
123
+ @form_fields = @action[:form_fields]
124
+ @form_url = resource_action_path(@resource_class.resource_name, @record, @action[:name])
125
+ end
126
+
127
+ # Renders the action form for a bulk action with form_fields.
128
+ #
129
+ # @return [void]
130
+ def bulk_action_form
131
+ action = find_bulk_action
119
132
  return head(:not_found) unless action
120
133
  return head(:forbidden) unless action_authorized?(action[:name])
121
134
 
122
- @record = record_scope.find(params[:id])
135
+ @action = action
136
+ @form_fields = action[:form_fields]
137
+ @form_url = resource_bulk_action_path(@resource_class.resource_name, action[:name])
138
+ end
139
+
140
+ # Executes a custom action on a single record.
141
+ #
142
+ # @return [void]
143
+ def execute_action
144
+ action = find_single_record_action
145
+ return unless action
146
+
147
+ return unless prepare_action_record?(action)
123
148
 
124
- ActiveRecord::Base.transaction do
125
- result = action[:block].call(@record)
126
- emit_event(params[:action_name], @record)
127
- raise ActiveRecord::Rollback if result == false
149
+ collected = action_form_params(action)
150
+
151
+ adapter.transaction do
152
+ adapter.wrap_rollback do
153
+ result = call_action_block(action[:block], @record, collected)
154
+ emit_event(params[:action_name], @record)
155
+ raise IronAdmin::Rollback if result == false
156
+ end
128
157
  end
129
158
 
130
159
  redirect_to resource_path(@resource_class.resource_name, @record),
131
160
  notice: I18n.t("iron_admin.resources.action.success")
132
- rescue ActiveRecord::RecordNotFound
161
+ rescue IronAdmin::RecordNotFound
133
162
  head(:not_found)
134
163
  rescue StandardError => e
135
164
  redirect_to resources_path(@resource_class.resource_name),
@@ -146,7 +175,7 @@ module IronAdmin
146
175
  ids = bulk_action_ids
147
176
  return redirect_bulk(:alert, I18n.t("iron_admin.resources.bulk_action.no_records")) if ids.empty?
148
177
 
149
- records = base_scope.where(id: ids)
178
+ records = adapter.filter(base_scope, :id, ids)
150
179
  action = find_bulk_action
151
180
 
152
181
  return head(:not_found) unless action
@@ -169,31 +198,20 @@ module IronAdmin
169
198
  return render json: [] if query.blank?
170
199
 
171
200
  display = @resource_class.display_attribute
172
- conn = @resource_class.model.connection
173
- table = conn.quote_table_name(@resource_class.model.table_name)
174
- column = conn.quote_column_name(display)
175
- like_operator = conn.adapter_name.downcase.include?("postgresql") ? "ILIKE" : "LIKE"
201
+ display = searchable_display_attribute unless adapter.has_column?(display)
202
+ return render json: [] unless display
176
203
 
177
- records = base_scope
178
- .where("#{table}.#{column} #{like_operator} ?", "%#{query}%")
179
- .limit(20)
180
- .map { |r| { id: r.id, label: r.public_send(display) } }
204
+ scope = adapter.search_column(base_scope, display, query)
205
+ records = adapter.limit(scope, 20)
206
+ .map { |record| { id: record.to_param.to_s, label: record.public_send(display).to_s } }
181
207
 
182
208
  render json: records
183
209
  end
184
210
 
185
211
  private
186
212
 
187
- def base_scope
188
- scope = @resource_class.model.all
189
- scope = IronAdmin.configuration.tenant_scope_block.call(scope) if IronAdmin.configuration.tenant_scope_block
190
- scope
191
- end
192
-
193
- def record_scope
194
- scope = base_scope
195
- scope = scope.unscope(where: @resource_class.soft_delete_column.to_sym) if @resource_class.soft_delete?
196
- scope
213
+ def adapter
214
+ @resource_class.adapter
197
215
  end
198
216
 
199
217
  def set_resource_class
@@ -229,7 +247,21 @@ module IronAdmin
229
247
  end
230
248
 
231
249
  def bulk_action_ids
232
- Array(params[:ids]).map(&:to_i).reject(&:zero?)
250
+ Array(params[:ids]).compact_blank
251
+ end
252
+
253
+ def find_single_record_action
254
+ action = @resource_class.defined_actions.find { |defined| defined[:name].to_s == params[:action_name] }
255
+ unless action
256
+ head(:not_found)
257
+ return nil
258
+ end
259
+ unless action_authorized?(action[:name])
260
+ head(:forbidden)
261
+ return nil
262
+ end
263
+
264
+ action
233
265
  end
234
266
 
235
267
  def find_bulk_action
@@ -245,12 +277,34 @@ module IronAdmin
245
277
  end
246
278
 
247
279
  def run_bulk_action_in_transaction(action, records)
248
- ActiveRecord::Base.transaction do
249
- result = action[:block].call(records)
250
- raise ActiveRecord::Rollback if result == false
280
+ collected = action_form_params(action)
281
+ adapter.transaction do
282
+ adapter.wrap_rollback do
283
+ result = call_action_block(action[:block], records, collected)
284
+ raise IronAdmin::Rollback if result == false
285
+ end
251
286
  end
252
287
  end
253
288
 
289
+ def searchable_display_attribute
290
+ @resource_class.searchable_columns.find { |column| adapter.has_column?(column) }
291
+ end
292
+
293
+ def action_condition_met?(action, record)
294
+ condition = action[:condition]
295
+ return true unless condition
296
+
297
+ condition.call(record)
298
+ end
299
+
300
+ def prepare_action_record?(action)
301
+ @record = find_record(record_scope, params[:id])
302
+ return true if action_condition_met?(action, @record)
303
+
304
+ head(:forbidden)
305
+ false
306
+ end
307
+
254
308
  def index_fields
255
309
  base_fields = if @resource_class.index_field_names
256
310
  fields_by_name = @resource_class.resolved_fields.index_by(&:name)
@@ -274,7 +328,7 @@ module IronAdmin
274
328
 
275
329
  def purge_attachments(record)
276
330
  form_fields.select { |f| f.type == :file }.each do |field|
277
- next unless params.dig(:record, :"#{field.name}_purge") == "1" && record.respond_to?(field.name)
331
+ next unless iron_admin_param_dig(params[:record], :"#{field.name}_purge") == "1" && record.respond_to?(field.name)
278
332
 
279
333
  record.public_send(field.name).then { |a| a.purge if a.attached? }
280
334
  end
@@ -291,70 +345,17 @@ module IronAdmin
291
345
  end
292
346
 
293
347
  @resource_class.habtm_associations.each { |a| permitted << { "#{a[:name].to_s.singularize}_ids": [] } }
294
- params.require(:record).permit(*permitted) # rubocop:disable Rails/StrongParametersExpect
295
- end
296
-
297
- def apply_filters(scope)
298
- @resource_class.all_filters.each do |filter|
299
- if filter[:type] == :date_range
300
- from = params.dig(:filters, "#{filter[:name]}_from")
301
- to = params.dig(:filters, "#{filter[:name]}_to")
302
- scope = scope.where(filter[:name] => parse_date(from)..) if from.present? && parse_date(from)
303
- scope = scope.where(filter[:name] => ..parse_date(to)&.end_of_day) if to.present? && parse_date(to)
304
- next
305
- end
306
-
307
- value = params.dig(:filters, filter[:name])
308
- next if value.blank?
309
- next unless value.is_a?(String)
310
348
 
311
- value = ActiveModel::Type::Boolean.new.cast(value) if filter[:type] == :boolean
312
-
313
- scope = if filter[:scope]
314
- filter[:scope].call(value, scope)
315
- else
316
- scope.where(filter[:name] => value)
317
- end
349
+ @resource_class.nested_associations.each do |nested|
350
+ permitted << { "#{nested.name}_attributes": build_nested_permit_list(nested) }
318
351
  end
319
- scope
320
- end
321
-
322
- def parse_date(value)
323
- return nil if value.blank?
324
-
325
- Date.parse(value)
326
- rescue ArgumentError, TypeError
327
- nil
328
- end
329
-
330
- def current_scope_name
331
- scope_name = params[:scope]
332
- defined_scope = @resource_class.all_scopes.find { |s| s[:name].to_s == scope_name }
333
- defined_scope ||= @resource_class.all_scopes.find { |s| s[:default] }
334
- defined_scope&.dig(:name)&.to_s
335
- end
336
-
337
- def apply_scopes(scope)
338
- defined_scope = @resource_class.all_scopes.find { |s| s[:name].to_s == params[:scope] }
339
- defined_scope ||= @resource_class.all_scopes.find { |s| s[:default] }
340
-
341
- return scope unless defined_scope
342
352
 
343
- scope.merge(defined_scope[:scope])
344
- end
345
-
346
- def apply_sorting(scope)
347
- sort_col = params[:sort].to_s
348
- valid_columns = @resource_class.model.column_names
349
- sort_col = IronAdmin.configuration.default_sort.to_s unless valid_columns.include?(sort_col)
350
- valid_dir = %w[asc desc].include?(params[:direction].to_s.downcase)
351
- sort_dir = valid_dir ? params[:direction] : IronAdmin.configuration.default_sort_direction
352
- scope.order(sort_col => sort_dir)
353
- end
353
+ record_params = params.require(:record)
354
+ raise ActionController::ParameterMissing, :record unless record_params.respond_to?(:permit)
354
355
 
355
- def apply_preloading(scope)
356
- preloads = @resource_class.preload_associations
357
- preloads.any? ? scope.includes(*preloads) : scope
356
+ parsed = record_params.permit(*permitted)
357
+ coerce_json_field_params!(parsed)
358
+ parsed
358
359
  end
359
360
 
360
361
  def emit_event(action, record)
@@ -362,8 +363,8 @@ module IronAdmin
362
363
  user: iron_admin_current_user,
363
364
  action: action,
364
365
  resource: @resource_class.name,
365
- record_id: record.id,
366
- changes: record.saved_changes,
366
+ record_id: record.id.to_s,
367
+ changes: adapter.record_changes(record),
367
368
  ip_address: request.remote_ip
368
369
  )
369
370