pakyow-reflection 1.0.0.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 +7 -0
- data/CHANGELOG.md +0 -0
- data/LICENSE +4 -0
- data/README.md +29 -0
- data/lib/pakyow/reflection/action.rb +25 -0
- data/lib/pakyow/reflection/attribute.rb +29 -0
- data/lib/pakyow/reflection/behavior/config.rb +33 -0
- data/lib/pakyow/reflection/behavior/reflecting.rb +45 -0
- data/lib/pakyow/reflection/behavior/rendering/install_form_metadata.rb +28 -0
- data/lib/pakyow/reflection/builders/abstract.rb +13 -0
- data/lib/pakyow/reflection/builders/actions.rb +80 -0
- data/lib/pakyow/reflection/builders/endpoints.rb +86 -0
- data/lib/pakyow/reflection/builders/helpers/controller.rb +234 -0
- data/lib/pakyow/reflection/builders/source.rb +51 -0
- data/lib/pakyow/reflection/endpoint.rb +74 -0
- data/lib/pakyow/reflection/extensions/controller.rb +302 -0
- data/lib/pakyow/reflection/framework.rb +70 -0
- data/lib/pakyow/reflection/mirror.rb +343 -0
- data/lib/pakyow/reflection/nested.rb +29 -0
- data/lib/pakyow/reflection/scope.rb +62 -0
- data/lib/pakyow/reflection.rb +12 -0
- metadata +133 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 06a3fad2efdf75a2570eb8ec91fa74ea9cfe813fd7519de08c36ee85af4af4a7
|
4
|
+
data.tar.gz: 26e3f2526b1668dce5bef2d920597251c4d464e149ec69801415f17f6db2e8a7
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: caddc15fbd9aa77b7fef080db96b1d59bf9649ef57d55aed2d45556d067e2864a85c2f86b771ec8c55ed276639902baa5ce0bfc302ccb01c82c9b9437dc9e799
|
7
|
+
data.tar.gz: 7ba4c7c16c39f61af0ae09899ca6b1cf6e594bddc07a73da3721f3fe08d2220e3e9e6d9d01d691b2db8106ae785cadbf0f0688aa0230ba36e31b3511f9dc31d4
|
data/CHANGELOG.md
ADDED
File without changes
|
data/LICENSE
ADDED
data/README.md
ADDED
@@ -0,0 +1,29 @@
|
|
1
|
+
# pakyow-reflection
|
2
|
+
|
3
|
+
Reflected behavior for Pakyow.
|
4
|
+
|
5
|
+
# Download
|
6
|
+
|
7
|
+
The latest version of Pakyow Reflection can be installed with RubyGems:
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install pakyow-reflection
|
11
|
+
```
|
12
|
+
|
13
|
+
Source code can be downloaded as part of the Pakyow project on Github:
|
14
|
+
|
15
|
+
- https://github.com/pakyow/pakyow/tree/master/pakyow-reflection
|
16
|
+
|
17
|
+
# License
|
18
|
+
|
19
|
+
Pakyow Reflection is free and open-source under the [LGPLv3 license](https://choosealicense.com/licenses/gpl-3.0/).
|
20
|
+
|
21
|
+
# Support
|
22
|
+
|
23
|
+
Found a bug? Tell us about it here:
|
24
|
+
|
25
|
+
- https://github.com/pakyow/pakyow/issues
|
26
|
+
|
27
|
+
We'd love to have you in the community:
|
28
|
+
|
29
|
+
- http://pakyow.org/get-involved
|
@@ -0,0 +1,25 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/inflector"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Reflection
|
7
|
+
class Action
|
8
|
+
attr_reader :name, :scope, :node, :view_path, :binding, :attributes, :nested, :parents
|
9
|
+
|
10
|
+
def initialize(name:, scope:, node:, view_path:, binding: nil, attributes: [], nested: [], parents: [])
|
11
|
+
@name, @scope, @node, @view_path, @binding, @attributes, @nested, @parents = normalize(name), scope, node, view_path, binding, attributes, nested, parents
|
12
|
+
end
|
13
|
+
|
14
|
+
def named?(name)
|
15
|
+
@name == normalize(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def normalize(name)
|
21
|
+
Support.inflector.singularize(name.to_s).to_sym
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/inflector"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Reflection
|
7
|
+
class Attribute
|
8
|
+
attr_reader :name, :type
|
9
|
+
|
10
|
+
def initialize(name, type:, required: false)
|
11
|
+
@name, @type, @required = normalize(name), type, required
|
12
|
+
end
|
13
|
+
|
14
|
+
def named?(name)
|
15
|
+
@name == normalize(name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def required?
|
19
|
+
@required == true
|
20
|
+
end
|
21
|
+
|
22
|
+
private
|
23
|
+
|
24
|
+
def normalize(name)
|
25
|
+
name.to_s.to_sym
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/class_state"
|
4
|
+
|
5
|
+
require "pakyow/reflection/builders/source"
|
6
|
+
require "pakyow/reflection/builders/endpoints"
|
7
|
+
require "pakyow/reflection/builders/actions"
|
8
|
+
|
9
|
+
module Pakyow
|
10
|
+
module Reflection
|
11
|
+
module Behavior
|
12
|
+
module Config
|
13
|
+
extend Support::Extension
|
14
|
+
|
15
|
+
apply_extension do
|
16
|
+
configurable :reflection do
|
17
|
+
setting :builders, {
|
18
|
+
source: Builders::Source,
|
19
|
+
endpoints: Builders::Endpoints,
|
20
|
+
actions: Builders::Actions
|
21
|
+
}
|
22
|
+
|
23
|
+
setting :ignored_template_stores, [:errors]
|
24
|
+
|
25
|
+
configurable :data do
|
26
|
+
setting :connection, :default
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/class_state"
|
4
|
+
|
5
|
+
require "pakyow/reflection/mirror"
|
6
|
+
|
7
|
+
module Pakyow
|
8
|
+
module Reflection
|
9
|
+
module Behavior
|
10
|
+
module Reflecting
|
11
|
+
extend Support::Extension
|
12
|
+
|
13
|
+
apply_extension do
|
14
|
+
attr_reader :mirror
|
15
|
+
|
16
|
+
after "initialize", priority: :high do
|
17
|
+
@mirror = Mirror.new(self)
|
18
|
+
|
19
|
+
builders = Hash[
|
20
|
+
config.reflection.builders.map { |type, builder|
|
21
|
+
[type, builder.new(self, @mirror.scopes)]
|
22
|
+
}
|
23
|
+
]
|
24
|
+
|
25
|
+
# Build the scopes.
|
26
|
+
#
|
27
|
+
@mirror.scopes.each do |scope|
|
28
|
+
builders[:source].build(scope)
|
29
|
+
end
|
30
|
+
|
31
|
+
# Build the actions.
|
32
|
+
#
|
33
|
+
@mirror.scopes.each do |scope|
|
34
|
+
builders[:actions].build(scope.actions)
|
35
|
+
end
|
36
|
+
|
37
|
+
# Build the endpoints.
|
38
|
+
#
|
39
|
+
builders[:endpoints].build(@mirror.endpoints)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/extension"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Reflection
|
7
|
+
module Behavior
|
8
|
+
module Rendering
|
9
|
+
module InstallFormMetadata
|
10
|
+
extend Support::Extension
|
11
|
+
|
12
|
+
apply_extension do
|
13
|
+
build do |view, composer:|
|
14
|
+
forms = view.forms
|
15
|
+
if !view.object.is_a?(StringDoc) && view.object.significant?(:form)
|
16
|
+
forms << view
|
17
|
+
end
|
18
|
+
|
19
|
+
forms.each do |form|
|
20
|
+
form.label(:form)[:view_path] = composer.view_path
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,80 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/reflection/builders/abstract"
|
4
|
+
require "pakyow/reflection/builders/helpers/controller"
|
5
|
+
|
6
|
+
module Pakyow
|
7
|
+
module Reflection
|
8
|
+
module Builders
|
9
|
+
class Actions < Abstract
|
10
|
+
include Helpers::Controller
|
11
|
+
|
12
|
+
def build(actions)
|
13
|
+
actions.each do |action|
|
14
|
+
define_action(action)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def define_action(action)
|
21
|
+
if action.parents.any?
|
22
|
+
parents = action.parents.dup
|
23
|
+
|
24
|
+
current_resource = ensure_controller_has_helpers(
|
25
|
+
find_or_define_resource_for_scope_at_path(parents.shift, action.view_path)
|
26
|
+
)
|
27
|
+
|
28
|
+
parents.each do |parent|
|
29
|
+
current_resource = ensure_controller_has_helpers(
|
30
|
+
find_or_define_resource_for_scope_in_resource(parent, current_resource)
|
31
|
+
)
|
32
|
+
end
|
33
|
+
|
34
|
+
resource = find_or_define_resource_for_scope_in_resource(action.scope, current_resource)
|
35
|
+
else
|
36
|
+
resource = find_or_define_resource_for_scope_at_path(action.scope, action.view_path)
|
37
|
+
end
|
38
|
+
|
39
|
+
ensure_controller_has_helpers(resource)
|
40
|
+
|
41
|
+
# Define the route unless it exists.
|
42
|
+
#
|
43
|
+
# Actions are easy since they always go in the resource controller for
|
44
|
+
# the scope. If a nested scope, the action is defined on the nested
|
45
|
+
# resource returned by `find_or_define_resource_for_scope`.
|
46
|
+
#
|
47
|
+
route = resource.routes.values.flatten.find { |possible_route|
|
48
|
+
possible_route.name == action.name
|
49
|
+
} || resource.send(action.name) do
|
50
|
+
reflect
|
51
|
+
end
|
52
|
+
|
53
|
+
# Install the reflect action if it hasn't been installed for this route.
|
54
|
+
#
|
55
|
+
if route.name
|
56
|
+
unless action.node.labeled?(:endpoint)
|
57
|
+
form_endpoint_name = [resource.name_of_self.to_s, route.name.to_s].join("_").to_sym
|
58
|
+
action.node.significance << :endpoint
|
59
|
+
action.node.set_label(:endpoint, form_endpoint_name)
|
60
|
+
action.node.attributes[:"data-e"] = form_endpoint_name
|
61
|
+
end
|
62
|
+
|
63
|
+
resource.action :set_reflected_action, only: [route.name] do
|
64
|
+
if connection.form
|
65
|
+
form_view_path = connection.form[:view_path]
|
66
|
+
form_binding = connection.form[:binding]&.to_sym
|
67
|
+
|
68
|
+
connection.set(:__reflected_action, action.scope.actions.find { |possible_action|
|
69
|
+
possible_action.view_path == form_view_path && possible_action.binding == form_binding
|
70
|
+
})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
else
|
74
|
+
# TODO: warn the user that a reflection couldn't be installed for an unnamed route
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
@@ -0,0 +1,86 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/core_refinements/string/normalization"
|
4
|
+
|
5
|
+
require "pakyow/reflection/builders/abstract"
|
6
|
+
require "pakyow/reflection/builders/helpers/controller"
|
7
|
+
require "pakyow/reflection/extensions/controller"
|
8
|
+
|
9
|
+
module Pakyow
|
10
|
+
module Reflection
|
11
|
+
module Builders
|
12
|
+
class Endpoints < Abstract
|
13
|
+
include Helpers::Controller
|
14
|
+
|
15
|
+
using Support::Refinements::String::Normalization
|
16
|
+
|
17
|
+
def build(endpoints)
|
18
|
+
endpoints.each do |endpoint|
|
19
|
+
define_endpoint(endpoint)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def define_endpoint(endpoint)
|
26
|
+
controller = if within_resource?(endpoint.view_path)
|
27
|
+
find_or_define_resource_for_scope_at_path(
|
28
|
+
resource_source_at_path(endpoint.view_path),
|
29
|
+
controller_path(endpoint.view_path),
|
30
|
+
endpoint.type
|
31
|
+
)
|
32
|
+
else
|
33
|
+
find_or_define_controller_at_path(controller_path(endpoint.view_path))
|
34
|
+
end
|
35
|
+
|
36
|
+
# TODO: Make this the responsibility of the helpers.
|
37
|
+
#
|
38
|
+
ensure_controller_has_helpers(controller)
|
39
|
+
|
40
|
+
if controller.expansions.include?(:resource)
|
41
|
+
endpoint_name = String.normalize_path(
|
42
|
+
endpoint.view_path.gsub(String.collapse_path(controller.path_to_self), "")
|
43
|
+
).split("/", 2)[1]
|
44
|
+
|
45
|
+
endpoint_name = if endpoint_name.empty?
|
46
|
+
:list
|
47
|
+
else
|
48
|
+
endpoint_name.to_sym
|
49
|
+
end
|
50
|
+
|
51
|
+
case endpoint_name
|
52
|
+
when :new, :edit, :list, :show
|
53
|
+
# Find or define the route by resource endpoint name.
|
54
|
+
#
|
55
|
+
route = controller.routes.values.flatten.find { |possible_route|
|
56
|
+
possible_route.name == endpoint_name
|
57
|
+
} || controller.send(endpoint_name) do
|
58
|
+
reflect
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
unless route
|
64
|
+
# Find or define the route by path.
|
65
|
+
#
|
66
|
+
# TODO: This should look across all controllers, not just the current one. Look through endpoints?
|
67
|
+
#
|
68
|
+
route = controller.routes.values.flatten.find { |possible_route|
|
69
|
+
possible_route.path == route_path(endpoint.view_path)
|
70
|
+
} || controller.get(route_name(endpoint.view_path), route_path(endpoint.view_path)) do
|
71
|
+
operations.reflect(controller: self)
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
if route.name
|
76
|
+
controller.action :set_reflected_endpoint, only: [route.name] do
|
77
|
+
connection.set(:__reflected_endpoint, endpoint)
|
78
|
+
end
|
79
|
+
else
|
80
|
+
# TODO: warn the user that a reflection couldn't be installed for an unnamed route
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|
86
|
+
end
|
@@ -0,0 +1,234 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/support/core_refinements/string/normalization"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Reflection
|
7
|
+
module Builders
|
8
|
+
module Helpers
|
9
|
+
module Controller
|
10
|
+
using Support::Refinements::String::Normalization
|
11
|
+
|
12
|
+
def find_or_define_controller_at_path(path)
|
13
|
+
controller_at_path(path) || define_controller_at_path(path)
|
14
|
+
end
|
15
|
+
|
16
|
+
def controller_at_path(path, state = @app.state(:controller))
|
17
|
+
if state.any?
|
18
|
+
state.find { |controller|
|
19
|
+
String.normalize_path(String.collapse_path(controller.path_to_self)) == String.normalize_path(path)
|
20
|
+
} || controller_at_path(path, state.flat_map(&:children))
|
21
|
+
else
|
22
|
+
nil
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
def controller_closest_to_path(path, state = @app.state(:controller))
|
27
|
+
if state.any?
|
28
|
+
controller_closest_to_path(path, state.flat_map(&:children)) || state.find { |controller|
|
29
|
+
String.normalize_path(path).start_with?(String.normalize_path(String.collapse_path(controller.path_to_self)))
|
30
|
+
}
|
31
|
+
else
|
32
|
+
nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def define_controller_at_path(path, within: nil)
|
37
|
+
nested_state = if within
|
38
|
+
within.children
|
39
|
+
else
|
40
|
+
@app.state(:controller)
|
41
|
+
end
|
42
|
+
|
43
|
+
path = String.normalize_path(path)
|
44
|
+
|
45
|
+
if controller = controller_closest_to_path(path, nested_state)
|
46
|
+
context = controller
|
47
|
+
path = path.gsub(
|
48
|
+
/^#{String.normalize_path(String.collapse_path(controller.path_to_self))}/, ""
|
49
|
+
)
|
50
|
+
else
|
51
|
+
context = within || @app
|
52
|
+
end
|
53
|
+
|
54
|
+
controller_name = if path == "/"
|
55
|
+
:root
|
56
|
+
else
|
57
|
+
String.normalize_path(path)[1..-1].gsub("/", "_").to_sym
|
58
|
+
end
|
59
|
+
|
60
|
+
method = if context.is_a?(Class) && context.ancestors.include?(Pakyow::Controller)
|
61
|
+
:namespace
|
62
|
+
else
|
63
|
+
:controller
|
64
|
+
end
|
65
|
+
|
66
|
+
context.send(method, controller_name, String.normalize_path(path)) do
|
67
|
+
# intentionally empty
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def controller_path(view_path)
|
72
|
+
if view_path_directory?(view_path)
|
73
|
+
view_path
|
74
|
+
else
|
75
|
+
view_path.split("/")[0..-2].to_a.join("/")
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def within_resource?(view_path)
|
80
|
+
view_path.split("/").any? { |view_path_part|
|
81
|
+
@app.state(:source).any? { |source|
|
82
|
+
source.plural_name == view_path_part.to_sym
|
83
|
+
}
|
84
|
+
}
|
85
|
+
end
|
86
|
+
|
87
|
+
def route_name(view_path)
|
88
|
+
if view_path_directory?(view_path)
|
89
|
+
:default
|
90
|
+
else
|
91
|
+
view_path.split("/").last.to_sym
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
def route_path(view_path)
|
96
|
+
if view_path_directory?(view_path)
|
97
|
+
"/"
|
98
|
+
else
|
99
|
+
"/#{view_path.split("/").last}"
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def resource_source_at_path(view_path)
|
104
|
+
view_path.split("/").reverse.each do |view_path_part|
|
105
|
+
@app.state(:source).each do |source|
|
106
|
+
if source.plural_name == view_path_part.to_sym
|
107
|
+
return source
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def view_path_directory?(view_path)
|
114
|
+
@app.state(:templates).any? { |templates|
|
115
|
+
File.directory?(File.join(templates.path, templates.config[:paths][:pages], view_path))
|
116
|
+
}
|
117
|
+
end
|
118
|
+
|
119
|
+
RESOURCE_ENDPOINTS = %i(new edit list show).freeze
|
120
|
+
|
121
|
+
def find_or_define_resource_for_scope_at_path(scope, path, endpoint_type = nil)
|
122
|
+
resource = resource_for_scope_at_path(scope, path) || define_resource_for_scope_at_path(scope, path)
|
123
|
+
|
124
|
+
if path.end_with?(resource_path_for_scope(scope)) || endpoint_type.nil? || RESOURCE_ENDPOINTS.include?(path.split("/").last.to_sym)
|
125
|
+
return resource
|
126
|
+
else
|
127
|
+
controller_for_endpoint_type = resource.send(endpoint_type)
|
128
|
+
|
129
|
+
nested_path = if view_path_directory?(path)
|
130
|
+
path
|
131
|
+
else
|
132
|
+
path.split("/")[0..-2].join("/")
|
133
|
+
end
|
134
|
+
|
135
|
+
nested_path = nested_path.gsub(
|
136
|
+
/^#{String.normalize_path(String.collapse_path(controller_for_endpoint_type.path_to_self))}/, ""
|
137
|
+
)
|
138
|
+
|
139
|
+
if current_controller = controller_at_path(nested_path, resource.children)
|
140
|
+
return current_controller
|
141
|
+
else
|
142
|
+
if nested_path.empty?
|
143
|
+
controller_for_endpoint_type
|
144
|
+
else
|
145
|
+
define_controller_at_path(nested_path, within: controller_for_endpoint_type)
|
146
|
+
end
|
147
|
+
end
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
def resource_for_scope_at_path(scope, path, state = @app.state(:controller))
|
152
|
+
if state.any?
|
153
|
+
state.select { |controller|
|
154
|
+
controller.expansions.include?(:resource)
|
155
|
+
}.find { |controller|
|
156
|
+
String.normalize_path(String.collapse_path(controller.path_to_self)) == full_resource_path_for_scope_at_path(scope, path)
|
157
|
+
} || resource_for_scope_at_path(scope, path, state.flat_map(&:children))
|
158
|
+
else
|
159
|
+
nil
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
def define_resource_for_scope_at_path(scope, path)
|
164
|
+
context = if resource_namespace_path = resource_namespace_path_for_scope_at_path(scope, path)
|
165
|
+
if within_resource?(resource_namespace_path)
|
166
|
+
ensure_controller_has_helpers(
|
167
|
+
find_or_define_resource_for_scope_at_path(
|
168
|
+
resource_source_at_path(resource_namespace_path), resource_namespace_path
|
169
|
+
)
|
170
|
+
)
|
171
|
+
else
|
172
|
+
ensure_controller_has_helpers(
|
173
|
+
find_or_define_controller_at_path(resource_namespace_path)
|
174
|
+
)
|
175
|
+
end
|
176
|
+
else
|
177
|
+
@app
|
178
|
+
end
|
179
|
+
|
180
|
+
context.resource resource_name_for_scope(scope), resource_path_for_scope(scope) do
|
181
|
+
# intentionally empty
|
182
|
+
end
|
183
|
+
end
|
184
|
+
|
185
|
+
def resource_namespace_path_for_scope_at_path(scope, path)
|
186
|
+
resource_path = resource_path_for_scope(scope)
|
187
|
+
|
188
|
+
if path.start_with?(resource_path)
|
189
|
+
nil
|
190
|
+
elsif path.include?(resource_path)
|
191
|
+
path.split(resource_path, 2)[0]
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
def resource_name_for_scope(scope)
|
196
|
+
scope.plural_name
|
197
|
+
end
|
198
|
+
|
199
|
+
def resource_path_for_scope(scope)
|
200
|
+
String.normalize_path(scope.plural_name)
|
201
|
+
end
|
202
|
+
|
203
|
+
def ensure_controller_has_helpers(controller)
|
204
|
+
unless controller.ancestors.include?(Extension::Controller)
|
205
|
+
controller.include Extension::Controller
|
206
|
+
end
|
207
|
+
|
208
|
+
controller
|
209
|
+
end
|
210
|
+
|
211
|
+
def find_or_define_resource_for_scope_in_resource(scope, resource)
|
212
|
+
resource.children.find { |child|
|
213
|
+
child.path == resource_path_for_scope(scope)
|
214
|
+
} || resource.resource(resource_name_for_scope(scope), resource_path_for_scope(scope)) do
|
215
|
+
# intentionally empty
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
def full_resource_path_for_scope_at_path(scope, path)
|
220
|
+
String.normalize_path(
|
221
|
+
File.join(
|
222
|
+
resource_namespace_path_for_scope_at_path(scope, path).to_s,
|
223
|
+
scope.plural_name.to_s
|
224
|
+
)
|
225
|
+
)
|
226
|
+
end
|
227
|
+
|
228
|
+
|
229
|
+
|
230
|
+
end
|
231
|
+
end
|
232
|
+
end
|
233
|
+
end
|
234
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "pakyow/reflection/builders/abstract"
|
4
|
+
|
5
|
+
module Pakyow
|
6
|
+
module Reflection
|
7
|
+
module Builders
|
8
|
+
class Source < Abstract
|
9
|
+
def build(scope)
|
10
|
+
(source_for_scope(scope) || define_source_for_scope(scope)).class_eval do
|
11
|
+
scope.attributes.each do |attribute|
|
12
|
+
unless attributes.key?(attribute.name)
|
13
|
+
attribute attribute.name, attribute.type
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
scope.children.each do |child_scope|
|
18
|
+
unless associations[:has_many].any? { |association|
|
19
|
+
association.name == child_scope.plural_name
|
20
|
+
} || associations[:has_one].any? { |association|
|
21
|
+
association.name == child_scope.name
|
22
|
+
}
|
23
|
+
has_many child_scope.plural_name, dependent: :delete
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
private
|
30
|
+
|
31
|
+
def source_for_scope(scope)
|
32
|
+
@app.state(:source).find { |source|
|
33
|
+
source.plural_name == scope.plural_name
|
34
|
+
}
|
35
|
+
end
|
36
|
+
|
37
|
+
def define_source_for_scope(scope)
|
38
|
+
connection = if scope.actions.any?
|
39
|
+
@app.config.reflection.data.connection
|
40
|
+
else
|
41
|
+
:memory
|
42
|
+
end
|
43
|
+
|
44
|
+
@app.source scope.plural_name, adapter: :sql, connection: connection do
|
45
|
+
# intentionally empty
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|