plutonium 0.5.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 (346) hide show
  1. checksums.yaml +7 -0
  2. data/.rspec +3 -0
  3. data/.ruby-version +1 -0
  4. data/.standard.yml +4 -0
  5. data/.vscode/extensions.json +15 -0
  6. data/.vscode/launch.json +7 -0
  7. data/.vscode/settings.json +35 -0
  8. data/CHANGELOG.md +5 -0
  9. data/LICENSE.txt +21 -0
  10. data/README copy.md +84 -0
  11. data/README.md +67 -0
  12. data/Rakefile +8 -0
  13. data/app/views/layouts/resource.html.erb +43 -0
  14. data/app/views/resource/_color_modes.html.erb +55 -0
  15. data/app/views/resource/_details.html.erb +6 -0
  16. data/app/views/resource/_empty_card.html.erb +12 -0
  17. data/app/views/resource/_flash.html.erb +9 -0
  18. data/app/views/resource/_form.html.erb +32 -0
  19. data/app/views/resource/_header.html.erb +8 -0
  20. data/app/views/resource/_interactive_resource_action_form.html.erb +67 -0
  21. data/app/views/resource/_messages.html.erb +1 -0
  22. data/app/views/resource/_metric_card.html.erb +16 -0
  23. data/app/views/resource/_nav_user.html.erb +4 -0
  24. data/app/views/resource/_pagination.html.erb +6 -0
  25. data/app/views/resource/_pagy_pagination.html.erb +15 -0
  26. data/app/views/resource/_resource.html.erb +1 -0
  27. data/app/views/resource/_resource.rabl +5 -0
  28. data/app/views/resource/_sidebar.html.erb +11 -0
  29. data/app/views/resource/_sidebar_menu.html.erb +1 -0
  30. data/app/views/resource/_tab_menu.html.erb +13 -0
  31. data/app/views/resource/_table.html.erb +78 -0
  32. data/app/views/resource/_table_actions.html.erb +15 -0
  33. data/app/views/resource/_toast.html.erb +26 -0
  34. data/app/views/resource/_toolbar.html.erb +22 -0
  35. data/app/views/resource/_toolbar_actions.html.erb +16 -0
  36. data/app/views/resource/_toolbar_breadcrumbs.html.erb +32 -0
  37. data/app/views/resource/_toolbar_search_input.erb +27 -0
  38. data/app/views/resource/edit.html.erb +10 -0
  39. data/app/views/resource/errors.rabl +3 -0
  40. data/app/views/resource/index.html.erb +19 -0
  41. data/app/views/resource/index.rabl +3 -0
  42. data/app/views/resource/interactive_resource_collection_action.html.erb +11 -0
  43. data/app/views/resource/interactive_resource_record_action.html.erb +11 -0
  44. data/app/views/resource/interactive_resource_recordless_action.html.erb +11 -0
  45. data/app/views/resource/new.html.erb +11 -0
  46. data/app/views/resource/readme.md +16 -0
  47. data/app/views/resource/show.html.erb +14 -0
  48. data/app/views/resource/show.rabl +3 -0
  49. data/brakeman.ignore +51 -0
  50. data/lib/active_model/validations/array_validator.rb +74 -0
  51. data/lib/active_model/validations/attached_validator.rb +17 -0
  52. data/lib/active_model/validations/url_validator.rb +51 -0
  53. data/lib/generators/pu/core/install/install_generator.rb +43 -0
  54. data/lib/generators/pu/core/install/templates/.keep +0 -0
  55. data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +2 -0
  56. data/lib/generators/pu/core/install/templates/app/interactions/resource_interaction.rb.tt +2 -0
  57. data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +5 -0
  58. data/lib/generators/pu/core/install/templates/app/policies/resource_policy.rb.tt +2 -0
  59. data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +2 -0
  60. data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +2 -0
  61. data/lib/generators/pu/core/install/templates/config/packages.rb +3 -0
  62. data/lib/generators/pu/gem/pagy/pagy_generator.rb +25 -0
  63. data/lib/generators/pu/gem/pagy/templates/.keep +0 -0
  64. data/lib/generators/pu/gem/pagy/templates/config/initializers/pagy.rb +4 -0
  65. data/lib/generators/pu/gem/rabl/rabl_generator.rb +25 -0
  66. data/lib/generators/pu/gem/rabl/templates/.keep +0 -0
  67. data/lib/generators/pu/gem/rabl/templates/config/initializers/rabl.rb +60 -0
  68. data/lib/generators/pu/gem/simple_form/simple_form_generator.rb +25 -0
  69. data/lib/generators/pu/gem/simple_form/templates/.keep +0 -0
  70. data/lib/generators/pu/gen/pug/pug_generator.rb +43 -0
  71. data/lib/generators/pu/gen/pug/templates/pug.rb.tt +23 -0
  72. data/lib/generators/pu/pkg/app/app_generator.rb +60 -0
  73. data/lib/generators/pu/pkg/app/templates/app/controllers/resource_controller.rb.tt +26 -0
  74. data/lib/generators/pu/pkg/app/templates/app/interactions/resource_interaction.rb.tt +4 -0
  75. data/lib/generators/pu/pkg/app/templates/app/policies/resource_policy.rb.tt +4 -0
  76. data/lib/generators/pu/pkg/app/templates/app/presenters/resource_presenter.rb.tt +4 -0
  77. data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +17 -0
  78. data/lib/generators/pu/pkg/app/templates/lib/engine.rb.tt +14 -0
  79. data/lib/generators/pu/pkg/feature/feature_generator.rb +44 -0
  80. data/lib/generators/pu/pkg/feature/templates/.keep +0 -0
  81. data/lib/generators/pu/pkg/feature/templates/app/controllers/resource_controller.rb.tt +7 -0
  82. data/lib/generators/pu/pkg/feature/templates/app/interactions/resource_interaction.rb.tt +4 -0
  83. data/lib/generators/pu/pkg/feature/templates/app/models/resource_record.rb.tt +5 -0
  84. data/lib/generators/pu/pkg/feature/templates/app/policies/resource_policy.rb.tt +4 -0
  85. data/lib/generators/pu/pkg/feature/templates/app/presenters/resource_presenter.rb.tt +4 -0
  86. data/lib/generators/pu/pkg/feature/templates/lib/engine.rb.tt +8 -0
  87. data/lib/generators/pu/resource/conn/conn_generator.rb +54 -0
  88. data/lib/generators/pu/resource/conn/templates/.keep +0 -0
  89. data/lib/generators/pu/resource/conn/templates/app/controllers/resource_controller.rb.tt +3 -0
  90. data/lib/generators/pu/resource/conn/templates/app/policies/resource_policy.rb.tt +3 -0
  91. data/lib/generators/pu/resource/conn/templates/app/presenters/resource_presenter.rb.tt +3 -0
  92. data/lib/generators/pu/resource/model/USAGE +113 -0
  93. data/lib/generators/pu/resource/model/model_generator.rb +163 -0
  94. data/lib/generators/pu/resource/model/templates/controller.rb.tt +5 -0
  95. data/lib/generators/pu/resource/model/templates/create_table_migration.rb.tt +26 -0
  96. data/lib/generators/pu/resource/model/templates/model.rb.tt +53 -0
  97. data/lib/generators/pu/resource/model/templates/module.rb.tt +7 -0
  98. data/lib/generators/pu/resource/model/templates/policy.rb.tt +4 -0
  99. data/lib/generators/pu/resource/model/templates/presenter.rb.tt +4 -0
  100. data/lib/generators/pu/resource/scaffold/scaffold_generator.rb +219 -0
  101. data/lib/generators/pu/resource/scaffold/templates/app/controllers/admin_resources/resource_controller.rb.tt +7 -0
  102. data/lib/generators/pu/resource/scaffold/templates/app/controllers/entity_resources/resource_controller.rb.tt +7 -0
  103. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/admin/resource_policy.rb.tt +22 -0
  104. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/entity/resource_policy.rb.tt +22 -0
  105. data/lib/generators/pu/resource/scaffold/templates/app/policies/resources/resource_policy.rb.tt +13 -0
  106. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/admin_presenter.rb.tt +7 -0
  107. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/entity_presenter.rb.tt +7 -0
  108. data/lib/generators/pu/resource/scaffold/templates/app/resources/resource/presenter.rb.tt +23 -0
  109. data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.html.erb.tt +3 -0
  110. data/lib/generators/pu/resource/scaffold/templates/app/views/resources/resource/_resource.rabl +7 -0
  111. data/lib/generators/pu/rodauth/account_generator.rb +120 -0
  112. data/lib/generators/pu/rodauth/concerns/account_selector.rb +22 -0
  113. data/lib/generators/pu/rodauth/concerns/configuration.rb +211 -0
  114. data/lib/generators/pu/rodauth/concerns/feature_selector.rb +125 -0
  115. data/lib/generators/pu/rodauth/install_generator.rb +69 -0
  116. data/lib/generators/pu/rodauth/migration/active_record/account_expiration.erb +8 -0
  117. data/lib/generators/pu/rodauth/migration/active_record/active_sessions.erb +7 -0
  118. data/lib/generators/pu/rodauth/migration/active_record/audit_logging.erb +16 -0
  119. data/lib/generators/pu/rodauth/migration/active_record/base.erb +22 -0
  120. data/lib/generators/pu/rodauth/migration/active_record/disallow_password_reuse.erb +5 -0
  121. data/lib/generators/pu/rodauth/migration/active_record/email_auth.erb +8 -0
  122. data/lib/generators/pu/rodauth/migration/active_record/jwt_refresh.erb +7 -0
  123. data/lib/generators/pu/rodauth/migration/active_record/lockout.erb +13 -0
  124. data/lib/generators/pu/rodauth/migration/active_record/otp.erb +8 -0
  125. data/lib/generators/pu/rodauth/migration/active_record/password_expiration.erb +6 -0
  126. data/lib/generators/pu/rodauth/migration/active_record/recovery_codes.erb +6 -0
  127. data/lib/generators/pu/rodauth/migration/active_record/remember.erb +7 -0
  128. data/lib/generators/pu/rodauth/migration/active_record/reset_password.erb +8 -0
  129. data/lib/generators/pu/rodauth/migration/active_record/separate_passwords.erb +5 -0
  130. data/lib/generators/pu/rodauth/migration/active_record/single_session.erb +6 -0
  131. data/lib/generators/pu/rodauth/migration/active_record/sms_codes.erb +9 -0
  132. data/lib/generators/pu/rodauth/migration/active_record/verify_account.erb +8 -0
  133. data/lib/generators/pu/rodauth/migration/active_record/verify_login_change.erb +8 -0
  134. data/lib/generators/pu/rodauth/migration/active_record/webauthn.erb +13 -0
  135. data/lib/generators/pu/rodauth/migration/sequel/account_expiration.erb +7 -0
  136. data/lib/generators/pu/rodauth/migration/sequel/active_sessions.erb +8 -0
  137. data/lib/generators/pu/rodauth/migration/sequel/audit_logging.erb +17 -0
  138. data/lib/generators/pu/rodauth/migration/sequel/base.erb +25 -0
  139. data/lib/generators/pu/rodauth/migration/sequel/disallow_password_reuse.erb +6 -0
  140. data/lib/generators/pu/rodauth/migration/sequel/email_auth.erb +7 -0
  141. data/lib/generators/pu/rodauth/migration/sequel/jwt_refresh.erb +8 -0
  142. data/lib/generators/pu/rodauth/migration/sequel/lockout.erb +11 -0
  143. data/lib/generators/pu/rodauth/migration/sequel/otp.erb +7 -0
  144. data/lib/generators/pu/rodauth/migration/sequel/password_expiration.erb +5 -0
  145. data/lib/generators/pu/rodauth/migration/sequel/recovery_codes.erb +6 -0
  146. data/lib/generators/pu/rodauth/migration/sequel/remember.erb +6 -0
  147. data/lib/generators/pu/rodauth/migration/sequel/reset_password.erb +7 -0
  148. data/lib/generators/pu/rodauth/migration/sequel/separate_passwords.erb +6 -0
  149. data/lib/generators/pu/rodauth/migration/sequel/single_session.erb +5 -0
  150. data/lib/generators/pu/rodauth/migration/sequel/sms_codes.erb +8 -0
  151. data/lib/generators/pu/rodauth/migration/sequel/verify_account.erb +7 -0
  152. data/lib/generators/pu/rodauth/migration/sequel/verify_login_change.erb +7 -0
  153. data/lib/generators/pu/rodauth/migration/sequel/webauthn.erb +13 -0
  154. data/lib/generators/pu/rodauth/migration_generator.rb +190 -0
  155. data/lib/generators/pu/rodauth/templates/INSTRUCTIONS +52 -0
  156. data/lib/generators/pu/rodauth/templates/app/controllers/plugin_controller.rb.tt +6 -0
  157. data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +3 -0
  158. data/lib/generators/pu/rodauth/templates/app/mailers/account_mailer.rb.tt +4 -0
  159. data/lib/generators/pu/rodauth/templates/app/mailers/rodauth_mailer.rb.tt +62 -0
  160. data/lib/generators/pu/rodauth/templates/app/misc/account_rodauth_plugin.rb.tt +255 -0
  161. data/lib/generators/pu/rodauth/templates/app/misc/rodauth_app.rb.tt +24 -0
  162. data/lib/generators/pu/rodauth/templates/app/misc/rodauth_plugin.rb.tt +234 -0
  163. data/lib/generators/pu/rodauth/templates/app/models/account.rb.tt +40 -0
  164. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_email_auth_request_form.html.erb +7 -0
  165. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form.html.erb +26 -0
  166. data/lib/generators/pu/rodauth/templates/app/views/rodauth/_login_form_footer.html.erb +9 -0
  167. data/lib/generators/pu/rodauth/templates/app/views/rodauth/add_recovery_codes.html.erb +6 -0
  168. data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_login.html.erb +27 -0
  169. data/lib/generators/pu/rodauth/templates/app/views/rodauth/change_password.html.erb +27 -0
  170. data/lib/generators/pu/rodauth/templates/app/views/rodauth/close_account.html.erb +13 -0
  171. data/lib/generators/pu/rodauth/templates/app/views/rodauth/confirm_password.html.erb +11 -0
  172. data/lib/generators/pu/rodauth/templates/app/views/rodauth/create_account.html.erb +35 -0
  173. data/lib/generators/pu/rodauth/templates/app/views/rodauth/email_auth.html.erb +5 -0
  174. data/lib/generators/pu/rodauth/templates/app/views/rodauth/login.html.erb +4 -0
  175. data/lib/generators/pu/rodauth/templates/app/views/rodauth/logout.html.erb +14 -0
  176. data/lib/generators/pu/rodauth/templates/app/views/rodauth/multi_phase_login.html.erb +3 -0
  177. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_auth.html.erb +15 -0
  178. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_disable.html.erb +13 -0
  179. data/lib/generators/pu/rodauth/templates/app/views/rodauth/otp_setup.html.erb +41 -0
  180. data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_auth.html.erb +11 -0
  181. data/lib/generators/pu/rodauth/templates/app/views/rodauth/recovery_codes.html.erb +13 -0
  182. data/lib/generators/pu/rodauth/templates/app/views/rodauth/remember.html.erb +22 -0
  183. data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password.html.erb +19 -0
  184. data/lib/generators/pu/rodauth/templates/app/views/rodauth/reset_password_request.html.erb +17 -0
  185. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_auth.html.erb +15 -0
  186. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_confirm.html.erb +15 -0
  187. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_disable.html.erb +13 -0
  188. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_request.html.erb +5 -0
  189. data/lib/generators/pu/rodauth/templates/app/views/rodauth/sms_setup.html.erb +23 -0
  190. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_email_auth_request_form.html.erb +5 -0
  191. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form.html.erb +24 -0
  192. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/_login_form_footer.html.erb +7 -0
  193. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/add_recovery_codes.html.erb +16 -0
  194. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_login.html.erb +25 -0
  195. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/change_password.html.erb +25 -0
  196. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/close_account.html.erb +11 -0
  197. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/confirm_password.html.erb +19 -0
  198. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/create_account.html.erb +33 -0
  199. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/email_auth.html.erb +3 -0
  200. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/login.html.erb +5 -0
  201. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/logout.html.erb +10 -0
  202. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/multi_phase_login.html.erb +5 -0
  203. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_auth.html.erb +9 -0
  204. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_disable.html.erb +11 -0
  205. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/otp_setup.html.erb +32 -0
  206. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_auth.html.erb +9 -0
  207. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/recovery_codes.html.erb +11 -0
  208. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/remember.html.erb +18 -0
  209. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password.html.erb +17 -0
  210. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/reset_password_request.html.erb +17 -0
  211. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_auth.html.erb +9 -0
  212. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_confirm.html.erb +9 -0
  213. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_disable.html.erb +11 -0
  214. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_request.html.erb +3 -0
  215. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/sms_setup.html.erb +17 -0
  216. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_auth.html.erb +5 -0
  217. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_disable.html.erb +11 -0
  218. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/two_factor_manage.html.erb +26 -0
  219. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account.html.erb +15 -0
  220. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/unlock_account_request.html.erb +9 -0
  221. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account.html.erb +19 -0
  222. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_account_resend.html.erb +17 -0
  223. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/verify_login_change.html.erb +3 -0
  224. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_auth.html.erb +13 -0
  225. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_autofill.html.erb +10 -0
  226. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_remove.html.erb +21 -0
  227. data/lib/generators/pu/rodauth/templates/app/views/rodauth/tailwind/webauthn_setup.html.erb +21 -0
  228. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_auth.html.erb +5 -0
  229. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_disable.html.erb +13 -0
  230. data/lib/generators/pu/rodauth/templates/app/views/rodauth/two_factor_manage.html.erb +22 -0
  231. data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account.html.erb +15 -0
  232. data/lib/generators/pu/rodauth/templates/app/views/rodauth/unlock_account_request.html.erb +9 -0
  233. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account.html.erb +21 -0
  234. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_account_resend.html.erb +17 -0
  235. data/lib/generators/pu/rodauth/templates/app/views/rodauth/verify_login_change.html.erb +5 -0
  236. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_auth.html.erb +15 -0
  237. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_autofill.html.erb +10 -0
  238. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_remove.html.erb +23 -0
  239. data/lib/generators/pu/rodauth/templates/app/views/rodauth/webauthn_setup.html.erb +23 -0
  240. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/email_auth.text.erb +5 -0
  241. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/password_changed.text.erb +2 -0
  242. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password.text.erb +5 -0
  243. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/reset_password_notify.text.erb +2 -0
  244. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/unlock_account.text.erb +5 -0
  245. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_account.text.erb +4 -0
  246. data/lib/generators/pu/rodauth/templates/app/views/rodauth_mailer/verify_login_change.text.erb +10 -0
  247. data/lib/generators/pu/rodauth/templates/config/initializers/rodauth.rb.tt +3 -0
  248. data/lib/generators/pu/rodauth/templates/db/migrate/create_rodauth.rb.tt +13 -0
  249. data/lib/generators/pu/rodauth/views_generator.rb +125 -0
  250. data/lib/plutonium/auth/public_access.rb +17 -0
  251. data/lib/plutonium/auth/rodauth.rb +35 -0
  252. data/lib/plutonium/auth.rb +12 -0
  253. data/lib/plutonium/config.rb +11 -0
  254. data/lib/plutonium/core/.DS_Store +0 -0
  255. data/lib/plutonium/core/action.rb +46 -0
  256. data/lib/plutonium/core/actions/basic_action.rb +16 -0
  257. data/lib/plutonium/core/actions/collection.rb +33 -0
  258. data/lib/plutonium/core/actions/destroy_action.rb +21 -0
  259. data/lib/plutonium/core/actions/edit_action.rb +19 -0
  260. data/lib/plutonium/core/actions/interactive_action.rb +64 -0
  261. data/lib/plutonium/core/actions/new_action.rb +18 -0
  262. data/lib/plutonium/core/actions/show_action.rb +17 -0
  263. data/lib/plutonium/core/actions.rb +17 -0
  264. data/lib/plutonium/core/app_controller.rb +121 -0
  265. data/lib/plutonium/core/autodiscovery/discoverer.rb +15 -0
  266. data/lib/plutonium/core/autodiscovery/input_discoverer.rb +33 -0
  267. data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +33 -0
  268. data/lib/plutonium/core/autodiscovery.rb +13 -0
  269. data/lib/plutonium/core/controllers/authorizable.rb +56 -0
  270. data/lib/plutonium/core/controllers/bootable.rb +44 -0
  271. data/lib/plutonium/core/controllers/crud_actions.rb +128 -0
  272. data/lib/plutonium/core/controllers/entity_scoping.rb +69 -0
  273. data/lib/plutonium/core/controllers/interactive_actions.rb +210 -0
  274. data/lib/plutonium/core/controllers/presentable.rb +59 -0
  275. data/lib/plutonium/core/controllers.rb +16 -0
  276. data/lib/plutonium/core/definers/action_definer.rb +25 -0
  277. data/lib/plutonium/core/definers/field_definer.rb +19 -0
  278. data/lib/plutonium/core/definers/input_definer.rb +37 -0
  279. data/lib/plutonium/core/definers/renderer_definer.rb +35 -0
  280. data/lib/plutonium/core/definers.rb +14 -0
  281. data/lib/plutonium/core/fields/inputs/association_input.rb +26 -0
  282. data/lib/plutonium/core/fields/inputs/basic_input.rb +42 -0
  283. data/lib/plutonium/core/fields/inputs/belongs_to_input.rb +15 -0
  284. data/lib/plutonium/core/fields/inputs/factory.rb +58 -0
  285. data/lib/plutonium/core/fields/inputs/has_many_input.rb +15 -0
  286. data/lib/plutonium/core/fields/inputs/noop_input.rb +19 -0
  287. data/lib/plutonium/core/fields/inputs.rb +18 -0
  288. data/lib/plutonium/core/fields/renderers/association_renderer.rb +25 -0
  289. data/lib/plutonium/core/fields/renderers/basic_renderer.rb +27 -0
  290. data/lib/plutonium/core/fields/renderers/factory.rb +52 -0
  291. data/lib/plutonium/core/fields/renderers.rb +15 -0
  292. data/lib/plutonium/core/fields.rb +12 -0
  293. data/lib/plutonium/core/ui/collection.rb +14 -0
  294. data/lib/plutonium/core/ui/detail.rb +11 -0
  295. data/lib/plutonium/core/ui/form.rb +11 -0
  296. data/lib/plutonium/core/ui.rb +13 -0
  297. data/lib/plutonium/core.rb +16 -0
  298. data/lib/plutonium/helpers/action_buttons_helper.rb +32 -0
  299. data/lib/plutonium/helpers/application_helper.rb +22 -0
  300. data/lib/plutonium/helpers/attachment_helper.rb +62 -0
  301. data/lib/plutonium/helpers/content_helper.rb +66 -0
  302. data/lib/plutonium/helpers/display_helper.rb +83 -0
  303. data/lib/plutonium/helpers/form_helper.rb +24 -0
  304. data/lib/plutonium/helpers/menu_helper.rb +69 -0
  305. data/lib/plutonium/helpers/pagination_helper.rb +9 -0
  306. data/lib/plutonium/helpers/turbo_helper.rb +13 -0
  307. data/lib/plutonium/helpers/turbo_stream_actions_helper.rb +9 -0
  308. data/lib/plutonium/helpers.rb +31 -0
  309. data/lib/plutonium/initializers/TODO +2 -0
  310. data/lib/plutonium/initializers/pagy.rb +5 -0
  311. data/lib/plutonium/initializers/patches.rb +2 -0
  312. data/lib/plutonium/initializers/rabl.rb +60 -0
  313. data/lib/plutonium/initializers/simple_form.rb +405 -0
  314. data/lib/plutonium/lib/after_commit.rb +34 -0
  315. data/lib/plutonium/lib/bit_flags.rb +36 -0
  316. data/lib/plutonium/packaging/app.rb +125 -0
  317. data/lib/plutonium/packaging/feature.rb +18 -0
  318. data/lib/plutonium/packaging/package.rb +22 -0
  319. data/lib/plutonium/packaging.rb +9 -0
  320. data/lib/plutonium/policy/initializer.rb +22 -0
  321. data/lib/plutonium/policy/scope.rb +19 -0
  322. data/lib/plutonium/policy.rb +8 -0
  323. data/lib/plutonium/preserved__/field.rb +65 -0
  324. data/lib/plutonium/preserved__/input.rb +93 -0
  325. data/lib/plutonium/reactor/core.rb +61 -0
  326. data/lib/plutonium/reactor/resource_context.rb +15 -0
  327. data/lib/plutonium/reactor/resource_controller.rb +108 -0
  328. data/lib/plutonium/reactor/resource_interaction.rb +8 -0
  329. data/lib/plutonium/reactor/resource_policy.rb +105 -0
  330. data/lib/plutonium/reactor/resource_presenter.rb +42 -0
  331. data/lib/plutonium/reactor/resource_record.rb +123 -0
  332. data/lib/plutonium/reactor.rb +13 -0
  333. data/lib/plutonium/refinements/parameter_refinements.rb +26 -0
  334. data/lib/plutonium/simple_form_components/attachment_component.rb +77 -0
  335. data/lib/plutonium/simple_form_components/input_group_component.rb +14 -0
  336. data/lib/plutonium/version.rb +3 -0
  337. data/lib/plutonium.rb +31 -0
  338. data/plutonium.gemspec +47 -0
  339. data/public/.keep +0 -0
  340. data/public/plutonium-assets/application.css +24280 -0
  341. data/public/plutonium-assets/application.js +31420 -0
  342. data/public/plutonium-assets/fonts/bootstrap-icons.woff +0 -0
  343. data/public/plutonium-assets/fonts/bootstrap-icons.woff2 +0 -0
  344. data/public/plutonium-assets/logo.png +0 -0
  345. data/sig/plutonium.rbs +4 -0
  346. metadata +519 -0
@@ -0,0 +1,163 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plutonium_generators"
4
+
5
+ require "rails/generators"
6
+ require "rails/generators/active_record/model/model_generator"
7
+
8
+ module Pu
9
+ module Resource
10
+ class ModelGenerator < ActiveRecord::Generators::ModelGenerator
11
+ include PlutoniumGenerators::Generator
12
+
13
+ source_root File.expand_path("templates", __dir__)
14
+
15
+ remove_hook_for :test_framework
16
+ remove_task :create_migration_file
17
+ remove_task :create_model_file
18
+ remove_task :create_module_file
19
+
20
+ class_option :package, type: :string
21
+
22
+ def run_create_module
23
+ create_module_file
24
+ end
25
+
26
+ def run_create_model
27
+ create_model_file
28
+ end
29
+
30
+ def run_create_migration
31
+ create_migration_file
32
+ end
33
+
34
+ def create_controller
35
+ template "controller.rb", File.join("app/controllers", class_path, "#{file_name.pluralize}_controller.rb")
36
+ end
37
+
38
+ def create_policy
39
+ template "policy.rb", File.join("app/policies", class_path, "#{file_name}_policy.rb")
40
+ end
41
+
42
+ def create_presenter
43
+ template "presenter.rb", File.join("app/presenters", class_path, "#{file_name}_presenter.rb")
44
+ end
45
+
46
+ # https://github.com/rails/rails/blob/main/railties/lib/rails/generators/generated_attribute.rb#L7
47
+
48
+ private
49
+
50
+ def parse_attributes!
51
+ self.attributes = (attributes || []).map do |attr|
52
+ GeneratedAttribute.parse(name, attr)
53
+ end
54
+ end
55
+
56
+ def name
57
+ @pu_name ||= begin
58
+ @selected_feature = select_feature selected_feature
59
+ @name = [main_app? ? nil : selected_feature.underscore, super.singularize.underscore].compact.join "/"
60
+ set_destination_root!
61
+ @name
62
+ end
63
+ end
64
+
65
+ def feature_package_name
66
+ main_app? ? nil : selected_feature.classify
67
+ end
68
+
69
+ def main_app?
70
+ selected_feature == "main_app"
71
+ end
72
+
73
+ def selected_feature
74
+ @selected_feature || options[:feature]
75
+ end
76
+
77
+ def set_destination_root!
78
+ @destination_stack = [File.join(Rails.root, main_app? ? "" : "packages/#{selected_feature.underscore}")]
79
+ end
80
+
81
+ class GeneratedAttribute < Rails::Generators::GeneratedAttribute
82
+ class << self
83
+ def parse(model_name, column_definition)
84
+ name, type, index_type = column_definition.split(":")
85
+
86
+ # if user provided "name:index" instead of "name:string:index"
87
+ # type should be set blank so GeneratedAttribute's constructor
88
+ # could set it to :string
89
+ index_type, type = type, nil if valid_index_type?(type)
90
+
91
+ type, attr_options = *parse_type_and_options(type)
92
+ type = type.to_sym if type
93
+
94
+ if dangerous_name?(name)
95
+ raise Error, "Could not generate field '#{name}', as it is already defined by Active Record."
96
+ end
97
+
98
+ if type && !valid_type?(type)
99
+ raise Error, "Could not generate field '#{name}' with unknown type '#{type}'."
100
+ end
101
+
102
+ if index_type && !valid_index_type?(index_type)
103
+ raise Error, "Could not generate field '#{name}' with unknown index '#{index_type}'."
104
+ end
105
+
106
+ if type && reference?(type)
107
+ if Rails::Generators::GeneratedAttribute::UNIQ_INDEX_OPTIONS.include?(index_type)
108
+ attr_options[:index] = {unique: true}
109
+ end
110
+
111
+ if name.include? "/"
112
+ attr_options[:to_table] = name.tr("/", "_").pluralize.to_sym
113
+ if (shared_namespace = find_shared_namespace(model_name, name, separator: "/"))
114
+ name = name.sub "#{shared_namespace}/", ""
115
+ end
116
+
117
+ name = name.tr "/", "_"
118
+ end
119
+ end
120
+
121
+ new(name, type, index_type, attr_options)
122
+ end
123
+
124
+ private
125
+
126
+ def find_shared_namespace(model1, model2, separator: "::")
127
+ # Split the model names by separator to get the namespaces and class names as arrays
128
+ parts1 = model1.split(separator)
129
+ parts2 = model2.split(separator)
130
+
131
+ # Initialize an array to hold the shared namespace parts
132
+ shared_namespace = []
133
+
134
+ # Iterate over the shorter of the two arrays
135
+ [parts1.length, parts2.length].min.times do |i|
136
+ if parts1[i] == parts2[i]
137
+ shared_namespace << parts1[i]
138
+ else
139
+ break
140
+ end
141
+ end
142
+
143
+ # Return the shared namespace, joined by '::' or nil if there's no shared namespace
144
+ shared_namespace.empty? ? nil : shared_namespace.join(separator)
145
+ end
146
+ end
147
+
148
+ def required?
149
+ # TODO: make it such that we can override fields as nullable
150
+ super || true
151
+ end
152
+
153
+ def options_for_migration
154
+ super.tap do |options|
155
+ if options[:to_table]
156
+ options[:foreign_key] = {to_table: options.delete(:to_table)}
157
+ end
158
+ end
159
+ end
160
+ end
161
+ end
162
+ end
163
+ end
@@ -0,0 +1,5 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name.pluralize %>Controller < <%= [feature_package_name, "ResourceController"].join "::" %>
3
+ controller_for ::<%= class_name %>
4
+ end
5
+ <% end -%>
@@ -0,0 +1,26 @@
1
+ class <%= migration_class_name %> < ActiveRecord::Migration[<%= ActiveRecord::Migration.current_version %>]
2
+ def change
3
+ create_table :<%= table_name %><%= primary_key_type %> do |t|
4
+ <% attributes.each do |attribute| -%>
5
+ <% if attribute.password_digest? -%>
6
+ t.string :password_digest<%= attribute.inject_options %>
7
+ <% elsif attribute.token? -%>
8
+ t.string :<%= attribute.name %><%= attribute.inject_options %>
9
+ <% elsif attribute.reference? -%>
10
+ t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %><%= foreign_key_type %>
11
+ <% elsif !attribute.virtual? -%>
12
+ t.<%= attribute.type %> :<%= attribute.name %><%= attribute.inject_options %>
13
+ <% end -%>
14
+ <% end -%>
15
+ <% if options[:timestamps] %>
16
+ t.timestamps
17
+ <% end -%>
18
+ end
19
+ <% attributes.select(&:token?).each do |attribute| -%>
20
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>, unique: true
21
+ <% end -%>
22
+ <% attributes_with_index.each do |attribute| -%>
23
+ add_index :<%= table_name %>, :<%= attribute.index_name %><%= attribute.inject_index_options %>
24
+ <% end -%>
25
+ end
26
+ end
@@ -0,0 +1,53 @@
1
+ <% if class_path.last.present? -%>
2
+ require_relative "../<%= class_path.last.underscore %>"
3
+
4
+ <% end -%>
5
+ <% module_namespacing do -%>
6
+ class <%= class_name %> < <%= [feature_package_name, "ResourceRecord"].join "::" %>
7
+ # add concerns above.
8
+
9
+ # add model configurations above.
10
+
11
+ <% attributes.select(&:reference?).each do |attribute| -%>
12
+ belongs_to :<%= attribute.name %><%= ", polymorphic: true" if attribute.polymorphic? %>
13
+ <% end -%>
14
+ # add belongs_to associations above.
15
+
16
+ # add has_one associations above.
17
+
18
+ # add has_many associations above.
19
+
20
+ <% attributes.select(&:attachment?).each do |attribute| -%>
21
+ has_one_attached :<%= attribute.name %>
22
+ <% end -%>
23
+ <% attributes.select(&:attachments?).each do |attribute| -%>
24
+ has_many_attached :<%= attribute.name %>
25
+ <% end -%>
26
+ # add attachments above.
27
+
28
+ <% attributes.select(&:rich_text?).each do |attribute| -%>
29
+ has_rich_text :<%= attribute.name %>
30
+ <% end -%>
31
+ <% attributes.select(&:token?).each do |attribute| -%>
32
+ has_secure_token<% if attribute.name != "token" %> :<%= attribute.name %><% end %>
33
+ <% end -%>
34
+ <% if attributes.any?(&:password_digest?) -%>
35
+ has_secure_password
36
+ <% end -%>
37
+ # add misc attribute macros above.
38
+
39
+ # add scopes above.
40
+
41
+ <% attributes.select(&:required?).each do |attribute| -%>
42
+ <%- next if attribute.reference? || attribute.rich_text? || attribute.token? || attribute.password_digest? -%>
43
+ validates :<%= attribute.name %>, presence: true
44
+ <% end -%>
45
+ # add validations above.
46
+
47
+ # add callbacks above.
48
+
49
+ # add delegations above.
50
+
51
+ # add methods above.
52
+ end
53
+ <% end -%>
@@ -0,0 +1,7 @@
1
+ <% module_namespacing do -%>
2
+ module <%= class_path.map(&:camelize).join("::") %>
3
+ def self.table_name_prefix
4
+ "<%= namespaced? ? namespaced_class_path.join("_") : class_path.join("_") %>_"
5
+ end
6
+ end
7
+ <% end -%>
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Policy < <%= [feature_package_name, "ResourcePolicy"].join "::" %>
3
+ end
4
+ <% end -%>
@@ -0,0 +1,4 @@
1
+ <% module_namespacing do -%>
2
+ class <%= class_name %>Presenter < <%= [feature_package_name, "ResourcePresenter"].join "::" %>
3
+ end
4
+ <% end -%>
@@ -0,0 +1,219 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "plutonium_generators"
4
+
5
+ module Pu
6
+ module Resource
7
+ class ScaffoldGenerator < Rails::Generators::Base
8
+ include PlutoniumGenerators::Generator
9
+
10
+ source_root File.expand_path("templates", __dir__)
11
+
12
+ desc "Scaffold a resource"
13
+
14
+ argument :name
15
+ class_option :env, type: :string, default: "all"
16
+
17
+ def start
18
+ setup_models
19
+ scaffold_route
20
+ scaffold_controllers
21
+ scaffold_views
22
+ scaffold_policies
23
+ scaffold_presenters
24
+ rescue => e
25
+ exception "Resource scaffold failed:", e
26
+ end
27
+
28
+ protected
29
+
30
+ def setup_models
31
+ return if resource_class < Pu::ResourceModel
32
+
33
+ insert_into_file "app/models/#{resource_path}.rb",
34
+ indent("include ResourceModel\n", 2),
35
+ before: /.*# pu:add concerns.*\n/
36
+ end
37
+
38
+ def scaffold_route
39
+ route_exists = File.read("config/routes.rb").match?(/concern :#{resource_name_underscored}_routes do/)
40
+ return if route_exists && skip_existing?
41
+
42
+ if resource_module_underscored.present?
43
+ indentation = " resources :#{resource_name_plural_underscored}, ".size
44
+ module_config = [
45
+ "module: '#{resource_module_underscored}'",
46
+ "controller: '#{resource_attribute_plural}'",
47
+ "path: '#{resources_path}'"
48
+ ].map { |c| indent c, indentation }.join(",\n")
49
+ module_config = ",\n#{module_config}"
50
+ end
51
+ route = <<~TILDE
52
+ concern :#{resource_name_underscored}_routes do
53
+ #{resource_name_underscored}_concerns = %i[]
54
+ #{resource_name_underscored}_concerns += shared_resource_concerns
55
+ resources :#{resource_name_plural_underscored}, concerns: #{resource_name_underscored}_concerns#{module_config} do
56
+ # pu:routes:#{resource_name_plural_underscored}
57
+ end
58
+ end
59
+ entity_resource_routes << :#{resource_name_underscored}_routes
60
+ admin_resource_routes << :#{resource_name_underscored}_routes
61
+ TILDE
62
+
63
+ route.gsub!(/entity_resource_routes << :#{resource_name_underscored}_routes\n/, "") if admin_only?
64
+ route = indent route, 2
65
+
66
+ if route_exists
67
+ gsub_file "config/routes.rb",
68
+ /.*concern :#{resource_name_underscored}_routes do(.|\n)*<< :#{resource_name_underscored}_routes\n/,
69
+ route
70
+ else
71
+ insert_into_file "config/routes.rb",
72
+ "#{route}\n",
73
+ before: /.*# pu:add #{entity? ? "entity" : "resource"} routes above.*/
74
+ end
75
+ end
76
+
77
+ def scaffold_controllers
78
+ template "app/controllers/admin_resources/resource_controller.rb",
79
+ "app/controllers/admin_resources/#{resources_path}_controller.rb", skip: skip_existing?
80
+
81
+ return if admin_only?
82
+
83
+ template "app/controllers/entity_resources/resource_controller.rb",
84
+ "app/controllers/entity_resources/#{resources_path}_controller.rb", skip: skip_existing?
85
+ end
86
+
87
+ def scaffold_views
88
+ %w[entity_resources admin_resources].each do |subdir|
89
+ next if subdir != "admin_resources" && admin_only?
90
+
91
+ create_file "app/views/#{subdir}/#{resources_path}/.keep", ""
92
+
93
+ # template 'app/views/resources/resource/_resource.html.erb',
94
+ # "app/views/#{subdir}/#{resources_path}/_#{resource_attribute}.html.erb", skip: skip_existing?
95
+ # copy_file 'app/views/resources/resource/_resource.rabl',
96
+ # "app/views/#{subdir}/#{resources_path}/_#{resource_attribute}.rabl", skip: skip_existing?
97
+ end
98
+ end
99
+
100
+ def scaffold_policies
101
+ template "app/policies/resources/resource_policy.rb",
102
+ "app/policies/resources/#{resource_path}_policy.rb", skip: skip_existing?
103
+
104
+ template "app/policies/resources/admin/resource_policy.rb",
105
+ "app/policies/resources/admin/#{resource_path}_policy.rb", skip: skip_existing?
106
+
107
+ return if admin_only?
108
+
109
+ template "app/policies/resources/entity/resource_policy.rb",
110
+ "app/policies/resources/entity/#{resource_path}_policy.rb", skip: skip_existing?
111
+ end
112
+
113
+ def scaffold_presenters
114
+ template "app/resources/resource/presenter.rb",
115
+ "app/resources/#{resources_path}/presenter.rb", skip: skip_existing?
116
+ template "app/resources/resource/admin_presenter.rb",
117
+ "app/resources/#{resources_path}/admin_presenter.rb", skip: skip_existing?
118
+
119
+ return if admin_only?
120
+
121
+ template "app/resources/resource/entity_presenter.rb",
122
+ "app/resources/#{resources_path}/entity_presenter.rb", skip: skip_existing?
123
+ end
124
+
125
+ def create_fields
126
+ @create_fields ||= (resource_class.attribute_names - %w[id slug created_at updated_at]).map(&:to_sym)
127
+ end
128
+
129
+ def read_fields
130
+ @read_fields ||= begin
131
+ attribute_names = resource_class.attribute_names.reject { |attr| associations[attr] }
132
+ attribute_names = attribute_names.map(&:to_sym)
133
+ attribute_names.insert(1, entity_assoc.name) if entity_assoc
134
+ attribute_names - %i[]
135
+ end
136
+ end
137
+
138
+ def associations
139
+ @associations ||= resource_class.reflect_on_all_associations.map do |assoc|
140
+ [assoc.foreign_key, assoc]
141
+ end.compact.to_h.with_indifferent_access
142
+ end
143
+
144
+ def entity_assoc(source_class = nil)
145
+ @entity_assoc ||= {}
146
+
147
+ source_class ||= resource_class
148
+ @entity_assoc[source_class] ||= begin
149
+ matcher = lambda do |assoc|
150
+ assoc_class = assoc.class_name.constantize
151
+ assoc_class == Entity || assoc_class < Entity
152
+ rescue
153
+ false
154
+ end
155
+
156
+ assoc = source_class.reflect_on_all_associations(:belongs_to).find(&matcher)
157
+ assoc ||= source_class.reflect_on_all_associations(:has_one).find(&matcher)
158
+ assoc
159
+ end
160
+ end
161
+
162
+ def assoc?(attr)
163
+ resource_class.reflect_on_association(attr)
164
+ end
165
+
166
+ def admin_only?
167
+ entity? || entity_assoc.nil?
168
+ end
169
+
170
+ def entity?
171
+ resource_class == Entity || resource_class < Entity
172
+ end
173
+
174
+ def resource_name
175
+ @resource_name ||= name.classify
176
+ end
177
+
178
+ def resource_name_plural
179
+ @resource_name_plural ||= resource_name.pluralize
180
+ end
181
+
182
+ def resource_class
183
+ @resource_class ||= resource_name.constantize
184
+ end
185
+
186
+ def resource_name_underscored
187
+ @resource_name_underscored ||= resource_name.underscore.tr("/", "_")
188
+ end
189
+
190
+ def resource_name_plural_underscored
191
+ @resource_name_plural_underscored ||= resource_name_plural.underscore.tr("/", "_")
192
+ end
193
+
194
+ def resource_path
195
+ @resource_path ||= resource_name.underscore
196
+ end
197
+
198
+ def resources_path
199
+ @resources_path ||= resource_name_plural.underscore
200
+ end
201
+
202
+ def resource_attribute
203
+ @resource_attribute ||= resource_name.demodulize.underscore
204
+ end
205
+
206
+ def resource_attribute_plural
207
+ @resource_attribute_plural ||= resource_name_plural.demodulize.underscore
208
+ end
209
+
210
+ def resource_module_underscored
211
+ @resource_module_underscored ||= resource_name.deconstantize.underscore
212
+ end
213
+
214
+ def skip_existing?
215
+ !options[:force]
216
+ end
217
+ end
218
+ end
219
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module AdminResources
4
+ class <%= resource_name_plural %>Controller < ResourceController
5
+ controller_for ::<%= resource_name %>
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module EntityResources
4
+ class <%= resource_name_plural %>Controller < ResourceController
5
+ controller_for ::<%= resource_name %>
6
+ end
7
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resources
4
+ module Admin
5
+ class <%= resource_name %>Policy < Resources::Admin::ResourcePolicy
6
+ include Resources::<%= resource_name %>Policy
7
+
8
+ class Scope
9
+ include Pu::Policy::Initializer
10
+
11
+ def resolve
12
+ scope = ::<%= resource_name %>.all
13
+ scope = @context.parent.<%= resource_name_plural_underscored %> if @context.parent.present?
14
+ scope
15
+ <%- if entity_assoc -%>
16
+ .includes(:<%= entity_assoc.name %>)
17
+ <%- end -%>
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,22 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resources
4
+ module Entity
5
+ class <%= resource_name %>Policy < Resources::Entity::ResourcePolicy
6
+ include Resources::<%= resource_name %>Policy
7
+
8
+ class Scope
9
+ include Pu::Policy::Initializer
10
+
11
+ def resolve
12
+ @context
13
+ .parent
14
+ .<%= resource_name_plural_underscored %>
15
+ <%- if entity_assoc -%>
16
+ .includes(:<%= entity_assoc.name %>)
17
+ <%- end -%>
18
+ end
19
+ end
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,13 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Resources
4
+ module <%= resource_name %>Policy
5
+ def permitted_attributes_for_read
6
+ <%= read_fields.inspect %>
7
+ end
8
+
9
+ def permitted_attributes_for_create
10
+ <%= create_fields.inspect %>
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= resource_name_plural %>
4
+ class AdminPresenter < Presenter
5
+ include AdminResourcePresenter
6
+ end
7
+ end
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= resource_name_plural %>
4
+ class EntityPresenter < Presenter
5
+ include EntityResourcePresenter
6
+ end
7
+ end
@@ -0,0 +1,23 @@
1
+ # frozen_string_literal: true
2
+
3
+ module <%= resource_name_plural %>
4
+ class Presenter < ResourcePresenter
5
+ private
6
+
7
+ def collection_fields
8
+ <%= (read_fields - %i[id]).inspect %>
9
+ end
10
+
11
+ def detail_fields
12
+ <%= (read_fields - %i[id]).inspect %>
13
+ end
14
+
15
+ def form_inputs
16
+ <%= create_fields.inspect %>
17
+ end
18
+
19
+ def associations_list
20
+ []
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ <%% raise NotImplementedError, "Only Builders::Details is supported" unless <%= resource_name_underscored %>.is_a? ::Pu::UI::Builder::Detail %>
2
+
3
+ <%%= render 'details', details: <%= resource_name_underscored %> %>
@@ -0,0 +1,7 @@
1
+ # frozen_string_literal: true
2
+
3
+ attributes :id
4
+ attributes(*permitted_attributes)
5
+ attributes :created_at, :updated_at
6
+
7
+ node(:url) { |resource| url_for(adapt_route_args(resource)) }