plutonium 0.13.3 → 0.14.1
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/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/config/initializers/plutonium.rb +10 -0
- data/lib/generators/pu/lib/plutonium_generators/concerns/actions.rb +19 -0
- data/lib/generators/pu/pkg/app/templates/config/routes.rb.tt +5 -6
- data/lib/generators/pu/pkg/app/templates/lib/engine.rb.tt +0 -4
- data/lib/generators/pu/res/conn/conn_generator.rb +4 -4
- data/lib/plutonium/application/controller.rb +1 -1
- data/lib/plutonium/application/dynamic_controllers.rb +108 -0
- data/lib/plutonium/auth/rodauth.rb +1 -1
- data/lib/plutonium/concerns/resource_validatable.rb +34 -0
- data/lib/plutonium/config/overlayed_hash.rb +86 -0
- data/lib/plutonium/configuration.rb +138 -0
- 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/controllers/entity_scoping.rb +84 -26
- data/lib/plutonium/helpers/assets_helper.rb +73 -20
- data/lib/plutonium/pkg/app.rb +3 -115
- data/lib/plutonium/pkg/concerns/resource_validatable.rb +36 -0
- data/lib/plutonium/railtie.rb +53 -30
- data/lib/plutonium/reloader.rb +66 -24
- data/lib/plutonium/resource/controller.rb +1 -1
- data/lib/plutonium/resource_register.rb +83 -0
- data/lib/plutonium/routing/mapper_extensions.rb +127 -0
- data/lib/plutonium/routing/resource_registration.rb +16 -0
- data/lib/plutonium/routing/route_set_extensions.rb +132 -0
- data/lib/plutonium/smart_cache.rb +151 -0
- data/lib/plutonium/version.rb +1 -1
- data/lib/plutonium.rb +41 -27
- data/sig/.keep +0 -0
- metadata +13 -4
- data/lib/generators/pu/rodauth/templates/app/rodauth/account_rodauth_plugin.rb.tt +0 -270
- data/sig/plutonium.rbs +0 -12
@@ -1,6 +1,17 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Plutonium
|
2
4
|
module Core
|
3
5
|
module Controllers
|
6
|
+
# EntityScoping module provides functionality for scoping controllers to specific entities.
|
7
|
+
#
|
8
|
+
# This module is designed to be included in controllers that need to operate within the context
|
9
|
+
# of a specific entity, such as a user's organization or a project.
|
10
|
+
#
|
11
|
+
# @example Usage in a controller
|
12
|
+
# class MyController < ApplicationController
|
13
|
+
# include Plutonium::Core::Controllers::EntityScoping
|
14
|
+
# end
|
4
15
|
module EntityScoping
|
5
16
|
extend ActiveSupport::Concern
|
6
17
|
|
@@ -9,70 +20,117 @@ module Plutonium
|
|
9
20
|
helper_method :current_scoped_entity
|
10
21
|
end
|
11
22
|
|
12
|
-
|
13
|
-
|
23
|
+
# Checks if the current engine is scoped to an entity.
|
24
|
+
#
|
25
|
+
# @return [Boolean] true if scoped to an entity, false otherwise
|
14
26
|
def scoped_to_entity?
|
15
27
|
current_engine.scoped_to_entity?
|
16
28
|
end
|
17
29
|
|
30
|
+
# Returns the strategy used for entity scoping.
|
31
|
+
#
|
32
|
+
# @return [Symbol] the scoping strategy
|
18
33
|
def scoped_entity_strategy
|
19
34
|
current_engine.scoped_entity_strategy
|
20
35
|
end
|
21
36
|
|
22
|
-
|
23
|
-
|
37
|
+
# Returns the parameter key used for entity scoping.
|
38
|
+
#
|
39
|
+
# @return [Symbol] the parameter key
|
40
|
+
# @raise [NotImplementedError] if not scoped to an entity
|
41
|
+
def scoped_entity_param_key
|
42
|
+
ensure_legal_entity_scoping_method_access!(__method__)
|
43
|
+
current_engine.scoped_entity_param_key
|
44
|
+
end
|
24
45
|
|
46
|
+
# Returns the class of the scoped entity.
|
47
|
+
#
|
48
|
+
# @return [Class] the scoped entity class
|
49
|
+
# @raise [NotImplementedError] if not scoped to an entity
|
50
|
+
def scoped_entity_class
|
51
|
+
ensure_legal_entity_scoping_method_access!(__method__)
|
25
52
|
current_engine.scoped_entity_class
|
26
53
|
end
|
27
54
|
|
28
|
-
|
29
|
-
ensure_legal_entity_scoping_method_access! :scoped_entity_param_key
|
30
|
-
|
31
|
-
current_engine.scoped_entity_param_key
|
32
|
-
end
|
55
|
+
private
|
33
56
|
|
57
|
+
# Returns the session key used to store the scoped entity.
|
58
|
+
#
|
59
|
+
# @return [Symbol] the session key
|
60
|
+
# @raise [NotImplementedError] if not scoped to an entity
|
34
61
|
def scoped_entity_session_key
|
35
|
-
ensure_legal_entity_scoping_method_access!
|
36
|
-
|
62
|
+
ensure_legal_entity_scoping_method_access!(__method__)
|
37
63
|
:"#{current_package.name.underscore}__scoped_entity_id"
|
38
64
|
end
|
39
65
|
|
66
|
+
# Returns the current scoped entity for the request.
|
67
|
+
#
|
68
|
+
# @return [ActiveRecord::Base, nil] the current scoped entity or nil if not found
|
69
|
+
# @raise [NotImplementedError] if not scoped to an entity or strategy is unknown
|
40
70
|
def current_scoped_entity
|
41
|
-
ensure_legal_entity_scoping_method_access!
|
42
|
-
|
71
|
+
ensure_legal_entity_scoping_method_access!(__method__)
|
43
72
|
return unless current_user.present?
|
44
73
|
|
45
|
-
@current_scoped_entity ||=
|
74
|
+
@current_scoped_entity ||= fetch_current_scoped_entity
|
75
|
+
end
|
76
|
+
|
77
|
+
# Fetches the current scoped entity based on the scoping strategy.
|
78
|
+
#
|
79
|
+
# @return [ActiveRecord::Base, nil] the current scoped entity or nil if not found
|
80
|
+
# @raise [NotImplementedError] if the scoping strategy is unknown
|
81
|
+
def fetch_current_scoped_entity
|
82
|
+
case scoped_entity_strategy
|
46
83
|
when :path
|
47
|
-
|
48
|
-
.associated_with(current_user)
|
49
|
-
.from_path_param(request.path_parameters[scoped_entity_param_key])
|
50
|
-
.first! # Raise NotFound if user does not have access to the entity or it does not exist
|
84
|
+
fetch_entity_from_path
|
51
85
|
when Symbol
|
52
|
-
send
|
86
|
+
send(scoped_entity_strategy)
|
53
87
|
else
|
54
|
-
raise NotImplementedError, "
|
88
|
+
raise NotImplementedError, "Unknown scoped entity strategy: #{scoped_entity_strategy.inspect}"
|
55
89
|
end
|
56
90
|
end
|
57
91
|
|
92
|
+
# Fetches the scoped entity from the path parameters.
|
93
|
+
#
|
94
|
+
# @return [ActiveRecord::Base] the scoped entity
|
95
|
+
# @raise [ActiveRecord::RecordNotFound] if the entity is not found or the user doesn't have access
|
96
|
+
def fetch_entity_from_path
|
97
|
+
scoped_entity_class
|
98
|
+
.associated_with(current_user)
|
99
|
+
.from_path_param(request.path_parameters[scoped_entity_param_key])
|
100
|
+
.first!
|
101
|
+
end
|
102
|
+
|
103
|
+
# Remembers the current scoped entity in the session.
|
104
|
+
#
|
105
|
+
# @return [void]
|
58
106
|
def remember_scoped_entity
|
59
107
|
return unless scoped_to_entity?
|
60
108
|
|
61
109
|
session[scoped_entity_session_key] = current_scoped_entity.to_global_id.to_s
|
62
110
|
end
|
63
111
|
|
112
|
+
# Retrieves the remembered scoped entity from the session.
|
113
|
+
#
|
114
|
+
# @return [ActiveRecord::Base, nil] the remembered scoped entity or nil if not found
|
115
|
+
# @raise [NotImplementedError] if not scoped to an entity
|
64
116
|
def remembered_scoped_entity
|
65
|
-
ensure_legal_entity_scoping_method_access!
|
66
|
-
|
67
|
-
@remembered_scoped_entity ||= GlobalID::Locator.locate session[scoped_entity_session_key]
|
117
|
+
ensure_legal_entity_scoping_method_access!(__method__)
|
118
|
+
@remembered_scoped_entity ||= GlobalID::Locator.locate(session[scoped_entity_session_key])
|
68
119
|
end
|
69
120
|
|
121
|
+
# Ensures that the method call is legal within the current scoping context.
|
122
|
+
#
|
123
|
+
# @param method [Symbol] the method being called
|
124
|
+
# @raise [NotImplementedError] if not scoped to an entity
|
70
125
|
def ensure_legal_entity_scoping_method_access!(method)
|
71
126
|
return if scoped_to_entity?
|
72
127
|
|
73
|
-
raise NotImplementedError,
|
74
|
-
|
75
|
-
|
128
|
+
raise NotImplementedError, <<~ERROR_MESSAGE
|
129
|
+
This request is not scoped to an entity.
|
130
|
+
|
131
|
+
Add the `scope_to_entity YourEntityRecord` directive in #{current_engine}
|
132
|
+
or implement #{self.class}##{method}
|
133
|
+
ERROR_MESSAGE
|
76
134
|
end
|
77
135
|
end
|
78
136
|
end
|
@@ -1,41 +1,94 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
module Plutonium
|
2
4
|
module Helpers
|
5
|
+
# Helper module for managing asset-related functionality
|
3
6
|
module AssetsHelper
|
7
|
+
# Generate a stylesheet tag for the resource
|
8
|
+
#
|
9
|
+
# @return [ActiveSupport::SafeBuffer] HTML stylesheet link tag
|
4
10
|
def resource_stylesheet_tag
|
5
|
-
url =
|
6
|
-
|
7
|
-
"/build/#{filename}"
|
8
|
-
else
|
9
|
-
resource_stylesheet_asset
|
10
|
-
end
|
11
|
-
stylesheet_link_tag url, "data-turbo-track": "reload"
|
11
|
+
url = resource_asset_url_for(:css, resource_stylesheet_asset)
|
12
|
+
stylesheet_link_tag(url, "data-turbo-track": "reload")
|
12
13
|
end
|
13
14
|
|
15
|
+
# Generate a script tag for the resource
|
16
|
+
#
|
17
|
+
# @return [ActiveSupport::SafeBuffer] HTML script tag
|
14
18
|
def resource_script_tag
|
15
|
-
url =
|
16
|
-
|
17
|
-
"/build/#{filename}"
|
18
|
-
else
|
19
|
-
resource_script_asset
|
20
|
-
end
|
21
|
-
javascript_include_tag url, "data-turbo-track": "reload", type: "module"
|
19
|
+
url = resource_asset_url_for(:js, resource_script_asset)
|
20
|
+
javascript_include_tag(url, "data-turbo-track": "reload", type: "module")
|
22
21
|
end
|
23
22
|
|
23
|
+
# Generate a favicon link tag
|
24
|
+
#
|
25
|
+
# @return [ActiveSupport::SafeBuffer] HTML favicon link tag
|
24
26
|
def resource_favicon_tag
|
25
|
-
favicon_link_tag
|
27
|
+
favicon_link_tag(resource_favicon_asset)
|
26
28
|
end
|
27
29
|
|
30
|
+
# Generate an image tag for the logo
|
31
|
+
#
|
32
|
+
# @param classname [String] CSS class name for the image tag
|
33
|
+
# @return [ActiveSupport::SafeBuffer] HTML image tag
|
28
34
|
def resource_logo_tag(classname:)
|
29
|
-
image_tag
|
35
|
+
image_tag(resource_logo_asset, class: classname)
|
30
36
|
end
|
31
37
|
|
32
|
-
|
38
|
+
# Get the logo asset path
|
39
|
+
#
|
40
|
+
# @return [String] path to the logo asset
|
41
|
+
def resource_logo_asset
|
42
|
+
Plutonium.configuration.assets.logo
|
43
|
+
end
|
33
44
|
|
34
|
-
|
45
|
+
# Get the stylesheet asset path
|
46
|
+
#
|
47
|
+
# @return [String] path to the stylesheet asset
|
48
|
+
def resource_stylesheet_asset
|
49
|
+
Plutonium.configuration.assets.stylesheet
|
50
|
+
end
|
35
51
|
|
36
|
-
|
52
|
+
# Get the script asset path
|
53
|
+
#
|
54
|
+
# @return [String] path to the script asset
|
55
|
+
def resource_script_asset
|
56
|
+
Plutonium.configuration.assets.script
|
57
|
+
end
|
37
58
|
|
38
|
-
|
59
|
+
# Get the favicon asset path
|
60
|
+
#
|
61
|
+
# @return [String] path to the favicon asset
|
62
|
+
def resource_favicon_asset
|
63
|
+
Plutonium.configuration.assets.favicon
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
|
68
|
+
# Generate the appropriate asset URL based on the environment
|
69
|
+
#
|
70
|
+
# @param type [Symbol] asset type (:css or :js)
|
71
|
+
# @param fallback [String] fallback asset path
|
72
|
+
# @return [String] asset URL
|
73
|
+
def resource_asset_url_for(type, fallback)
|
74
|
+
if Plutonium.configuration.development?
|
75
|
+
resource_development_asset_url(type)
|
76
|
+
else
|
77
|
+
fallback
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
# Generate the asset URL for development environment
|
82
|
+
#
|
83
|
+
# @param type [Symbol] asset type (:css or :js)
|
84
|
+
# @return [String] asset URL for development
|
85
|
+
def resource_development_asset_url(type)
|
86
|
+
manifest_file = (type == :css) ? "css.manifest" : "js.manifest"
|
87
|
+
asset_key = (type == :css) ? "plutonium.css" : "plutonium.js"
|
88
|
+
|
89
|
+
filename = JSON.parse(File.read(Plutonium.root.join("src", "build", manifest_file)))[asset_key]
|
90
|
+
"/build/#{filename}"
|
91
|
+
end
|
39
92
|
end
|
40
93
|
end
|
41
94
|
end
|
data/lib/plutonium/pkg/app.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
|
1
|
+
# frozen_string_literal: true
|
2
2
|
|
3
3
|
module Plutonium
|
4
4
|
module Pkg
|
@@ -11,10 +11,11 @@ module Plutonium
|
|
11
11
|
end
|
12
12
|
|
13
13
|
class_methods do
|
14
|
+
include Plutonium::Concerns::ResourceValidatable
|
14
15
|
attr_reader :scoped_entity_class, :scoped_entity_strategy, :scoped_entity_param_key
|
15
16
|
|
16
17
|
def scope_to_entity(entity_class, strategy: :path, param_key: nil)
|
17
|
-
|
18
|
+
validate_resource! entity_class
|
18
19
|
|
19
20
|
@scoped_entity_class = entity_class
|
20
21
|
@scoped_entity_strategy = strategy
|
@@ -25,122 +26,9 @@ module Plutonium
|
|
25
26
|
scoped_entity_class.present?
|
26
27
|
end
|
27
28
|
|
28
|
-
def initialize_register!
|
29
|
-
# this exists solely to support hot reloads
|
30
|
-
# if the user has modified the register especially if they removed a registration, we have no way of telling
|
31
|
-
# so instead we start over
|
32
|
-
@resource_register = []
|
33
|
-
end
|
34
|
-
|
35
|
-
def register_resource(resource)
|
36
|
-
@resource_register.append resource
|
37
|
-
end
|
38
|
-
|
39
|
-
def resource_register
|
40
|
-
@resource_register || []
|
41
|
-
end
|
42
|
-
|
43
|
-
def registered_resource_route_key_lookup
|
44
|
-
@registered_resource_route_key_lookup = resource_register.map { |resource|
|
45
|
-
[resource.model_name.singular_route_key.to_sym, resource]
|
46
|
-
}.to_h
|
47
|
-
end
|
48
|
-
|
49
|
-
def draw_custom_routes(&block)
|
50
|
-
@custom_routes_block = block
|
51
|
-
end
|
52
|
-
|
53
|
-
def draw_resource_routes
|
54
|
-
ActiveSupport::Notifications.instrument("plutonium.app.draw_resource_routes", app: self.class.module_parent.to_s) do
|
55
|
-
draw_resource_routes_internal
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
29
|
def dom_id
|
60
30
|
module_parent_name.underscore.dasherize
|
61
31
|
end
|
62
|
-
|
63
|
-
private
|
64
|
-
|
65
|
-
def draw_resource_routes_internal
|
66
|
-
custom_routes_block = @custom_routes_block
|
67
|
-
registered_resources = resource_register
|
68
|
-
scoped_entity_param_key = self.scoped_entity_param_key if scoped_entity_strategy == :path
|
69
|
-
routes.draw do
|
70
|
-
shared_resource_concerns = [:interactive_resource_actions] # TODO: make this a config parameter
|
71
|
-
concern :interactive_resource_actions do
|
72
|
-
# these concerns power the interactive actions feature
|
73
|
-
member do
|
74
|
-
get "record_actions/:interactive_action", action: :begin_interactive_resource_record_action,
|
75
|
-
as: :interactive_resource_record_action
|
76
|
-
post "record_actions/:interactive_action", action: :commit_interactive_resource_record_action
|
77
|
-
end
|
78
|
-
|
79
|
-
collection do
|
80
|
-
get "collection_actions/:interactive_action", action: :begin_interactive_resource_collection_action,
|
81
|
-
as: :interactive_resource_collection_action
|
82
|
-
post "collection_actions/:interactive_action", action: :commit_interactive_resource_collection_action
|
83
|
-
|
84
|
-
get "recordless_actions/:interactive_action", action: :begin_interactive_resource_recordless_action,
|
85
|
-
as: :interactive_resource_recordless_action
|
86
|
-
post "recordless_actions/:interactive_action", action: :commit_interactive_resource_recordless_action
|
87
|
-
end
|
88
|
-
end
|
89
|
-
|
90
|
-
resource_route_names = []
|
91
|
-
resource_route_opts_lookup = {}
|
92
|
-
# for each of our registered resources, we are registering the routes required
|
93
|
-
registered_resources.each do |resource|
|
94
|
-
resource_name = resource.to_s # Deeply::Namespaced::ResourceModel
|
95
|
-
resource_controller = resource_name.pluralize.underscore # deeply/namespaced/resource_models
|
96
|
-
resource_route = resource.model_name.plural # deeply_namespaced_resource_models
|
97
|
-
resource_route_name = :"#{resource_route}_routes" # deeply_namespaced_resource_models_routes
|
98
|
-
|
99
|
-
resource_route_opts = {}
|
100
|
-
# rails is not smart enough to infer Deeply::Namespaced::ResourceModelsController from deeply_namespaced_resource_models
|
101
|
-
# since we are heavy on namespaces, we choose to be explicit to guarantee there is no confusion
|
102
|
-
resource_route_opts[:controller] = resource_controller
|
103
|
-
# using collection for path is much nicer than the alternative
|
104
|
-
# e.g. deeply/namespaced/resource_models vs deeply_namespaced_resource_models
|
105
|
-
resource_route_opts[:path] = resource.model_name.collection
|
106
|
-
resource_route_opts_lookup[resource_route] = resource_route_opts
|
107
|
-
|
108
|
-
# defining our resources with concerns allows us to defer materializing till later,
|
109
|
-
# ensuring that resource_route_opts_lookup is populated
|
110
|
-
concern resource_route_name do
|
111
|
-
resources resource_route, **resource_route_opts, concerns: shared_resource_concerns do
|
112
|
-
nested_resources_route_opts = resource_route_opts_lookup.slice(*resource.has_many_association_routes)
|
113
|
-
nested_resources_route_opts.each do |nested_resource_route, nested_resource_route_opts|
|
114
|
-
resources nested_resource_route, **nested_resource_route_opts, concerns: shared_resource_concerns
|
115
|
-
end
|
116
|
-
end
|
117
|
-
end
|
118
|
-
resource_route_names << resource_route_name
|
119
|
-
end
|
120
|
-
|
121
|
-
# materialize our routes using a scope
|
122
|
-
# if the app is scoped to an entity, ensure that the expected route param and url helper prefix are specified.
|
123
|
-
|
124
|
-
# path => /:entity/deeply/namespaced/resource_models/:deeply_namespaced_resource_model_id/
|
125
|
-
# helper => entity_deeply_namespaced_resource_models_path
|
126
|
-
scope_name = scoped_entity_param_key.present? ? ":#{scoped_entity_param_key}" : ""
|
127
|
-
|
128
|
-
# path => /deeply/namespaced/resource_models/:deeply_namespaced_resource_model_id/
|
129
|
-
# helper => deeply_namespaced_resource_models_path
|
130
|
-
scope_options = scoped_entity_param_key.present? ? {as: scoped_entity_param_key} : {}
|
131
|
-
|
132
|
-
scope scope_name, scope_options do
|
133
|
-
instance_exec(&custom_routes_block) if custom_routes_block.present?
|
134
|
-
# we have to reverse sort our resource routes in order to prevent routing conflicts
|
135
|
-
# e.g. /blogs/1 and blogs/comments cause an issue if Blog is registered before Blogs::Comment
|
136
|
-
# attempting to load blogs/comments routes to blogs/:id which fails with a 404 since BlogsController
|
137
|
-
# essentially performs a Blog.find('comments')
|
138
|
-
# since the route names for these 2 will be 'blogs' and 'blog_comments',
|
139
|
-
# reverse sorting ensures that blog_comments is registered first, preventing the issue described above
|
140
|
-
concerns resource_route_names.sort
|
141
|
-
end
|
142
|
-
end
|
143
|
-
end
|
144
32
|
end
|
145
33
|
end
|
146
34
|
end
|
@@ -0,0 +1,36 @@
|
|
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
|
data/lib/plutonium/railtie.rb
CHANGED
@@ -1,45 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
1
3
|
require "view_component"
|
2
4
|
|
3
5
|
module Plutonium
|
6
|
+
# Plutonium::Railtie integrates Plutonium with Rails applications.
|
7
|
+
#
|
8
|
+
# This Railtie sets up configurations, initializers, and tasks for Plutonium
|
9
|
+
# to work seamlessly within a Rails environment.
|
4
10
|
class Railtie < Rails::Railtie
|
5
|
-
|
6
|
-
|
7
|
-
config.plutonium.enable_hotreload = defined?(Rails.env) && Rails.env.development?
|
8
|
-
|
9
|
-
config.plutonium.assets = ActiveSupport::OrderedOptions.new
|
10
|
-
config.plutonium.assets.logo = "plutonium.png"
|
11
|
-
config.plutonium.assets.favicon = "plutonium.ico"
|
12
|
-
config.plutonium.assets.stylesheet = "plutonium.css"
|
13
|
-
config.plutonium.assets.script = "plutonium.min.js"
|
14
|
-
|
11
|
+
# Assets to be precompiled
|
12
|
+
#
|
15
13
|
# If you don't want to precompile Plutonium's assets (eg. because you're using webpack),
|
16
14
|
# you can do this in an intiailzer:
|
17
15
|
#
|
18
16
|
# config.after_initialize do
|
19
17
|
# config.assets.precompile -= Plutonium::Railtie::PRECOMPILE_ASSETS
|
20
18
|
# end
|
21
|
-
PRECOMPILE_ASSETS = %w[
|
19
|
+
PRECOMPILE_ASSETS = %w[
|
20
|
+
plutonium.js plutonium.js.map plutonium.min.js plutonium.min.js.map
|
21
|
+
plutonium.css plutonium.png plutonium.ico
|
22
|
+
].freeze
|
22
23
|
|
23
24
|
initializer "plutonium.assets" do
|
24
|
-
|
25
|
+
setup_asset_pipeline if Rails.application.config.respond_to?(:assets)
|
26
|
+
end
|
27
|
+
|
28
|
+
initializer "plutonium.load_components" do
|
29
|
+
load_base_component
|
30
|
+
end
|
31
|
+
|
32
|
+
initializer "plutonium.initializers" do
|
33
|
+
load_plutonium_initializers
|
34
|
+
end
|
25
35
|
|
36
|
+
initializer "plutonium.asset_server" do
|
37
|
+
setup_development_asset_server if Plutonium.configuration.development?
|
38
|
+
end
|
39
|
+
|
40
|
+
initializer "plutonium.view_components_capture_compat" do
|
41
|
+
config.view_component.capture_compatibility_patch_enabled = true
|
42
|
+
end
|
43
|
+
|
44
|
+
initializer "plutonium.action_dispatch_extensions" do
|
45
|
+
extend_action_dispatch
|
46
|
+
end
|
47
|
+
|
48
|
+
rake_tasks do
|
49
|
+
load "tasks/create_rodauth_admin.rake"
|
50
|
+
end
|
51
|
+
|
52
|
+
config.after_initialize do
|
53
|
+
Plutonium::Reloader.start! if Plutonium.configuration.enable_hotreload
|
54
|
+
Plutonium::ZEITWERK_LOADER.eager_load if Rails.env.production?
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def setup_asset_pipeline
|
26
60
|
Rails.application.config.assets.precompile += PRECOMPILE_ASSETS
|
27
61
|
Rails.application.config.assets.paths << Plutonium.root.join("app/assets").to_s
|
28
62
|
end
|
29
63
|
|
30
|
-
|
64
|
+
def load_base_component
|
31
65
|
load Plutonium.root.join("app", "views", "components", "base.rb")
|
32
66
|
end
|
33
67
|
|
34
|
-
|
68
|
+
def load_plutonium_initializers
|
35
69
|
Dir.glob(Plutonium.root.join("config", "initializers", "**", "*.rb")) { |file| load file }
|
36
70
|
end
|
37
71
|
|
38
|
-
|
39
|
-
next unless Plutonium.development?
|
40
|
-
|
72
|
+
def setup_development_asset_server
|
41
73
|
puts "=> [plutonium] starting assets server"
|
42
|
-
# setup a middleware to serve our assets
|
43
74
|
config.app_middleware.insert_before(
|
44
75
|
ActionDispatch::Static,
|
45
76
|
Rack::Static,
|
@@ -47,23 +78,15 @@ module Plutonium
|
|
47
78
|
root: Plutonium.root.join("src").to_s,
|
48
79
|
cascade: true,
|
49
80
|
header_rules: [
|
50
|
-
# Cache all static files in public caches (e.g. Rack::Cache) as well as in the browser
|
51
81
|
[:all, {"cache-control" => "public, max-age=31536000"}]
|
52
82
|
]
|
53
83
|
)
|
54
84
|
end
|
55
85
|
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
rake_tasks do
|
61
|
-
load "tasks/create_rodauth_admin.rake"
|
62
|
-
end
|
63
|
-
|
64
|
-
config.after_initialize do
|
65
|
-
Plutonium::Reloader.start! if Rails.application.config.plutonium.enable_hotreload
|
66
|
-
Plutonium::ZEITWERK_LOADER.eager_load if Rails.env.production?
|
86
|
+
def extend_action_dispatch
|
87
|
+
ActionDispatch::Routing::Mapper.prepend Plutonium::Routing::MapperExtensions
|
88
|
+
ActionDispatch::Routing::RouteSet.prepend Plutonium::Routing::RouteSetExtensions
|
89
|
+
Rails::Engine.include Plutonium::Routing::ResourceRegistration
|
67
90
|
end
|
68
91
|
end
|
69
92
|
end
|