plutonium 0.14.0 → 0.15.0.pre.rc1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|