effective_resources 1.5.5 → 1.6.4
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.md +9 -2
- data/app/controllers/concerns/effective/crud_controller.rb +7 -1
- data/app/controllers/concerns/effective/crud_controller/actions.rb +14 -4
- data/app/controllers/concerns/effective/crud_controller/dsl.rb +1 -1
- data/app/controllers/concerns/effective/crud_controller/permitted_params.rb +7 -7
- data/app/controllers/concerns/effective/crud_controller/save.rb +3 -1
- data/app/controllers/concerns/effective/wizard_controller.rb +65 -0
- data/app/controllers/concerns/effective/wizard_controller/actions.rb +30 -0
- data/app/controllers/concerns/effective/wizard_controller/before_actions.rb +69 -0
- data/app/controllers/concerns/effective/wizard_controller/save.rb +24 -0
- data/app/helpers/effective_resources_wizard_helper.rb +38 -0
- data/app/models/concerns/acts_as_wizard.rb +103 -0
- data/app/models/effective/resources/actions.rb +31 -17
- data/app/models/effective/resources/init.rb +44 -43
- data/app/models/effective/resources/klass.rb +4 -0
- data/app/models/effective/resources/naming.rb +8 -0
- data/lib/effective_resources.rb +1 -0
- data/lib/effective_resources/engine.rb +4 -1
- data/lib/effective_resources/version.rb +1 -1
- metadata +92 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4bb7652d9f80993d8147a2256189201111268282d81f881172df757474113e39
|
4
|
+
data.tar.gz: 101536d12175828d0ae1008e2d6dbf226e3f594a93c55f7566f89a17d3bcd1c8
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 360ae9e38369c840302b06696686e3e3f64ed4375fdc651571f29208c437281248c02ab8aed272063e3f3e0fd6ab999e891bbe368e60f93ff05cbc27521abffa
|
7
|
+
data.tar.gz: 5cfa3f62f33ec8f0d2b1c2ea11806634964af86f9b19c2088ea184c1cf528bcabf3d7c4c0c873125ab90d60eb8a794ca376c91d78a05cd57f43137d6f827567f
|
data/README.md
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
# Effective Resources
|
2
2
|
|
3
3
|
This gem looks at the current `routes.rb`, authorization `ability.rb`, `current_user` and controller context
|
4
|
-
to metaprogram an effective CRUD website.
|
4
|
+
to metaprogram an effective CRUD website.
|
5
5
|
|
6
6
|
It automates linking to resource edit, show, delete pages, as well as member and collection actions.
|
7
7
|
|
@@ -256,6 +256,14 @@ end
|
|
256
256
|
|
257
257
|
and include Effective::CrudController in your resource controller.
|
258
258
|
|
259
|
+
## Testing
|
260
|
+
|
261
|
+
Run tests by:
|
262
|
+
|
263
|
+
```ruby
|
264
|
+
rails test
|
265
|
+
```
|
266
|
+
|
259
267
|
## License
|
260
268
|
|
261
269
|
MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
@@ -268,4 +276,3 @@ MIT License. Copyright [Code and Effect Inc.](http://www.codeandeffect.com/)
|
|
268
276
|
4. Push to the branch (`git push origin my-new-feature`)
|
269
277
|
5. Bonus points for test coverage
|
270
278
|
6. Create new Pull Request
|
271
|
-
|
@@ -71,6 +71,10 @@ module Effective
|
|
71
71
|
effective_resource.name
|
72
72
|
end
|
73
73
|
|
74
|
+
def resource_name_id
|
75
|
+
(effective_resource.name + '_id').to_sym
|
76
|
+
end
|
77
|
+
|
74
78
|
def resource_klass # Thing
|
75
79
|
effective_resource.klass
|
76
80
|
end
|
@@ -118,7 +122,9 @@ module Effective
|
|
118
122
|
|
119
123
|
return unless datatable_klass.present?
|
120
124
|
|
121
|
-
datatable_klass.new(resource_datatable_attributes)
|
125
|
+
datatable = datatable_klass.new(resource_datatable_attributes)
|
126
|
+
datatable.effective_resource = effective_resource if datatable.respond_to?(:effective_resource=)
|
127
|
+
datatable
|
122
128
|
end
|
123
129
|
|
124
130
|
def resource_params_method_name
|
@@ -63,8 +63,13 @@ module Effective
|
|
63
63
|
self.resource ||= resource_scope.new
|
64
64
|
action = (commit_action[:action] == :save ? :create : commit_action[:action])
|
65
65
|
|
66
|
-
|
67
|
-
|
66
|
+
if respond_to?(:current_user) && resource.respond_to?(:current_user=)
|
67
|
+
resource.current_user ||= current_user
|
68
|
+
end
|
69
|
+
|
70
|
+
if respond_to?(:current_user) && resource.respond_to?(:created_by=)
|
71
|
+
resource.created_by ||= current_user
|
72
|
+
end
|
68
73
|
|
69
74
|
resource.assign_attributes(send(resource_params_method_name))
|
70
75
|
|
@@ -121,8 +126,13 @@ module Effective
|
|
121
126
|
EffectiveResources.authorize!(self, action, resource)
|
122
127
|
@page_title ||= "Edit #{resource}"
|
123
128
|
|
124
|
-
|
125
|
-
|
129
|
+
if respond_to?(:current_user) && resource.respond_to?(:current_user=)
|
130
|
+
resource.current_user ||= current_user
|
131
|
+
end
|
132
|
+
|
133
|
+
if respond_to?(:current_user) && resource.respond_to?(:updated_by=)
|
134
|
+
resource.updated_by ||= current_user
|
135
|
+
end
|
126
136
|
|
127
137
|
resource.assign_attributes(send(resource_params_method_name))
|
128
138
|
|
@@ -80,7 +80,7 @@ module Effective
|
|
80
80
|
raise 'expected a proc or block' unless (obj.respond_to?(:call) || block_given?)
|
81
81
|
|
82
82
|
instance_exec do
|
83
|
-
|
83
|
+
before_action(opts) { @_effective_resource_scope ||= instance_exec(&(block_given? ? block : obj)) }
|
84
84
|
end
|
85
85
|
end
|
86
86
|
|
@@ -5,7 +5,7 @@ module Effective
|
|
5
5
|
|
6
6
|
# This is only available to models that use the effective_resource do ... end attributes block
|
7
7
|
# It will be called last, and only for those resources
|
8
|
-
# params.require(effective_resource.
|
8
|
+
# params.require(effective_resource.resource_name).permit!
|
9
9
|
def resource_permitted_params
|
10
10
|
raise 'expected resource class to have effective_resource do .. end' if effective_resource.model.blank?
|
11
11
|
|
@@ -13,10 +13,10 @@ module Effective
|
|
13
13
|
|
14
14
|
if Rails.env.development?
|
15
15
|
Rails.logger.info "Effective::CrudController#resource_permitted_params:"
|
16
|
-
Rails.logger.info "params.require(:#{effective_resource.
|
16
|
+
Rails.logger.info "params.require(:#{effective_resource.resource_name}).permit(#{permitted_params.to_s[1...-1]})"
|
17
17
|
end
|
18
18
|
|
19
|
-
params.require(effective_resource.
|
19
|
+
params.require(effective_resource.resource_name).permit(*permitted_params)
|
20
20
|
end
|
21
21
|
|
22
22
|
# If the resource is ActiveModel, just permit all
|
@@ -24,13 +24,13 @@ module Effective
|
|
24
24
|
def resource_active_model_permitted_params
|
25
25
|
if Rails.env.development?
|
26
26
|
Rails.logger.info "Effective::CrudController#resource_permitted_params:"
|
27
|
-
Rails.logger.info "params.require(:#{effective_resource.
|
27
|
+
Rails.logger.info "params.require(:#{effective_resource.resource_name}).permit!"
|
28
28
|
end
|
29
29
|
|
30
|
-
if params[effective_resource.
|
31
|
-
params.require(effective_resource.
|
30
|
+
if params[effective_resource.resource_name].present?
|
31
|
+
params.require(effective_resource.resource_name).permit!
|
32
32
|
else
|
33
|
-
params.require((effective_resource.namespaces + [effective_resource.
|
33
|
+
params.require((effective_resource.namespaces + [effective_resource.resource_name]).join('_')).permit!
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -24,7 +24,9 @@ module Effective
|
|
24
24
|
save_action = ([:create, :update].include?(action) ? :save : action)
|
25
25
|
raise "expected @#{resource_name} to respond to #{save_action}!" unless resource.respond_to?("#{save_action}!")
|
26
26
|
|
27
|
-
|
27
|
+
if respond_to?(:current_user) && resource.respond_to?(:current_user=)
|
28
|
+
resource.current_user ||= current_user
|
29
|
+
end
|
28
30
|
|
29
31
|
success = false
|
30
32
|
|
@@ -0,0 +1,65 @@
|
|
1
|
+
module Effective
|
2
|
+
module WizardController
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
unless defined?(Wicked)
|
6
|
+
raise("please install gem 'wicked' to use Effective::WizardController")
|
7
|
+
end
|
8
|
+
|
9
|
+
include Wicked::Wizard
|
10
|
+
include Effective::CrudController
|
11
|
+
|
12
|
+
include Effective::WizardController::Actions
|
13
|
+
include Effective::WizardController::BeforeActions
|
14
|
+
include Effective::WizardController::Save
|
15
|
+
|
16
|
+
included do
|
17
|
+
with_options(only: [:show, :update]) do
|
18
|
+
before_action :redirect_if_blank_step
|
19
|
+
|
20
|
+
before_action :assign_resource
|
21
|
+
before_action :authorize_resource
|
22
|
+
before_action :assign_required_steps
|
23
|
+
before_action :setup_wizard # Wicked
|
24
|
+
|
25
|
+
before_action :enforce_can_visit_step
|
26
|
+
|
27
|
+
before_action :assign_current_step
|
28
|
+
before_action :assign_page_title
|
29
|
+
end
|
30
|
+
|
31
|
+
helper_method :resource
|
32
|
+
helper_method :resource_wizard_step_title
|
33
|
+
|
34
|
+
helper EffectiveResourcesWizardHelper
|
35
|
+
|
36
|
+
rescue_from Wicked::Wizard::InvalidStepError do |exception|
|
37
|
+
flash[:danger] = "Unknown step. You have been moved to the #{resource_wizard_steps.first} step."
|
38
|
+
redirect_to wizard_path(resource_wizard_steps.first)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
def find_wizard_resource
|
43
|
+
if params[resource_name_id] && params[resource_name_id] != 'new'
|
44
|
+
resource_scope.find(params[resource_name_id])
|
45
|
+
else
|
46
|
+
resource_scope.new
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def resource_wizard_step_title(step)
|
51
|
+
return if step == 'wicked_finish'
|
52
|
+
effective_resource.klass.const_get(:WIZARD_STEPS).fetch(step)
|
53
|
+
end
|
54
|
+
|
55
|
+
def resource_wizard_steps
|
56
|
+
effective_resource.klass.const_get(:WIZARD_STEPS).keys
|
57
|
+
end
|
58
|
+
|
59
|
+
def resource_wizard_path(resource, step)
|
60
|
+
path_helper = effective_resource.action_path_helper(:show).to_s.sub('_path', '_build_path')
|
61
|
+
public_send(path_helper, resource, step)
|
62
|
+
end
|
63
|
+
|
64
|
+
end
|
65
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Effective
|
2
|
+
module WizardController
|
3
|
+
module Actions
|
4
|
+
|
5
|
+
def new
|
6
|
+
Rails.logger.info 'Processed by Effective::WizardController#new'
|
7
|
+
|
8
|
+
self.resource ||= resource_scope.new
|
9
|
+
EffectiveResources.authorize!(self, :new, resource)
|
10
|
+
|
11
|
+
redirect_to resource_wizard_path(:new, resource_wizard_steps.first)
|
12
|
+
end
|
13
|
+
|
14
|
+
def show
|
15
|
+
Rails.logger.info 'Processed by Effective::WizardController#show'
|
16
|
+
|
17
|
+
render_wizard
|
18
|
+
end
|
19
|
+
|
20
|
+
def update
|
21
|
+
Rails.logger.info 'Processed by Effective::WizardController#update'
|
22
|
+
|
23
|
+
resource.assign_attributes(send(resource_params_method_name))
|
24
|
+
|
25
|
+
save_wizard_resource(resource)
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module Effective
|
2
|
+
module WizardController
|
3
|
+
module BeforeActions
|
4
|
+
|
5
|
+
# before_action :redirect_if_blank_step, only: [:show]
|
6
|
+
# When I visit /resources/1, redirect to /resources/1/build/step
|
7
|
+
def redirect_if_blank_step
|
8
|
+
if params[:id].present? && params[resource_name_id].blank?
|
9
|
+
params[resource_name_id] = params[:id]
|
10
|
+
|
11
|
+
assign_resource()
|
12
|
+
|
13
|
+
step = (resource.first_uncompleted_step || resource_wizard_steps.last)
|
14
|
+
redirect_to resource_wizard_path(resource, step)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# before_action :assign_resource, only: [:show, :update]
|
19
|
+
# Assigns the resource
|
20
|
+
def assign_resource
|
21
|
+
self.resource ||= find_wizard_resource
|
22
|
+
end
|
23
|
+
|
24
|
+
# before_action :authorize_resource, only: [:show, :update]
|
25
|
+
# Authorize the resource
|
26
|
+
def authorize_resource
|
27
|
+
EffectiveResources.authorize!(self, action_name.to_sym, resource)
|
28
|
+
end
|
29
|
+
|
30
|
+
# before_action :assign_required_steps, only: [:show, :update]
|
31
|
+
# Assign the required steps to Wickeds (dynamic steps)
|
32
|
+
def assign_required_steps
|
33
|
+
self.steps = resource.required_steps
|
34
|
+
end
|
35
|
+
|
36
|
+
# setup_wizard from Wicked called now
|
37
|
+
|
38
|
+
# before_action :enforce_can_visit_step, only: [:show, :update]
|
39
|
+
# Make sure I have permission for this step
|
40
|
+
def enforce_can_visit_step
|
41
|
+
return if step == 'wicked_finish'
|
42
|
+
return if resource.can_visit_step?(step)
|
43
|
+
|
44
|
+
next_step = wizard_steps.reverse.find { |step| resource.can_visit_step?(step) }
|
45
|
+
raise('There is no wizard step to visit') unless next_step
|
46
|
+
|
47
|
+
flash[:danger] = "You have been redirected to the #{resource_wizard_step_title(next_step)} step."
|
48
|
+
redirect_to wizard_path(next_step)
|
49
|
+
end
|
50
|
+
|
51
|
+
# before_action :assign_current_step, only: [:show, :update]
|
52
|
+
# Assign the urrent step to resource
|
53
|
+
def assign_current_step
|
54
|
+
if respond_to?(:current_user) && resource.respond_to?(:current_user=)
|
55
|
+
resource.current_user = current_user
|
56
|
+
end
|
57
|
+
|
58
|
+
resource.current_step = step.to_sym
|
59
|
+
end
|
60
|
+
|
61
|
+
# before_action :assign_page_title, only: [:show, :update]
|
62
|
+
# Assign page title
|
63
|
+
def assign_page_title
|
64
|
+
@page_title ||= resource_wizard_step_title(step)
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
@@ -0,0 +1,24 @@
|
|
1
|
+
module Effective
|
2
|
+
module WizardController
|
3
|
+
module Save
|
4
|
+
|
5
|
+
def save_wizard_resource(resource, action = nil, options = {})
|
6
|
+
was_new_record = resource.new_record?
|
7
|
+
action ||= resource.respond_to?("#{step}!") ? step : :save
|
8
|
+
|
9
|
+
if save_resource(resource, action)
|
10
|
+
flash[:success] = options.delete(:success) || resource_flash(:success, resource, action)
|
11
|
+
|
12
|
+
@skip_to ||= next_step
|
13
|
+
@redirect_to ||= resource_wizard_path(resource, @skip_to) if was_new_record
|
14
|
+
|
15
|
+
redirect_to(@redirect_to || wizard_path(@skip_to))
|
16
|
+
else
|
17
|
+
flash.now[:danger] = options.delete(:error) || resource_flash(:danger, resource, action)
|
18
|
+
render_step(wizard_value(step), options)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module EffectiveResourcesWizardHelper
|
4
|
+
|
5
|
+
def render_wizard_sidebar(resource, numbers: true, &block)
|
6
|
+
sidebar = content_tag(:div, class: 'nav list-group wizard-sidebar') do
|
7
|
+
resource.required_steps.map.with_index do |nav_step, index|
|
8
|
+
render_wizard_sidebar_item(resource, nav_step, (index + 1 if numbers))
|
9
|
+
end.join.html_safe
|
10
|
+
end
|
11
|
+
|
12
|
+
return sidebar unless block_given?
|
13
|
+
|
14
|
+
content_tag(:div, class: 'row') do
|
15
|
+
content_tag(:div, class: 'col-3') { sidebar } +
|
16
|
+
content_tag(:div, class: 'col-9') { yield }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def render_wizard_sidebar_item(resource, nav_step, index = nil)
|
21
|
+
# From Controller
|
22
|
+
current = (nav_step == step)
|
23
|
+
title = resource_wizard_step_title(nav_step)
|
24
|
+
|
25
|
+
# From Model
|
26
|
+
disabled = !resource.can_visit_step?(nav_step)
|
27
|
+
|
28
|
+
label = [index, title].compact.join('. ')
|
29
|
+
klass = ['list-group-item', ('active' if current), ('disabled' if disabled && !current)].compact.join(' ')
|
30
|
+
|
31
|
+
if (current || disabled)
|
32
|
+
content_tag(:li, label, class: klass)
|
33
|
+
else
|
34
|
+
link_to(label, wizard_path(nav_step), class: klass)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
# ActsAsWizard
|
2
|
+
# Works alongside wicked gem to build a wizard
|
3
|
+
# https://github.com/zombocom/wicked
|
4
|
+
|
5
|
+
# acts_as_wizard(start: 'Start Step', select: 'Select Step', finish: 'Finished')
|
6
|
+
|
7
|
+
module ActsAsWizard
|
8
|
+
extend ActiveSupport::Concern
|
9
|
+
|
10
|
+
module Base
|
11
|
+
def acts_as_wizard(steps)
|
12
|
+
raise 'acts_as_wizard expected a Hash of steps' unless steps.kind_of?(Hash)
|
13
|
+
|
14
|
+
unless steps.all? { |k, v| k.kind_of?(Symbol) && v.kind_of?(String) }
|
15
|
+
raise 'acts_as_wizard expected a Hash of symbol => String steps'
|
16
|
+
end
|
17
|
+
|
18
|
+
@acts_as_wizard_options = {steps: steps}
|
19
|
+
|
20
|
+
include ::ActsAsWizard
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
included do
|
25
|
+
acts_as_wizard_options = @acts_as_wizard_options
|
26
|
+
|
27
|
+
attr_accessor :current_step
|
28
|
+
attr_accessor :current_user
|
29
|
+
|
30
|
+
if Rails.env.test? # So our tests can override the required_steps method
|
31
|
+
cattr_accessor :test_required_steps
|
32
|
+
end
|
33
|
+
|
34
|
+
const_set(:WIZARD_STEPS, acts_as_wizard_options[:steps])
|
35
|
+
|
36
|
+
effective_resource do
|
37
|
+
wizard_steps :text, permitted: false
|
38
|
+
end
|
39
|
+
|
40
|
+
serialize :wizard_steps, Hash
|
41
|
+
|
42
|
+
before_save(if: -> { current_step.present? }) do
|
43
|
+
wizard_steps[current_step.to_sym] ||= Time.zone.now
|
44
|
+
end
|
45
|
+
|
46
|
+
def can_visit_step?(step)
|
47
|
+
can_revisit_completed_steps(step)
|
48
|
+
end
|
49
|
+
|
50
|
+
def required_steps
|
51
|
+
return self.class.test_required_steps if Rails.env.test? && self.class.test_required_steps.present?
|
52
|
+
self.class.const_get(:WIZARD_STEPS).keys
|
53
|
+
end
|
54
|
+
|
55
|
+
def first_completed_step
|
56
|
+
required_steps.find { |step| has_completed_step?(step) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def last_completed_step
|
60
|
+
required_steps.reverse.find { |step| has_completed_step?(step) }
|
61
|
+
end
|
62
|
+
|
63
|
+
def first_uncompleted_step
|
64
|
+
required_steps.find { |step| has_completed_step?(step) == false }
|
65
|
+
end
|
66
|
+
|
67
|
+
def has_completed_step?(step)
|
68
|
+
wizard_steps[step].present?
|
69
|
+
end
|
70
|
+
|
71
|
+
def previous_step(step)
|
72
|
+
index = required_steps.index(step)
|
73
|
+
required_steps[index-1] unless index == 0 || index.nil?
|
74
|
+
end
|
75
|
+
|
76
|
+
def has_completed_previous_step?(step)
|
77
|
+
previous = previous_step(step)
|
78
|
+
previous.blank? || has_completed_step?(previous)
|
79
|
+
end
|
80
|
+
|
81
|
+
def has_completed_last_step?
|
82
|
+
has_completed_step?(required_steps.last)
|
83
|
+
end
|
84
|
+
|
85
|
+
private
|
86
|
+
|
87
|
+
def can_revisit_completed_steps(step)
|
88
|
+
return (step == required_steps.last) if has_completed_last_step?
|
89
|
+
has_completed_previous_step?(step)
|
90
|
+
end
|
91
|
+
|
92
|
+
def cannot_revisit_completed_steps(step)
|
93
|
+
return (step == required_steps.last) if has_completed_last_step?
|
94
|
+
has_completed_previous_step?(step) && !has_completed_step?(step)
|
95
|
+
end
|
96
|
+
|
97
|
+
end
|
98
|
+
|
99
|
+
module ClassMethods
|
100
|
+
def acts_as_wizard?; true; end
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
@@ -11,24 +11,36 @@ module Effective
|
|
11
11
|
# Effective::Resource.new('admin/posts').routes[:index]
|
12
12
|
def routes
|
13
13
|
@routes ||= (
|
14
|
-
matches = [
|
14
|
+
matches = [
|
15
|
+
[namespace, plural_name].compact.join('/'),
|
16
|
+
[namespace, name].compact.join('/')
|
17
|
+
]
|
18
|
+
|
19
|
+
# Check main Rails app
|
20
|
+
routes = Rails.application.routes.routes.select do |route|
|
21
|
+
(matches & [route.defaults[:controller]]).present? && !route.name.to_s.end_with?('root')
|
22
|
+
end
|
23
|
+
|
24
|
+
# Check engine routes
|
25
|
+
if routes.blank?
|
26
|
+
matches = [
|
27
|
+
[namespace, plural_name].compact.join('/'),
|
28
|
+
[namespace, name].compact.join('/'),
|
29
|
+
['effective', namespace, plural_name].compact.join('/'),
|
30
|
+
['effective', namespace, name].compact.join('/')
|
31
|
+
]
|
32
|
+
|
33
|
+
(Rails::Engine.subclasses.reverse + [Rails.application]).each do |engine|
|
34
|
+
routes = engine.routes.routes.select do |route|
|
35
|
+
(matches & [route.defaults[:controller]]).present? && !route.name.to_s.end_with?('root')
|
36
|
+
end
|
15
37
|
|
16
|
-
|
17
|
-
|
18
|
-
end.inject({}) do |h, route|
|
19
|
-
h[route.defaults[:action].to_sym] = route; h
|
38
|
+
break if routes.present?
|
39
|
+
end
|
20
40
|
end
|
21
|
-
)
|
22
|
-
end
|
23
41
|
|
24
|
-
|
25
|
-
|
26
|
-
case class_name
|
27
|
-
when 'Effective::Order'
|
28
|
-
EffectiveOrders::Engine
|
29
|
-
else
|
30
|
-
Rails.application
|
31
|
-
end
|
42
|
+
Array(routes).inject({}) { |h, route| h[route.defaults[:action].to_sym] = route; h }
|
43
|
+
)
|
32
44
|
end
|
33
45
|
|
34
46
|
# Effective::Resource.new('admin/posts').action_path_helper(:edit) => 'edit_admin_posts_path'
|
@@ -73,13 +85,15 @@ module Effective
|
|
73
85
|
h[part] = target.public_send(part)
|
74
86
|
end
|
75
87
|
end
|
76
|
-
|
88
|
+
elsif target.respond_to?(:to_param) || target.respond_to?(:id)
|
77
89
|
target
|
90
|
+
else
|
91
|
+
{id: target}
|
78
92
|
end
|
79
93
|
end
|
80
94
|
|
81
95
|
# Generate the path
|
82
|
-
path = routes[action].format(formattable || EMPTY_HASH)
|
96
|
+
path = (routes[action].format(formattable || EMPTY_HASH) rescue nil)
|
83
97
|
|
84
98
|
if path.present? && opts.present?
|
85
99
|
uri = URI.parse(path)
|
@@ -6,8 +6,40 @@ module Effective
|
|
6
6
|
|
7
7
|
def _initialize_input(input, namespace: nil)
|
8
8
|
@initialized_name = input
|
9
|
+
@model_klass = _klass_by_input(input)
|
9
10
|
|
10
|
-
|
11
|
+
# Consider namespaces
|
12
|
+
if namespace
|
13
|
+
@namespaces = (namespace.kind_of?(String) ? namespace.split('/') : Array(namespace))
|
14
|
+
end
|
15
|
+
|
16
|
+
if input.kind_of?(Array) && @namespaces.blank?
|
17
|
+
@namespaces = input[0...-1].map { |input| input.to_s.presence }.compact
|
18
|
+
end
|
19
|
+
|
20
|
+
# Consider relation
|
21
|
+
if input.kind_of?(ActiveRecord::Relation)
|
22
|
+
@relation ||= input
|
23
|
+
end
|
24
|
+
|
25
|
+
if input.kind_of?(ActiveRecord::Reflection::MacroReflection) && input.scope
|
26
|
+
@relation ||= klass.where(nil).merge(input.scope)
|
27
|
+
end
|
28
|
+
|
29
|
+
# Consider instance
|
30
|
+
if klass && input.instance_of?(klass)
|
31
|
+
@instance ||= input
|
32
|
+
end
|
33
|
+
|
34
|
+
if klass && input.kind_of?(Array) && input.last.instance_of?(klass)
|
35
|
+
@instance ||= input.last
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def _klass_by_input(input)
|
40
|
+
case input
|
41
|
+
when Array
|
42
|
+
_klass_by_input(input.last)
|
11
43
|
when String, Symbol
|
12
44
|
_klass_by_name(input)
|
13
45
|
when Class
|
@@ -24,22 +56,6 @@ module Effective
|
|
24
56
|
when nil ; raise 'expected a string or class'
|
25
57
|
else ; _klass_by_name(input.class.name)
|
26
58
|
end
|
27
|
-
|
28
|
-
if namespace
|
29
|
-
@namespaces = (namespace.kind_of?(String) ? namespace.split('/') : Array(namespace))
|
30
|
-
end
|
31
|
-
|
32
|
-
if input.kind_of?(ActiveRecord::Relation)
|
33
|
-
@relation = input
|
34
|
-
end
|
35
|
-
|
36
|
-
if input.kind_of?(ActiveRecord::Reflection::MacroReflection) && input.scope
|
37
|
-
@relation = klass.where(nil).merge(input.scope)
|
38
|
-
end
|
39
|
-
|
40
|
-
if klass && input.instance_of?(klass)
|
41
|
-
@instance = input
|
42
|
-
end
|
43
59
|
end
|
44
60
|
|
45
61
|
def _klass_by_name(input)
|
@@ -48,6 +64,7 @@ module Effective
|
|
48
64
|
|
49
65
|
names = input.split('/')
|
50
66
|
|
67
|
+
# Crazy classify
|
51
68
|
0.upto(names.length-1) do |index|
|
52
69
|
class_name = names[index..-1].map { |name| name.classify } * '::'
|
53
70
|
klass = class_name.safe_constantize
|
@@ -64,35 +81,19 @@ module Effective
|
|
64
81
|
end
|
65
82
|
end
|
66
83
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
def _initialize_written
|
72
|
-
@written_attributes = []
|
73
|
-
@written_belong_tos = []
|
74
|
-
@written_scopes = []
|
75
|
-
|
76
|
-
return unless File.exists?(model_file)
|
77
|
-
|
78
|
-
Effective::CodeReader.new(model_file) do |reader|
|
79
|
-
first = reader.index { |line| line == '# Attributes' }
|
80
|
-
last = reader.index(from: first) { |line| line.start_with?('#') == false && line.length > 0 } if first
|
81
|
-
|
82
|
-
if first && last
|
83
|
-
@written_attributes = reader.select(from: first+1, to: last-1).map do |line|
|
84
|
-
Effective::Attribute.parse_written(line).presence
|
85
|
-
end.compact
|
86
|
-
end
|
87
|
-
|
88
|
-
@written_belong_tos = reader.select { |line| line.start_with?('belongs_to ') }.map do |line|
|
89
|
-
line.scan(/belongs_to\s+:(\w+)/).flatten.first
|
90
|
-
end
|
84
|
+
# Crazy engine
|
85
|
+
if names[0] == 'admin'
|
86
|
+
class_name = (['effective'] + names[1..-1]).map { |name| name.classify } * '::'
|
87
|
+
klass = class_name.safe_constantize
|
91
88
|
|
92
|
-
|
93
|
-
|
89
|
+
if klass.present?
|
90
|
+
@namespaces ||= names[0...-1]
|
91
|
+
@model_klass = klass
|
92
|
+
return klass
|
94
93
|
end
|
95
94
|
end
|
95
|
+
|
96
|
+
nil
|
96
97
|
end
|
97
98
|
|
98
99
|
end
|
@@ -9,8 +9,12 @@ module Effective
|
|
9
9
|
def datatable_klass
|
10
10
|
if defined?(EffectiveDatatables)
|
11
11
|
"#{namespaced_class_name.pluralize}Datatable".safe_constantize ||
|
12
|
+
"#{namespaced_module_name.pluralize}Datatable".safe_constantize ||
|
13
|
+
"#{namespaced_class_name.pluralize.gsub('::', '')}Datatable".safe_constantize ||
|
12
14
|
"#{class_name.pluralize.camelize}Datatable".safe_constantize ||
|
15
|
+
"#{class_name.pluralize.camelize.gsub('::', '')}Datatable".safe_constantize ||
|
13
16
|
"#{name.pluralize.camelize}Datatable".safe_constantize ||
|
17
|
+
"#{name.pluralize.camelize.gsub('::', '')}Datatable".safe_constantize ||
|
14
18
|
"Effective::Datatables::#{namespaced_class_name.pluralize}".safe_constantize ||
|
15
19
|
"Effective::Datatables::#{class_name.pluralize.camelize}".safe_constantize ||
|
16
20
|
"Effective::Datatables::#{name.pluralize.camelize}".safe_constantize
|
@@ -11,6 +11,10 @@ module Effective
|
|
11
11
|
name.pluralize
|
12
12
|
end
|
13
13
|
|
14
|
+
def resource_name # 'effective_post' used by permitted params
|
15
|
+
@resource_name ||= ((klass.present? ? klass.name : initialized_name).to_s.split(SPLIT).join('_') || '').singularize.underscore
|
16
|
+
end
|
17
|
+
|
14
18
|
def initialized_name
|
15
19
|
@initialized_name
|
16
20
|
end
|
@@ -27,6 +31,10 @@ module Effective
|
|
27
31
|
(Array(namespaces).map { |name| name.to_s.classify } + [class_name]) * '::'
|
28
32
|
end
|
29
33
|
|
34
|
+
def namespaced_module_name # 'Admin::EffectivePosts'
|
35
|
+
Array(namespaces).map { |name| name.to_s.classify }.join('::') + '::' + class_name.gsub('::', '')
|
36
|
+
end
|
37
|
+
|
30
38
|
def namespace # 'admin/things'
|
31
39
|
(namespaces.join('/') if namespaces.present?)
|
32
40
|
end
|
data/lib/effective_resources.rb
CHANGED
@@ -26,6 +26,7 @@ module EffectiveResources
|
|
26
26
|
ActiveRecord::Base.extend(ActsAsTokened::Base)
|
27
27
|
ActiveRecord::Base.extend(ActsAsSlugged::Base)
|
28
28
|
ActiveRecord::Base.extend(ActsAsStatused::Base)
|
29
|
+
ActiveRecord::Base.extend(ActsAsWizard::Base)
|
29
30
|
ActiveRecord::Base.extend(EffectiveResource::Base)
|
30
31
|
end
|
31
32
|
end
|
@@ -50,7 +51,9 @@ module EffectiveResources
|
|
50
51
|
# Register the acts_as_archived routes concern
|
51
52
|
# resources :things, concerns: :acts_as_archived
|
52
53
|
initializer 'effective_resources.routes_concern' do |app|
|
53
|
-
|
54
|
+
ActiveSupport.on_load :action_controller_base do
|
55
|
+
ActionDispatch::Routing::Mapper.include(ActsAsArchived::RoutesConcern)
|
56
|
+
end
|
54
57
|
end
|
55
58
|
|
56
59
|
# Register the flash_messages concern so that it can be called in ActionController
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: effective_resources
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.6.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Code and Effect
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2020-
|
11
|
+
date: 2020-12-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -24,6 +24,90 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: 4.0.0
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: sqlite3
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :development
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: effective_bootstrap
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :development
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: effective_datatables
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: haml
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: pry-byebug
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: wicked
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
27
111
|
description: Make any controller an effective resource controller.
|
28
112
|
email:
|
29
113
|
- info@codeandeffect.com
|
@@ -44,12 +128,18 @@ files:
|
|
44
128
|
- app/controllers/concerns/effective/crud_controller/save.rb
|
45
129
|
- app/controllers/concerns/effective/crud_controller/submits.rb
|
46
130
|
- app/controllers/concerns/effective/flash_messages.rb
|
131
|
+
- app/controllers/concerns/effective/wizard_controller.rb
|
132
|
+
- app/controllers/concerns/effective/wizard_controller/actions.rb
|
133
|
+
- app/controllers/concerns/effective/wizard_controller/before_actions.rb
|
134
|
+
- app/controllers/concerns/effective/wizard_controller/save.rb
|
47
135
|
- app/helpers/effective_resources_helper.rb
|
48
136
|
- app/helpers/effective_resources_private_helper.rb
|
137
|
+
- app/helpers/effective_resources_wizard_helper.rb
|
49
138
|
- app/models/concerns/acts_as_archived.rb
|
50
139
|
- app/models/concerns/acts_as_slugged.rb
|
51
140
|
- app/models/concerns/acts_as_statused.rb
|
52
141
|
- app/models/concerns/acts_as_tokened.rb
|
142
|
+
- app/models/concerns/acts_as_wizard.rb
|
53
143
|
- app/models/concerns/effective_resource.rb
|
54
144
|
- app/models/effective/access_denied.rb
|
55
145
|
- app/models/effective/action_failed.rb
|