plutonium 0.14.0 → 0.15.0.pre.rc1
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.
- checksums.yaml +4 -4
- data/README copy.md +1 -1
- data/README.md +1 -1
- data/app/assets/plutonium.css +1 -1
- data/app/views/{application → plutonium}/_resource_header.html copy.erb +1 -1
- data/app/views/{application → plutonium}/_resource_header.html.erb +1 -1
- data/app/views/{application → plutonium}/_resource_sidebar.html.erb +2 -0
- data/app/views/resource/_resource_details.html.erb +1 -36
- data/app/views/resource/_resource_form.html.erb +1 -5
- data/app/views/resource/_resource_table.html.erb +315 -85
- data/app/views/resource/edit.html.erb +1 -5
- data/app/views/resource/index.html.erb +1 -5
- data/app/views/resource/new.html.erb +1 -5
- data/app/views/resource/show.html.erb +1 -5
- data/config/initializers/pagy.rb +1 -0
- data/config/initializers/rabl.rb +27 -20
- data/gemfiles/rails_7.gemfile.lock +5 -1
- data/lib/generators/pu/core/assets/assets_generator.rb +2 -2
- data/lib/generators/pu/core/install/install_generator.rb +0 -3
- data/lib/generators/pu/core/install/templates/app/controllers/plutonium_controller.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/controllers/resource_controller.rb.tt +21 -1
- data/lib/generators/pu/core/install/templates/app/definitions/resource_definition.rb.tt +2 -0
- data/lib/generators/pu/core/install/templates/app/models/resource_record.rb.tt +0 -2
- data/lib/generators/pu/core/install/templates/config/initializers/plutonium.rb +5 -2
- data/lib/generators/pu/eject/shell/shell_generator.rb +2 -2
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +19 -0
- data/lib/generators/pu/lib/plutonium_generators/concerns/logger.rb +1 -1
- data/lib/generators/pu/lib/plutonium_generators/generator.rb +5 -3
- data/lib/generators/pu/lib/plutonium_generators/model_generator_base.rb +26 -2
- data/lib/generators/pu/pkg/{feature/feature_generator.rb → package/package_generator.rb} +4 -4
- data/lib/generators/pu/pkg/{feature → package}/templates/app/controllers/resource_controller.rb.tt +0 -2
- data/lib/generators/pu/pkg/package/templates/app/definitions/resource_definition.rb.tt +4 -0
- data/lib/generators/pu/pkg/package/templates/app/query_objects/resource_query_object.rb.tt +4 -0
- data/lib/generators/pu/pkg/{app/app_generator.rb → portal/portal_generator.rb} +10 -8
- data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/concerns/controller.rb.tt +3 -7
- data/lib/generators/pu/pkg/{app → portal}/templates/app/controllers/dashboard_controller.rb.tt +1 -1
- data/lib/generators/pu/pkg/portal/templates/app/controllers/plutonium_controller.rb.tt +5 -0
- data/lib/generators/pu/pkg/{app/templates/app/controllers/controller.rb.tt → portal/templates/app/controllers/resource_controller.rb.tt} +1 -1
- data/lib/generators/pu/pkg/portal/templates/app/definitions/resource_definition.rb.tt +4 -0
- data/lib/generators/pu/pkg/{app → portal}/templates/app/views/package/dashboard/index.html.erb +2 -1
- data/lib/generators/pu/res/conn/conn_generator.rb +78 -3
- data/lib/generators/pu/res/conn/templates/app/controllers/resource_controller.rb.tt +1 -1
- data/lib/generators/pu/res/conn/templates/app/definitions/resource_definition.rb.tt +3 -0
- data/lib/generators/pu/res/conn/templates/app/policies/resource_policy.rb.tt +29 -1
- data/lib/generators/pu/res/conn/templates/app/presenters/resource_presenter.rb.tt +1 -1
- data/lib/generators/pu/res/conn/templates/app/query_objects/resource_query_object.rb.tt +1 -1
- data/lib/generators/pu/res/model/model_generator.rb +0 -7
- data/lib/generators/pu/res/model/templates/model.rb.tt +4 -1
- data/lib/generators/pu/res/scaffold/scaffold_generator.rb +22 -4
- data/lib/generators/pu/res/scaffold/templates/controller.rb.tt +0 -1
- data/lib/generators/pu/res/scaffold/templates/definition.rb.tt +4 -0
- data/lib/generators/pu/res/scaffold/templates/policy.rb.tt +2 -2
- data/lib/generators/pu/rodauth/templates/app/controllers/rodauth_controller.rb.tt +1 -1
- data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +270 -0
- data/lib/plutonium/action/README.md +0 -0
- data/lib/plutonium/action/base.rb +103 -0
- data/lib/plutonium/action/interactive.rb +117 -0
- data/lib/plutonium/action/route_options.rb +65 -0
- data/lib/plutonium/action/simple.rb +8 -0
- data/lib/plutonium/auth.rb +1 -1
- data/lib/plutonium/configuration.rb +130 -0
- data/lib/plutonium/core/actions/collection.rb +1 -1
- data/lib/plutonium/core/associations/renderers/factory.rb +3 -1
- data/lib/plutonium/core/autodiscovery/association_renderer_discoverer.rb +1 -1
- data/lib/plutonium/core/autodiscovery/input_discoverer.rb +1 -1
- data/lib/plutonium/core/autodiscovery/renderer_discoverer.rb +1 -1
- data/lib/plutonium/core/controller.rb +110 -0
- data/lib/plutonium/core/controllers/authorizable.rb +12 -35
- data/lib/plutonium/core/controllers/bootable.rb +38 -7
- data/lib/plutonium/core/controllers/entity_scoping.rb +6 -2
- data/lib/plutonium/core/fields/renderers/association_renderer.rb +1 -1
- data/lib/plutonium/core/ui/collection.rb +1 -1
- data/lib/plutonium/core/ui/detail.rb +1 -1
- data/lib/plutonium/core/ui/form.rb +1 -1
- data/lib/plutonium/definition/actions.rb +50 -0
- data/lib/plutonium/definition/base.rb +92 -0
- data/lib/plutonium/definition/config_attr.rb +30 -0
- data/lib/plutonium/definition/defineable_props.rb +96 -0
- data/lib/plutonium/definition/search.rb +21 -0
- data/lib/plutonium/engine/validator.rb +30 -0
- data/lib/plutonium/engine.rb +25 -0
- data/lib/plutonium/helpers/assets_helper.rb +73 -20
- data/lib/plutonium/helpers/form_helper.rb +1 -3
- data/lib/plutonium/interaction/README.md +369 -0
- data/lib/plutonium/interaction/base.rb +75 -0
- data/lib/plutonium/interaction/concerns/presentable.rb +61 -0
- data/lib/plutonium/interaction/concerns/workflow_dsl.rb +82 -0
- data/lib/plutonium/interaction/outcome.rb +129 -0
- data/lib/plutonium/interaction/response/base.rb +63 -0
- data/lib/plutonium/interaction/response/null.rb +33 -0
- data/lib/plutonium/interaction/response/redirect.rb +30 -0
- data/lib/plutonium/interaction/response/render.rb +28 -0
- data/lib/plutonium/lib/bit_flags.rb +70 -9
- data/lib/plutonium/lib/overlayed_hash.rb +86 -0
- data/lib/plutonium/lib/smart_cache.rb +171 -0
- data/lib/plutonium/models/has_cents.rb +170 -0
- data/lib/plutonium/{pkg/base.rb → package/engine.rb} +10 -2
- data/lib/plutonium/{application → portal}/controller.rb +3 -11
- data/lib/plutonium/{application → portal}/dynamic_controllers.rb +4 -4
- data/lib/plutonium/portal/engine.rb +15 -0
- data/lib/plutonium/railtie.rb +35 -15
- data/lib/plutonium/reloader.rb +71 -29
- data/lib/plutonium/resource/controller.rb +51 -34
- data/lib/plutonium/resource/controllers/authorizable.rb +128 -0
- data/lib/plutonium/{core → resource}/controllers/crud_actions.rb +23 -22
- data/lib/plutonium/resource/controllers/defineable.rb +26 -0
- data/lib/plutonium/{core → resource}/controllers/interactive_actions.rb +12 -12
- data/lib/plutonium/resource/controllers/presentable.rb +41 -0
- data/lib/plutonium/resource/controllers/queryable.rb +44 -0
- data/lib/plutonium/resource/definition.rb +6 -0
- data/lib/plutonium/resource/policy.rb +25 -13
- data/lib/plutonium/resource/query_object.rb +50 -51
- data/lib/plutonium/resource/record.rb +6 -89
- data/lib/plutonium/resource/register.rb +82 -0
- data/lib/plutonium/routing/mapper_extensions.rb +1 -1
- data/lib/plutonium/routing/resource_registration.rb +1 -1
- data/lib/plutonium/routing/route_set_extensions.rb +6 -18
- data/lib/plutonium/ui/action_button.rb +125 -0
- data/lib/plutonium/ui/breadcrumbs.rb +163 -0
- data/lib/plutonium/ui/component/base.rb +13 -0
- data/lib/plutonium/ui/component/behaviour.rb +38 -0
- data/lib/plutonium/ui/component/kit.rb +31 -0
- data/lib/plutonium/ui/component/methods.rb +54 -0
- data/lib/plutonium/ui/display/base.rb +25 -0
- data/lib/plutonium/ui/display/component/association.rb +26 -0
- data/lib/plutonium/ui/display/resource.rb +77 -0
- data/lib/plutonium/ui/display/theme.rb +27 -0
- data/lib/plutonium/ui/dyna_frame/content.rb +20 -0
- data/lib/plutonium/ui/empty_card.rb +20 -0
- data/lib/plutonium/ui/form/base.rb +37 -0
- data/lib/plutonium/ui/form/resource.rb +75 -0
- data/lib/plutonium/ui/form/theme.rb +42 -0
- data/lib/plutonium/ui/page/base.rb +112 -0
- data/lib/plutonium/ui/page/edit.rb +23 -0
- data/lib/plutonium/ui/page/index.rb +27 -0
- data/lib/plutonium/ui/page/new.rb +23 -0
- data/lib/plutonium/ui/page/show.rb +27 -0
- data/lib/plutonium/ui/page_header.rb +49 -0
- data/lib/plutonium/ui/table/base.rb +13 -0
- data/lib/plutonium/ui/table/components/pagy_info.rb +70 -0
- data/lib/plutonium/ui/table/components/pagy_page_info.rb +70 -0
- data/lib/plutonium/ui/table/components/pagy_pagination.rb +105 -0
- data/lib/plutonium/ui/table/components/scopes_bar.rb +136 -0
- data/lib/plutonium/ui/table/components/search_bar.rb +158 -0
- data/lib/plutonium/ui/table/display_theme.rb +21 -0
- data/lib/plutonium/ui/table/resource.rb +98 -0
- data/lib/plutonium/ui/table/theme.rb +35 -0
- data/lib/plutonium/ui.rb +9 -0
- data/lib/plutonium/version.rb +5 -1
- data/lib/plutonium.rb +53 -26
- data/package-lock.json +19 -22
- data/package.json +4 -4
- data/sig/.keep +0 -0
- data/src/css/plutonium.css +15 -0
- data/tailwind.options.js +11 -3
- metadata +220 -81
- data/lib/generators/pu/core/install/templates/app/presenters/resource_presenter.rb.tt +0 -2
- data/lib/generators/pu/core/install/templates/app/query_objects/resource_query_object.rb.tt +0 -2
- data/lib/generators/pu/pkg/feature/templates/app/query_objects/resource_query_object.rb.tt +0 -4
- data/lib/plutonium/concerns/resource_validatable.rb +0 -34
- data/lib/plutonium/config.rb +0 -9
- data/lib/plutonium/core/controllers/base.rb +0 -101
- data/lib/plutonium/core/controllers/presentable.rb +0 -65
- data/lib/plutonium/core/controllers/queryable.rb +0 -28
- data/lib/plutonium/pkg/app.rb +0 -35
- data/lib/plutonium/pkg/concerns/resource_validatable.rb +0 -36
- data/lib/plutonium/pkg/feature.rb +0 -18
- data/lib/plutonium/policy/initializer.rb +0 -22
- data/lib/plutonium/policy/scope.rb +0 -19
- data/lib/plutonium/pundit/context.rb +0 -18
- data/lib/plutonium/pundit/policy_finder.rb +0 -25
- data/lib/plutonium/resource/policy_context.rb +0 -5
- data/lib/plutonium/resource_register.rb +0 -83
- data/lib/plutonium/smart_cache.rb +0 -151
- data/sig/plutonium.rbs +0 -12
- /data/app/views/{application → plutonium}/_flash.html.erb +0 -0
- /data/app/views/{application → plutonium}/_flash_alerts.html.erb +0 -0
- /data/app/views/{application → plutonium}/_flash_toasts.html.erb +0 -0
- /data/lib/generators/pu/pkg/{app/templates/app/views/package → package/templates}/.keep +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/interactions/resource_interaction.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/models/resource_record.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/policies/resource_policy.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/app/presenters/resource_presenter.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature → package}/templates/lib/engine.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/policies/resource_policy.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/presenters/resource_presenter.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/app/query_objects/resource_query_object.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{feature/templates → portal/templates/app/views/package}/.keep +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/config/routes.rb.tt +0 -0
- /data/lib/generators/pu/pkg/{app → portal}/templates/lib/engine.rb.tt +0 -0
|
@@ -1,101 +0,0 @@
|
|
|
1
|
-
module Plutonium
|
|
2
|
-
module Core
|
|
3
|
-
module Controllers
|
|
4
|
-
module Base
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
include Plutonium::Core::Controllers::Bootable
|
|
7
|
-
include Plutonium::Core::Controllers::EntityScoping
|
|
8
|
-
|
|
9
|
-
included do
|
|
10
|
-
add_flash_types :success, :warning, :error
|
|
11
|
-
|
|
12
|
-
before_action do
|
|
13
|
-
next unless defined?(ActiveStorage)
|
|
14
|
-
|
|
15
|
-
ActiveStorage::Current.url_options = {protocol: request.protocol, host: request.host, port: request.port}
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
helper Plutonium::Helpers
|
|
19
|
-
helper_method :make_page_title, :resource_url_for, :resource_url_args_for, :root_path
|
|
20
|
-
|
|
21
|
-
append_view_path File.expand_path("app/views", Plutonium.root)
|
|
22
|
-
layout -> { turbo_frame_request? ? false : "resource" }
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
private
|
|
26
|
-
|
|
27
|
-
def set_page_title(page_title)
|
|
28
|
-
@page_title = page_title
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def make_page_title(title)
|
|
32
|
-
[title.presence, helpers.application_name].compact.join(" | ")
|
|
33
|
-
end
|
|
34
|
-
|
|
35
|
-
#
|
|
36
|
-
# Returns a dynamic list of args to be used with `url_for`, which considers the route namespace and nesting.
|
|
37
|
-
# The current entity and parent record (for nested routes) are inserted appropriately, ensuring that generated URLs
|
|
38
|
-
# obey the current routing.
|
|
39
|
-
#
|
|
40
|
-
# e.g., of route helpers that will be invoked given the output of this method
|
|
41
|
-
#
|
|
42
|
-
# - when invoked in a root route (/acme/dashboard/users)
|
|
43
|
-
#
|
|
44
|
-
# `resource_url_args_for User` => `entity_users_*`
|
|
45
|
-
# `resource_url_args_for @user` => `entity_user_*`
|
|
46
|
-
# `resource_url_args_for @user, action: :edit` => `edit_entity_user_*`
|
|
47
|
-
# `resource_url_args_for @user, Post` => `entity_user_posts_*`
|
|
48
|
-
#
|
|
49
|
-
# - when invoked in a nested route (/acme/dashboard/users/1/post/1)
|
|
50
|
-
#
|
|
51
|
-
# `resource_url_args_for Post` => `entity_user_posts_*`
|
|
52
|
-
# `resource_url_args_for @post` => `entity_user_post_*`
|
|
53
|
-
# `resource_url_args_for @post, action: :edit` => `edit_entity_user_post_*`
|
|
54
|
-
#
|
|
55
|
-
# @param [Class, ApplicationRecord] *args arguments you would normally pass to `url_for`
|
|
56
|
-
# @param [Symbol] action optional action to invoke, e.g., :new, :edit
|
|
57
|
-
# @param [ApplicationRecord] parent the parent record for nested routes, if any
|
|
58
|
-
# @param [Hash] kwargs additional keyword arguments to pass to `url_for`
|
|
59
|
-
#
|
|
60
|
-
# @return [Hash] args to pass to `url_for`
|
|
61
|
-
#
|
|
62
|
-
def resource_url_args_for(*args, action: nil, parent: nil, **kwargs)
|
|
63
|
-
url_args = {**kwargs, action: action}.compact
|
|
64
|
-
|
|
65
|
-
controller_chain = [current_package.to_s]
|
|
66
|
-
[*args].compact.each_with_index do |element, index|
|
|
67
|
-
if element.is_a?(Class)
|
|
68
|
-
controller_chain << element.to_s.pluralize
|
|
69
|
-
else
|
|
70
|
-
controller_chain << element.class.to_s.pluralize
|
|
71
|
-
if index == args.length - 1
|
|
72
|
-
url_args[:id] = element.to_param
|
|
73
|
-
url_args[:action] ||= :show
|
|
74
|
-
else
|
|
75
|
-
url_args[element.model_name.singular_route_key.to_sym] = element.to_param
|
|
76
|
-
end
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
url_args[:controller] = "/#{controller_chain.join("::").underscore}"
|
|
80
|
-
|
|
81
|
-
url_args[:"#{parent.model_name.singular_route_key}_id"] = parent.to_param if parent.present?
|
|
82
|
-
if scoped_to_entity? && scoped_entity_strategy == :path
|
|
83
|
-
url_args[scoped_entity_param_key] = current_scoped_entity
|
|
84
|
-
end
|
|
85
|
-
|
|
86
|
-
url_args
|
|
87
|
-
end
|
|
88
|
-
|
|
89
|
-
def resource_url_for(...)
|
|
90
|
-
send(current_package.name.underscore.to_sym).url_for(resource_url_args_for(...))
|
|
91
|
-
end
|
|
92
|
-
|
|
93
|
-
def root_path(*)
|
|
94
|
-
return send(:"#{scoped_entity_param_key}_root_path", *) if scoped_to_entity? && scoped_entity_strategy == :path
|
|
95
|
-
|
|
96
|
-
super(*)
|
|
97
|
-
end
|
|
98
|
-
end
|
|
99
|
-
end
|
|
100
|
-
end
|
|
101
|
-
end
|
|
@@ -1,65 +0,0 @@
|
|
|
1
|
-
module Plutonium
|
|
2
|
-
module Core
|
|
3
|
-
module Controllers
|
|
4
|
-
module Presentable
|
|
5
|
-
extend ActiveSupport::Concern
|
|
6
|
-
|
|
7
|
-
included do
|
|
8
|
-
helper_method :presentable_attributes, :present_associations?
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def resource_presenter(resource_class, resource_record)
|
|
14
|
-
presenter_class = "#{resource_class}Presenter".constantize
|
|
15
|
-
presenter_class.new resource_context, resource_record
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def current_presenter
|
|
19
|
-
@current_presenter ||= resource_presenter resource_class, @resource_record
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def presentable_attributes
|
|
23
|
-
@presentable_attributes ||= begin
|
|
24
|
-
presentable_attributes = permitted_attributes
|
|
25
|
-
presentable_attributes -= [scoped_entity_param_key, :"#{scoped_entity_param_key}_id"] if scoped_to_entity?
|
|
26
|
-
presentable_attributes -= [parent_input_param, :"#{parent_input_param}_id"] if current_parent.present?
|
|
27
|
-
presentable_attributes
|
|
28
|
-
end
|
|
29
|
-
end
|
|
30
|
-
|
|
31
|
-
def build_collection
|
|
32
|
-
Plutonium::Core::Ui::Collection.new(
|
|
33
|
-
resource_class:,
|
|
34
|
-
records: @resource_records,
|
|
35
|
-
fields: current_presenter.defined_field_renderers_for(*presentable_attributes),
|
|
36
|
-
actions: current_presenter.actions,
|
|
37
|
-
pager: @pagy,
|
|
38
|
-
search_object: @search_object
|
|
39
|
-
)
|
|
40
|
-
end
|
|
41
|
-
|
|
42
|
-
def build_detail
|
|
43
|
-
Plutonium::Core::Ui::Detail.new(
|
|
44
|
-
resource_class:,
|
|
45
|
-
record: resource_record,
|
|
46
|
-
fields: current_presenter.defined_field_renderers_for(*presentable_attributes),
|
|
47
|
-
associations: current_presenter.defined_association_renderers_for(*permitted_associations),
|
|
48
|
-
actions: current_presenter.actions
|
|
49
|
-
)
|
|
50
|
-
end
|
|
51
|
-
|
|
52
|
-
def build_form
|
|
53
|
-
Plutonium::Core::Ui::Form.new(
|
|
54
|
-
record: resource_record,
|
|
55
|
-
inputs: current_presenter.defined_field_inputs_for(*presentable_attributes)
|
|
56
|
-
)
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
def present_associations?
|
|
60
|
-
current_parent.nil?
|
|
61
|
-
end
|
|
62
|
-
end
|
|
63
|
-
end
|
|
64
|
-
end
|
|
65
|
-
end
|
|
@@ -1,28 +0,0 @@
|
|
|
1
|
-
using Plutonium::Refinements::ParameterRefinements
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Core
|
|
5
|
-
module Controllers
|
|
6
|
-
module Queryable
|
|
7
|
-
extend ActiveSupport::Concern
|
|
8
|
-
|
|
9
|
-
included do
|
|
10
|
-
helper_method :resource_query_params
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
def resource_query_object(resource_class, params)
|
|
14
|
-
query_object_class = "#{resource_class}QueryObject".constantize
|
|
15
|
-
query_object_class.new resource_context, params
|
|
16
|
-
end
|
|
17
|
-
|
|
18
|
-
def current_query_object
|
|
19
|
-
@current_query_object ||= resource_query_object resource_class, resource_query_params
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def resource_query_params
|
|
23
|
-
(params[:q]&.nilify&.to_unsafe_h || {}).with_indifferent_access
|
|
24
|
-
end
|
|
25
|
-
end
|
|
26
|
-
end
|
|
27
|
-
end
|
|
28
|
-
end
|
data/lib/plutonium/pkg/app.rb
DELETED
|
@@ -1,35 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Pkg
|
|
5
|
-
module App
|
|
6
|
-
extend ActiveSupport::Concern
|
|
7
|
-
include Base
|
|
8
|
-
|
|
9
|
-
included do
|
|
10
|
-
isolate_namespace to_s.deconstantize.constantize
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
class_methods do
|
|
14
|
-
include Plutonium::Concerns::ResourceValidatable
|
|
15
|
-
attr_reader :scoped_entity_class, :scoped_entity_strategy, :scoped_entity_param_key
|
|
16
|
-
|
|
17
|
-
def scope_to_entity(entity_class, strategy: :path, param_key: nil)
|
|
18
|
-
validate_resource! entity_class
|
|
19
|
-
|
|
20
|
-
@scoped_entity_class = entity_class
|
|
21
|
-
@scoped_entity_strategy = strategy
|
|
22
|
-
@scoped_entity_param_key = param_key || entity_class.model_name.singular_route_key.to_sym
|
|
23
|
-
end
|
|
24
|
-
|
|
25
|
-
def scoped_to_entity?
|
|
26
|
-
scoped_entity_class.present?
|
|
27
|
-
end
|
|
28
|
-
|
|
29
|
-
def dom_id
|
|
30
|
-
module_parent_name.underscore.dasherize
|
|
31
|
-
end
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
@@ -1,36 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Pkg
|
|
5
|
-
module Concerns
|
|
6
|
-
# Provides methods for validating Plutonium resources
|
|
7
|
-
module ResourceValidatable
|
|
8
|
-
extend ActiveSupport::Concern
|
|
9
|
-
|
|
10
|
-
# Custom error class for invalid resources
|
|
11
|
-
class InvalidResourceError < StandardError; end
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
# Validates if a given resource is a valid Plutonium::Resource::Record
|
|
16
|
-
#
|
|
17
|
-
# @param resource [Object] The resource to validate
|
|
18
|
-
# @raise [InvalidResourceError] If the resource is not valid
|
|
19
|
-
# @return [void]
|
|
20
|
-
def validate_resource!(resource)
|
|
21
|
-
unless valid_resource?(resource)
|
|
22
|
-
raise InvalidResourceError, "#{resource} is not a valid Plutonium::Resource::Record"
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
|
|
26
|
-
# Checks if a given resource is a valid Plutonium::Resource::Record
|
|
27
|
-
#
|
|
28
|
-
# @param resource [Object] The resource to check
|
|
29
|
-
# @return [Boolean] True if the resource is valid, false otherwise
|
|
30
|
-
def valid_resource?(resource)
|
|
31
|
-
resource.is_a?(Class) && resource.include?(Plutonium::Resource::Record)
|
|
32
|
-
end
|
|
33
|
-
end
|
|
34
|
-
end
|
|
35
|
-
end
|
|
36
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
module Plutonium
|
|
2
|
-
module Pkg
|
|
3
|
-
module Feature
|
|
4
|
-
extend ActiveSupport::Concern
|
|
5
|
-
include Base
|
|
6
|
-
|
|
7
|
-
included do
|
|
8
|
-
initializer :append_migrations do |app|
|
|
9
|
-
unless app.root.to_s.match root.to_s
|
|
10
|
-
config.paths["db/migrate"].expanded.each do |expanded_path|
|
|
11
|
-
app.config.paths["db/migrate"] << expanded_path
|
|
12
|
-
end
|
|
13
|
-
end
|
|
14
|
-
end
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
require "pundit"
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Policy
|
|
5
|
-
module Initializer
|
|
6
|
-
def initialize(context, record)
|
|
7
|
-
authorize!(context)
|
|
8
|
-
|
|
9
|
-
@context = context
|
|
10
|
-
@record = record
|
|
11
|
-
end
|
|
12
|
-
|
|
13
|
-
private
|
|
14
|
-
|
|
15
|
-
attr_reader :context, :record
|
|
16
|
-
|
|
17
|
-
def authorize!(context)
|
|
18
|
-
raise Pundit::NotAuthorizedError, "must be logged in" unless context&.user
|
|
19
|
-
end
|
|
20
|
-
end
|
|
21
|
-
end
|
|
22
|
-
end
|
|
@@ -1,19 +0,0 @@
|
|
|
1
|
-
require "pundit"
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Policy
|
|
5
|
-
class Scope
|
|
6
|
-
include Plutonium::Policy::Initializer
|
|
7
|
-
|
|
8
|
-
def resolve
|
|
9
|
-
scope = context.resource_context.resource_class.all
|
|
10
|
-
if @context.resource_context.parent.present?
|
|
11
|
-
scope = scope.associated_with(@context.resource_context.parent)
|
|
12
|
-
elsif @context.resource_context.scope.present?
|
|
13
|
-
scope = scope.associated_with(@context.resource_context.scope)
|
|
14
|
-
end
|
|
15
|
-
scope
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
19
|
-
end
|
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
require "pundit"
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Pundit
|
|
5
|
-
class Context < ::Pundit::Context
|
|
6
|
-
def initialize(*, package:, **)
|
|
7
|
-
super(*, **)
|
|
8
|
-
@package = package
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
private
|
|
12
|
-
|
|
13
|
-
def policy_finder(record)
|
|
14
|
-
PolicyFinder.new(record, package: @package)
|
|
15
|
-
end
|
|
16
|
-
end
|
|
17
|
-
end
|
|
18
|
-
end
|
|
@@ -1,25 +0,0 @@
|
|
|
1
|
-
require "pundit"
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
module Pundit
|
|
5
|
-
class PolicyFinder < ::Pundit::PolicyFinder
|
|
6
|
-
def initialize(*, package:)
|
|
7
|
-
super(*)
|
|
8
|
-
@package = package
|
|
9
|
-
end
|
|
10
|
-
|
|
11
|
-
attr_reader :package
|
|
12
|
-
|
|
13
|
-
def policy
|
|
14
|
-
policy_internal([package, object]) || policy_internal(object)
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
private
|
|
18
|
-
|
|
19
|
-
def policy_internal(object)
|
|
20
|
-
klass = find(object)
|
|
21
|
-
klass.is_a?(String) ? klass.safe_constantize : klass
|
|
22
|
-
end
|
|
23
|
-
end
|
|
24
|
-
end
|
|
25
|
-
end
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
# ResourceRegister manages the registration and lookup of resources.
|
|
5
|
-
class ResourceRegister
|
|
6
|
-
include Plutonium::SmartCache
|
|
7
|
-
include Concerns::ResourceValidatable
|
|
8
|
-
|
|
9
|
-
# Custom error class for frozen register operations
|
|
10
|
-
class FrozenRegisterError < StandardError; end
|
|
11
|
-
|
|
12
|
-
def initialize
|
|
13
|
-
@resources = Set.new
|
|
14
|
-
@frozen = false
|
|
15
|
-
end
|
|
16
|
-
|
|
17
|
-
# Registers a new resource with the register.
|
|
18
|
-
#
|
|
19
|
-
# @param resource [Class] The resource class to be registered.
|
|
20
|
-
# @raise [Plutonium::Concerns::ResourceValidatable::InvalidResourceError] If the resource is not a valid Plutonium::Resource::Record.
|
|
21
|
-
# @raise [FrozenRegisterError] If the register is frozen.
|
|
22
|
-
# @return [void]
|
|
23
|
-
def register(resource)
|
|
24
|
-
raise FrozenRegisterError, "Cannot modify frozen resource register" if @frozen
|
|
25
|
-
|
|
26
|
-
validate_resource!(resource)
|
|
27
|
-
@resources.add(resource.to_s)
|
|
28
|
-
end
|
|
29
|
-
|
|
30
|
-
# Returns an array of all registered resource classes and freezes the register.
|
|
31
|
-
#
|
|
32
|
-
# @return [Array<Class>] An array of registered resource classes.
|
|
33
|
-
def resources
|
|
34
|
-
freeze
|
|
35
|
-
@resources.map(&:constantize)
|
|
36
|
-
end
|
|
37
|
-
memoize_unless_reloading :resources
|
|
38
|
-
|
|
39
|
-
# Returns a hash mapping route keys to their corresponding resource classes.
|
|
40
|
-
# This method will freeze the register if it hasn't been frozen already.
|
|
41
|
-
#
|
|
42
|
-
# @return [Hash{Symbol => Class}] A hash where keys are route keys and values are resource classes.
|
|
43
|
-
def route_key_lookup
|
|
44
|
-
freeze
|
|
45
|
-
resources.to_h do |resource|
|
|
46
|
-
[resource.model_name.singular_route_key.to_sym, resource]
|
|
47
|
-
end
|
|
48
|
-
end
|
|
49
|
-
memoize_unless_reloading :route_key_lookup
|
|
50
|
-
|
|
51
|
-
# Clears all registered resources and invalidates the cache.
|
|
52
|
-
#
|
|
53
|
-
# @return [void]
|
|
54
|
-
def clear
|
|
55
|
-
@resources.clear
|
|
56
|
-
@frozen = false
|
|
57
|
-
invalidate_cache
|
|
58
|
-
end
|
|
59
|
-
|
|
60
|
-
# Checks if the register is frozen.
|
|
61
|
-
#
|
|
62
|
-
# @return [Boolean] True if the register is frozen, false otherwise.
|
|
63
|
-
def frozen?
|
|
64
|
-
@frozen
|
|
65
|
-
end
|
|
66
|
-
|
|
67
|
-
private
|
|
68
|
-
|
|
69
|
-
# Freezes the register
|
|
70
|
-
#
|
|
71
|
-
# @return [Boolean] Always returns true
|
|
72
|
-
def freeze
|
|
73
|
-
@frozen ||= true
|
|
74
|
-
end
|
|
75
|
-
|
|
76
|
-
# Invalidates the memoization cache
|
|
77
|
-
#
|
|
78
|
-
# @return [void]
|
|
79
|
-
def invalidate_cache
|
|
80
|
-
flush_smart_cache
|
|
81
|
-
end
|
|
82
|
-
end
|
|
83
|
-
end
|
|
@@ -1,151 +0,0 @@
|
|
|
1
|
-
# frozen_string_literal: true
|
|
2
|
-
|
|
3
|
-
module Plutonium
|
|
4
|
-
# The SmartCache module provides flexible caching mechanisms for classes and objects,
|
|
5
|
-
# allowing for both inline caching and method-level memoization.
|
|
6
|
-
#
|
|
7
|
-
# This module is designed to optimize performance by caching results
|
|
8
|
-
# when class caching is enabled (typically in production),
|
|
9
|
-
# while ensuring fresh results when caching is disabled (typically in development).
|
|
10
|
-
#
|
|
11
|
-
# This implementation is thread-safe.
|
|
12
|
-
#
|
|
13
|
-
# @example Including SmartCache in a class
|
|
14
|
-
# class MyClass
|
|
15
|
-
# include Plutonium::SmartCache
|
|
16
|
-
#
|
|
17
|
-
# def my_method(arg)
|
|
18
|
-
# cache_unless_reloading("my_method_#{arg}") { expensive_operation(arg) }
|
|
19
|
-
# end
|
|
20
|
-
#
|
|
21
|
-
# def another_method(arg)
|
|
22
|
-
# # Method implementation
|
|
23
|
-
# end
|
|
24
|
-
# memoize_unless_reloading :another_method
|
|
25
|
-
# end
|
|
26
|
-
module SmartCache
|
|
27
|
-
extend ActiveSupport::Concern
|
|
28
|
-
|
|
29
|
-
included do
|
|
30
|
-
class_attribute :_memoized_results, instance_writer: false, default: Concurrent::Map.new
|
|
31
|
-
end
|
|
32
|
-
|
|
33
|
-
# Caches the result of the given block unless class caching is disabled.
|
|
34
|
-
#
|
|
35
|
-
# @param cache_key [String] A unique key to identify the cached result
|
|
36
|
-
# @yield The block whose result will be cached
|
|
37
|
-
# @return [Object] The result of the block, either freshly computed or from cache
|
|
38
|
-
#
|
|
39
|
-
# @example Using cache_unless_reloading inline
|
|
40
|
-
# def fetch_user_data(user_id)
|
|
41
|
-
# cache_unless_reloading("user_data_#{user_id}") do
|
|
42
|
-
# UserDataService.fetch(user_id)
|
|
43
|
-
# end
|
|
44
|
-
# end
|
|
45
|
-
#
|
|
46
|
-
# @note This method uses Rails.application.config.cache_classes
|
|
47
|
-
# to determine whether to cache or not. When cache_classes is false
|
|
48
|
-
# (typical in development), it will always yield to get a fresh result.
|
|
49
|
-
# When true (typical in production), it will use the cache.
|
|
50
|
-
def cache_unless_reloading(cache_key, &block)
|
|
51
|
-
return yield unless should_cache?
|
|
52
|
-
|
|
53
|
-
@cached_results ||= Concurrent::Map.new
|
|
54
|
-
@cached_results.compute_if_absent(cache_key) { yield }
|
|
55
|
-
end
|
|
56
|
-
|
|
57
|
-
# Flushes the smart cache for the specified keys or all keys if none are specified.
|
|
58
|
-
#
|
|
59
|
-
# @param keys [Array<Symbol, String>, Symbol, String] The cache key(s) to flush
|
|
60
|
-
# @return [void]
|
|
61
|
-
#
|
|
62
|
-
# @example Flushing specific cache keys
|
|
63
|
-
# flush_smart_cache([:user_data, :product_list])
|
|
64
|
-
#
|
|
65
|
-
# @example Flushing all cache keys
|
|
66
|
-
# flush_smart_cache
|
|
67
|
-
#
|
|
68
|
-
# @note This method clears both inline caches and memoized method results.
|
|
69
|
-
def flush_smart_cache(keys = nil)
|
|
70
|
-
keys = Array(keys).map(&:to_sym)
|
|
71
|
-
if keys.present?
|
|
72
|
-
@cached_results&.delete_if { |k, _| keys.include?(k.to_sym) }
|
|
73
|
-
keys.each { |key| self.class._memoized_results.delete(key) }
|
|
74
|
-
else
|
|
75
|
-
@cached_results&.clear
|
|
76
|
-
self.class._memoized_results.clear
|
|
77
|
-
end
|
|
78
|
-
end
|
|
79
|
-
|
|
80
|
-
# Determines whether caching should be performed based on the current Rails configuration.
|
|
81
|
-
#
|
|
82
|
-
# @return [Boolean] true if caching should be performed, false otherwise
|
|
83
|
-
# @note This method uses Rails.application.config.cache_classes to determine caching behavior.
|
|
84
|
-
# When cache_classes is false (typical in development), it returns false.
|
|
85
|
-
# When true (typical in production), it returns true.
|
|
86
|
-
def should_cache?
|
|
87
|
-
Rails.application.config.cache_classes
|
|
88
|
-
end
|
|
89
|
-
|
|
90
|
-
class_methods do
|
|
91
|
-
# Memoizes the result of the specified method unless class caching is disabled.
|
|
92
|
-
#
|
|
93
|
-
# @param method_name [Symbol] The name of the method to memoize
|
|
94
|
-
# @return [void]
|
|
95
|
-
#
|
|
96
|
-
# @example Memoizing a method
|
|
97
|
-
# class User
|
|
98
|
-
# include Plutonium::SmartCache
|
|
99
|
-
#
|
|
100
|
-
# def expensive_full_name_calculation
|
|
101
|
-
# # Complex name calculation
|
|
102
|
-
# end
|
|
103
|
-
# memoize_unless_reloading :expensive_full_name_calculation
|
|
104
|
-
# end
|
|
105
|
-
#
|
|
106
|
-
# @note This method uses Rails.application.config.cache_classes to determine
|
|
107
|
-
# whether to memoize or not. When cache_classes is false (typical in development),
|
|
108
|
-
# it will always call the original method. When true (typical in production),
|
|
109
|
-
# it will use memoization, caching results for each unique set of arguments.
|
|
110
|
-
def memoize_unless_reloading(method_name)
|
|
111
|
-
original_method = instance_method(method_name)
|
|
112
|
-
define_method(method_name) do |*args|
|
|
113
|
-
if should_cache?
|
|
114
|
-
cache = self.class._memoized_results[method_name] ||= Concurrent::Map.new
|
|
115
|
-
cache.compute_if_absent(args.hash.to_s) { original_method.bind_call(self, *args) }
|
|
116
|
-
else
|
|
117
|
-
original_method.bind_call(self, *args)
|
|
118
|
-
end
|
|
119
|
-
end
|
|
120
|
-
end
|
|
121
|
-
end
|
|
122
|
-
end
|
|
123
|
-
|
|
124
|
-
# Configuration:
|
|
125
|
-
# The caching behavior is controlled by the Rails configuration option config.cache_classes:
|
|
126
|
-
#
|
|
127
|
-
# - When false (typical in development):
|
|
128
|
-
# - Classes are reloaded on each request.
|
|
129
|
-
# - cache_unless_reloading always yields fresh results.
|
|
130
|
-
# - memoize_unless_reloading always calls the original method.
|
|
131
|
-
#
|
|
132
|
-
# - When true (typical in production):
|
|
133
|
-
# - Classes are cached.
|
|
134
|
-
# - cache_unless_reloading uses cached results.
|
|
135
|
-
# - memoize_unless_reloading uses memoized results, caching for each unique set of arguments.
|
|
136
|
-
#
|
|
137
|
-
# Best Practices:
|
|
138
|
-
# - Use meaningful and unique cache keys to avoid collisions.
|
|
139
|
-
# - Be mindful of memory usage, especially with large cached results.
|
|
140
|
-
# - Consider cache expiration strategies for long-running processes.
|
|
141
|
-
# - Use cache_unless_reloading for fine-grained control within methods.
|
|
142
|
-
# - Use memoize_unless_reloading for entire methods, especially those with expensive computations.
|
|
143
|
-
#
|
|
144
|
-
# Thread Safety:
|
|
145
|
-
# - This implementation is thread-safe.
|
|
146
|
-
# - It uses Concurrent::Map from the concurrent-ruby gem for thread-safe caching.
|
|
147
|
-
#
|
|
148
|
-
# Testing:
|
|
149
|
-
# - In your test environment, you may want to control caching behavior explicitly.
|
|
150
|
-
# - You can mock or stub Rails.application.config.cache_classes or override should_cache? as needed in your tests.
|
|
151
|
-
end
|
data/sig/plutonium.rbs
DELETED
|
@@ -1,12 +0,0 @@
|
|
|
1
|
-
# plutonium.rbs
|
|
2
|
-
module Plutonium
|
|
3
|
-
class Error < StandardError; end
|
|
4
|
-
|
|
5
|
-
def self.root: () -> Pathname
|
|
6
|
-
def self.lib_root: () -> Pathname
|
|
7
|
-
def self.logger: () -> Logger
|
|
8
|
-
def self.application_name: () -> String
|
|
9
|
-
def self.application_name=: (String) -> void
|
|
10
|
-
def self.development?: () -> bool
|
|
11
|
-
def self.eager_load_rails!: () -> void
|
|
12
|
-
end
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
/data/lib/generators/pu/pkg/{feature → package}/templates/app/policies/resource_policy.rb.tt
RENAMED
|
File without changes
|
/data/lib/generators/pu/pkg/{feature → package}/templates/app/presenters/resource_presenter.rb.tt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
/data/lib/generators/pu/pkg/{app → portal}/templates/app/presenters/resource_presenter.rb.tt
RENAMED
|
File without changes
|
/data/lib/generators/pu/pkg/{app → portal}/templates/app/query_objects/resource_query_object.rb.tt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|