undercarriage 0.1.0 → 0.4.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/README.md +42 -4
- data/lib/undercarriage.rb +15 -3
- data/lib/undercarriage/controllers/action_concern.rb +18 -0
- data/lib/undercarriage/controllers/kaminari_concern.rb +11 -0
- data/lib/undercarriage/controllers/locale_concern.rb +7 -1
- data/lib/undercarriage/controllers/restful/actions/base_concern.rb +120 -0
- data/lib/undercarriage/controllers/restful/actions/create_concern.rb +107 -0
- data/lib/undercarriage/controllers/restful/actions/destroy_concern.rb +97 -0
- data/lib/undercarriage/controllers/restful/actions/edit_concern.rb +94 -0
- data/lib/undercarriage/controllers/restful/actions/index_concern.rb +85 -0
- data/lib/undercarriage/controllers/restful/actions/new_concern.rb +96 -0
- data/lib/undercarriage/controllers/restful/actions/show_concern.rb +91 -0
- data/lib/undercarriage/controllers/restful/actions/update_concern.rb +105 -0
- data/lib/undercarriage/controllers/restful/flash_concern.rb +112 -0
- data/lib/undercarriage/controllers/restful/location_after_concern.rb +79 -0
- data/lib/undercarriage/controllers/restful/namespace_concern.rb +41 -0
- data/lib/undercarriage/controllers/restful/permitted_attributes_concern.rb +109 -0
- data/lib/undercarriage/controllers/restful/utility_concern.rb +74 -0
- data/lib/undercarriage/controllers/restful_concern.rb +34 -0
- data/lib/undercarriage/models/published_concern.rb +120 -0
- data/lib/undercarriage/version.rb +4 -1
- metadata +17 -4
- data/lib/tasks/undercarriage_tasks.rake +0 -6
- data/lib/undercarriage/railtie.rb +0 -6
@@ -0,0 +1,105 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Undercarriage
|
4
|
+
# :nodoc:
|
5
|
+
module Controllers
|
6
|
+
# :nodoc:
|
7
|
+
module Restful
|
8
|
+
# :nodoc:
|
9
|
+
module Actions
|
10
|
+
##
|
11
|
+
# Update restful action
|
12
|
+
#
|
13
|
+
# Usage
|
14
|
+
# class ExamplesController < ApplicationController
|
15
|
+
# include Undercarriage::Controllers::RestfulConcern
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
module UpdateConcern
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
included do
|
22
|
+
before_action :update_resource, only: %i[update]
|
23
|
+
end
|
24
|
+
|
25
|
+
##
|
26
|
+
# Update action
|
27
|
+
#
|
28
|
+
# Usage
|
29
|
+
# class ExamplesController < ApplicationController
|
30
|
+
# include Undercarriage::Controllers::RestfulConcern
|
31
|
+
#
|
32
|
+
# ##
|
33
|
+
# # This method is only needed if you want to override the action entirely. Otherwise, it is not needed.
|
34
|
+
# # Database resources can be accessed as `@update_resource` or `@example`
|
35
|
+
# #
|
36
|
+
# # def update
|
37
|
+
# # ...
|
38
|
+
# # end
|
39
|
+
# end
|
40
|
+
#
|
41
|
+
def update
|
42
|
+
nested_resource_pre_build
|
43
|
+
|
44
|
+
if @update_resource.update(update_resource_params)
|
45
|
+
after_update_action
|
46
|
+
|
47
|
+
flash[flash_status_type] = flash_updated_message
|
48
|
+
|
49
|
+
redirect_to location_after_update
|
50
|
+
else
|
51
|
+
nested_resource_build
|
52
|
+
|
53
|
+
render :edit, status: :unprocessable_entity
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
protected
|
58
|
+
|
59
|
+
##
|
60
|
+
# Update restful action
|
61
|
+
#
|
62
|
+
# Usage
|
63
|
+
# class ExamplesController < ApplicationController
|
64
|
+
# include Undercarriage::Controllers::RestfulConcern
|
65
|
+
#
|
66
|
+
# ##
|
67
|
+
# # This method is only needed if you want to override the query entirely. Otherwise, it is not needed.
|
68
|
+
# # Database resources can be accessed as `@example`
|
69
|
+
# #
|
70
|
+
# # def update_resource_content
|
71
|
+
# # ...
|
72
|
+
# # end
|
73
|
+
#
|
74
|
+
# ##
|
75
|
+
# # To add authorization through something like Pundit, the following could be used
|
76
|
+
# #
|
77
|
+
# # def update_resource_content
|
78
|
+
# # super
|
79
|
+
# #
|
80
|
+
# # authorize @example
|
81
|
+
# # end
|
82
|
+
#
|
83
|
+
# ##
|
84
|
+
# # The `resource_content` method can also be overwritten. Be careful with this because the `show`,
|
85
|
+
# # `edit` and `destroy` actions will also use this method
|
86
|
+
# #
|
87
|
+
# # def resource_content
|
88
|
+
# # ...
|
89
|
+
# # end
|
90
|
+
# end
|
91
|
+
#
|
92
|
+
def update_resource_content
|
93
|
+
resource_content
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
|
98
|
+
def update_resource
|
99
|
+
@update_resource ||= update_resource_content
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
105
|
+
end
|
@@ -0,0 +1,112 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Undercarriage
|
4
|
+
# :nodoc:
|
5
|
+
module Controllers
|
6
|
+
# :nodoc:
|
7
|
+
module Restful
|
8
|
+
##
|
9
|
+
# Flash
|
10
|
+
#
|
11
|
+
# Flash messages
|
12
|
+
#
|
13
|
+
# Usage
|
14
|
+
# class ExamplesController < ApplicationController
|
15
|
+
# include Undercarriage::Controllers::Restful::FlashConcern
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
# # config/locales/flash.en.yml
|
19
|
+
# flash:
|
20
|
+
# actions:
|
21
|
+
# create:
|
22
|
+
# notice: "%{resource_name} was successfully created."
|
23
|
+
# update:
|
24
|
+
# notice: "%{resource_name} was successfully updated."
|
25
|
+
# destroy:
|
26
|
+
# notice: "%{resource_name} was successfully destroyed."
|
27
|
+
# posts:
|
28
|
+
# create:
|
29
|
+
# notice: "Your %{downcase_resource_name} was created."
|
30
|
+
# update:
|
31
|
+
# notice_html: "<strong>Huzzah!</strong> Your %{downcase_resource_name} was updated."
|
32
|
+
# notice: "Huzzah! Your %{downcase_resource_name} was updated." # Not used since `notice_html` is defined
|
33
|
+
# things:
|
34
|
+
# destroy:
|
35
|
+
# notice: "Good riddance. That wasn't needed anyway."
|
36
|
+
#
|
37
|
+
module FlashConcern
|
38
|
+
extend ActiveSupport::Concern
|
39
|
+
|
40
|
+
included do
|
41
|
+
class_attribute :flash_status_type
|
42
|
+
self.flash_status_type = :success
|
43
|
+
end
|
44
|
+
|
45
|
+
protected
|
46
|
+
|
47
|
+
##
|
48
|
+
# Flash message for `#create` action
|
49
|
+
#
|
50
|
+
# Translate create flash message
|
51
|
+
#
|
52
|
+
def flash_created_message
|
53
|
+
flash_message_builder(:create, flash_status_type, 'created')
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
# Flash message for `#update` action
|
58
|
+
#
|
59
|
+
# Translate update flash message
|
60
|
+
#
|
61
|
+
def flash_updated_message
|
62
|
+
flash_message_builder(:update, flash_status_type, 'updated')
|
63
|
+
end
|
64
|
+
|
65
|
+
##
|
66
|
+
# Flash message for `#destroy` action
|
67
|
+
#
|
68
|
+
# Translate destroy flash message
|
69
|
+
#
|
70
|
+
def flash_destroyed_message
|
71
|
+
flash_message_builder(:destroy, flash_status_type, 'destroyed')
|
72
|
+
end
|
73
|
+
|
74
|
+
private
|
75
|
+
|
76
|
+
def flash_message_builder(action, status, past_tense)
|
77
|
+
defaults = flash_message_defaults(controller_name_singular_human, action, status, past_tense)
|
78
|
+
message = defaults.shift
|
79
|
+
|
80
|
+
I18n.t(message, resource_name: controller_name_singular_human,
|
81
|
+
downcase_resource_name: controller_name_singular,
|
82
|
+
default: defaults)
|
83
|
+
end
|
84
|
+
|
85
|
+
##
|
86
|
+
# Default flash messages
|
87
|
+
#
|
88
|
+
# List of default flash messages. The following is the list
|
89
|
+
#
|
90
|
+
# flash.[NAMESPACE].[CONTROLLER].[ACTION].[STATUS]_html
|
91
|
+
# flash.[NAMESPACE].[CONTROLLER].[ACTION].[STATUS]
|
92
|
+
# flash.[CONTROLLER].[ACTION].[STATUS]_html
|
93
|
+
# flash.[CONTROLLER].[ACTION].[STATUS]
|
94
|
+
# flash.actions.[ACTION].[STATUS]
|
95
|
+
# English default
|
96
|
+
#
|
97
|
+
def flash_message_defaults(resource_name, action, status, past_tense)
|
98
|
+
controller_with_namespace = [resource_namespace, controller_name].compact.join('.')
|
99
|
+
|
100
|
+
[
|
101
|
+
:"flash.#{controller_with_namespace}.#{action}.#{status}_html",
|
102
|
+
:"flash.#{controller_with_namespace}.#{action}.#{status}",
|
103
|
+
:"flash.#{controller_name}.#{action}.#{status}_html",
|
104
|
+
:"flash.#{controller_name}.#{action}.#{status}",
|
105
|
+
:"flash.actions.#{action}.#{status}",
|
106
|
+
"#{resource_name} was successfully #{past_tense}."
|
107
|
+
]
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Undercarriage
|
4
|
+
# :nodoc:
|
5
|
+
module Controllers
|
6
|
+
# :nodoc:
|
7
|
+
module Restful
|
8
|
+
##
|
9
|
+
# Location after
|
10
|
+
#
|
11
|
+
# Redirect locations after create, update or destroy
|
12
|
+
#
|
13
|
+
# Usage
|
14
|
+
# class ExamplesController < ApplicationController
|
15
|
+
# include Undercarriage::Controllers::Restful::LocationAfterConcern
|
16
|
+
# end
|
17
|
+
#
|
18
|
+
module LocationAfterConcern
|
19
|
+
extend ActiveSupport::Concern
|
20
|
+
|
21
|
+
protected
|
22
|
+
|
23
|
+
##
|
24
|
+
# Location after create
|
25
|
+
#
|
26
|
+
# The path of the created resource
|
27
|
+
#
|
28
|
+
def location_after_create
|
29
|
+
resource_id = @create_resource
|
30
|
+
|
31
|
+
resource_path(resource_id)
|
32
|
+
end
|
33
|
+
|
34
|
+
##
|
35
|
+
# Location after update
|
36
|
+
#
|
37
|
+
# The path of the updated resource
|
38
|
+
#
|
39
|
+
def location_after_update
|
40
|
+
resource_id = @update_resource
|
41
|
+
|
42
|
+
resource_path(resource_id)
|
43
|
+
end
|
44
|
+
|
45
|
+
##
|
46
|
+
# Location after destroy
|
47
|
+
#
|
48
|
+
# The path of the resources
|
49
|
+
#
|
50
|
+
def location_after_destroy
|
51
|
+
location_after_save
|
52
|
+
end
|
53
|
+
|
54
|
+
##
|
55
|
+
# Location after save
|
56
|
+
#
|
57
|
+
# The path of the resources
|
58
|
+
#
|
59
|
+
def location_after_save
|
60
|
+
resources_path
|
61
|
+
end
|
62
|
+
|
63
|
+
private
|
64
|
+
|
65
|
+
def resource_path(resource, options = {})
|
66
|
+
location_path = [resource_namespace, controller_name_singular].compact
|
67
|
+
|
68
|
+
send("#{location_path.join('_')}_path", resource, options)
|
69
|
+
end
|
70
|
+
|
71
|
+
def resources_path(options = {})
|
72
|
+
location_path = [resource_namespace, controller_name].compact
|
73
|
+
|
74
|
+
polymorphic_path(location_path, options)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Undercarriage
|
4
|
+
# :nodoc:
|
5
|
+
module Controllers
|
6
|
+
# :nodoc:
|
7
|
+
module Restful
|
8
|
+
##
|
9
|
+
# Namespace
|
10
|
+
#
|
11
|
+
# Usage
|
12
|
+
# class ExamplesController < ApplicationController
|
13
|
+
# include Undercarriage::Controllers::Restful::NamespaceConcern
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
module NamespaceConcern
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
##
|
22
|
+
# Resource namespace
|
23
|
+
#
|
24
|
+
# Best guess for namespace. Take `controller_path` and if there is more than one segment, assume the first is
|
25
|
+
# the namespace. When there is one segment, the namespace is `nil`
|
26
|
+
#
|
27
|
+
# Example
|
28
|
+
# # Override method that builds namespace
|
29
|
+
# def resource_namespace
|
30
|
+
# :admin
|
31
|
+
# end
|
32
|
+
#
|
33
|
+
def resource_namespace
|
34
|
+
segments = controller_path.split('/')
|
35
|
+
|
36
|
+
segments.length > 1 ? segments.first : nil
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Undercarriage
|
4
|
+
# :nodoc:
|
5
|
+
module Controllers
|
6
|
+
# :nodoc:
|
7
|
+
module Restful
|
8
|
+
##
|
9
|
+
# Permitted attributes
|
10
|
+
#
|
11
|
+
# Usage
|
12
|
+
# class ExamplesController < ApplicationController
|
13
|
+
# include Undercarriage::Controllers::Restful::PermittedAttributesConcern
|
14
|
+
# end
|
15
|
+
#
|
16
|
+
module PermittedAttributesConcern
|
17
|
+
extend ActiveSupport::Concern
|
18
|
+
|
19
|
+
protected
|
20
|
+
|
21
|
+
##
|
22
|
+
# Permitted attributes for `create` action
|
23
|
+
#
|
24
|
+
# Permitted attributes for the `create` action. If `create` and `update` do not need to be different, you can
|
25
|
+
# still override the `permitted_attributes` method which would be applied to both `create` and `update`.
|
26
|
+
#
|
27
|
+
# Example
|
28
|
+
# def permitted_create_attributes
|
29
|
+
# %i[thingy dilly whatsit]
|
30
|
+
# end
|
31
|
+
#
|
32
|
+
# # Use this method is `create` and `update` do not need different permitted attributes
|
33
|
+
# def permitted_attributes
|
34
|
+
# [
|
35
|
+
# :thingy, :dilly, :whatsit,
|
36
|
+
# { whosits_attributes: %i[id _destroy name] }
|
37
|
+
# ]
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
def permitted_create_attributes
|
41
|
+
permitted_attributes_fallback
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# Permitted attributes for `update` action
|
46
|
+
#
|
47
|
+
# Permitted attributes for the `update` action. If `create` and `update` do not need to be different, you can
|
48
|
+
# still override the `permitted_attributes` method which would be applied to both `create` and `update`.
|
49
|
+
#
|
50
|
+
# Example
|
51
|
+
# def permitted_update_attributes
|
52
|
+
# %i[thingy dilly whatsit]
|
53
|
+
# end
|
54
|
+
#
|
55
|
+
# # Use this method is `create` and `update` do not need different permitted attributes
|
56
|
+
# def permitted_attributes
|
57
|
+
# [
|
58
|
+
# :thingy, :dilly, :whatsit,
|
59
|
+
# { whosits_attributes: %i[id _destroy name] }
|
60
|
+
# ]
|
61
|
+
# end
|
62
|
+
#
|
63
|
+
def permitted_update_attributes
|
64
|
+
permitted_attributes_fallback
|
65
|
+
end
|
66
|
+
|
67
|
+
##
|
68
|
+
# New resource decider
|
69
|
+
#
|
70
|
+
# For the `new` action, resource params are `nil`. For the `create` action, resource params are the posted
|
71
|
+
# params from `create_resource_params` method
|
72
|
+
#
|
73
|
+
def resource_new_params
|
74
|
+
action_name == 'new' ? nil : create_resource_params
|
75
|
+
end
|
76
|
+
|
77
|
+
##
|
78
|
+
# Permitted params for `create` action
|
79
|
+
#
|
80
|
+
# Permitted params for the `create` action scoped to the resource.
|
81
|
+
#
|
82
|
+
def create_resource_params
|
83
|
+
permitted = permitted_create_attributes
|
84
|
+
|
85
|
+
params.require(resource_scope).permit(permitted)
|
86
|
+
end
|
87
|
+
|
88
|
+
##
|
89
|
+
# Permitted params for `update` action
|
90
|
+
#
|
91
|
+
# Permitted params for the `update` action scoped to the resource.
|
92
|
+
#
|
93
|
+
def update_resource_params
|
94
|
+
permitted = permitted_update_attributes
|
95
|
+
|
96
|
+
params.require(resource_scope).permit(permitted)
|
97
|
+
end
|
98
|
+
|
99
|
+
private
|
100
|
+
|
101
|
+
def permitted_attributes_fallback
|
102
|
+
with_method = self.class.instance_methods(false).include?(:permitted_attributes)
|
103
|
+
|
104
|
+
with_method ? permitted_attributes : []
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|