undercarriage 0.1.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|