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.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +42 -4
  3. data/lib/undercarriage.rb +15 -3
  4. data/lib/undercarriage/controllers/action_concern.rb +18 -0
  5. data/lib/undercarriage/controllers/kaminari_concern.rb +11 -0
  6. data/lib/undercarriage/controllers/locale_concern.rb +7 -1
  7. data/lib/undercarriage/controllers/restful/actions/base_concern.rb +120 -0
  8. data/lib/undercarriage/controllers/restful/actions/create_concern.rb +107 -0
  9. data/lib/undercarriage/controllers/restful/actions/destroy_concern.rb +97 -0
  10. data/lib/undercarriage/controllers/restful/actions/edit_concern.rb +94 -0
  11. data/lib/undercarriage/controllers/restful/actions/index_concern.rb +85 -0
  12. data/lib/undercarriage/controllers/restful/actions/new_concern.rb +96 -0
  13. data/lib/undercarriage/controllers/restful/actions/show_concern.rb +91 -0
  14. data/lib/undercarriage/controllers/restful/actions/update_concern.rb +105 -0
  15. data/lib/undercarriage/controllers/restful/flash_concern.rb +112 -0
  16. data/lib/undercarriage/controllers/restful/location_after_concern.rb +79 -0
  17. data/lib/undercarriage/controllers/restful/namespace_concern.rb +41 -0
  18. data/lib/undercarriage/controllers/restful/permitted_attributes_concern.rb +109 -0
  19. data/lib/undercarriage/controllers/restful/utility_concern.rb +74 -0
  20. data/lib/undercarriage/controllers/restful_concern.rb +34 -0
  21. data/lib/undercarriage/models/published_concern.rb +120 -0
  22. data/lib/undercarriage/version.rb +4 -1
  23. metadata +17 -4
  24. data/lib/tasks/undercarriage_tasks.rake +0 -6
  25. 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