undercarriage 0.2.0 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (25) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +59 -5
  3. data/lib/undercarriage.rb +2 -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 +79 -1
  8. data/lib/undercarriage/controllers/restful/actions/create_concern.rb +16 -9
  9. data/lib/undercarriage/controllers/restful/actions/destroy_concern.rb +10 -2
  10. data/lib/undercarriage/controllers/restful/actions/edit_concern.rb +3 -4
  11. data/lib/undercarriage/controllers/restful/actions/index_concern.rb +4 -6
  12. data/lib/undercarriage/controllers/restful/actions/new_concern.rb +3 -4
  13. data/lib/undercarriage/controllers/restful/actions/show_concern.rb +4 -6
  14. data/lib/undercarriage/controllers/restful/actions/update_concern.rb +16 -9
  15. data/lib/undercarriage/controllers/restful/flash_concern.rb +112 -0
  16. data/lib/undercarriage/controllers/restful/location_after_concern.rb +32 -0
  17. data/lib/undercarriage/controllers/restful/namespace_concern.rb +10 -0
  18. data/lib/undercarriage/controllers/restful/permitted_attributes_concern.rb +65 -2
  19. data/lib/undercarriage/controllers/restful/utility_concern.rb +37 -0
  20. data/lib/undercarriage/controllers/restful_concern.rb +2 -0
  21. data/lib/undercarriage/models/published_concern.rb +120 -0
  22. data/lib/undercarriage/version.rb +4 -1
  23. metadata +6 -6
  24. data/lib/tasks/undercarriage_tasks.rake +0 -6
  25. data/lib/undercarriage/railtie.rb +0 -6
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: fccd3ba65ccfd908ef199e41930f736cd2f9022ca3113ee90186a96230a7cf8c
4
- data.tar.gz: a92a0518846b2d4996ba806f55e1a4f00df34ad6dcdd0501a3e4cd7292915bf5
3
+ metadata.gz: 2a9348f83d9d2e3924e13edfcb27bcea2a7602479195298e5f9e95ce646e8cb2
4
+ data.tar.gz: 2f6fe5126d7b6d4db2429118dc9343f30c76609766d313937cf26790cf5ad7e8
5
5
  SHA512:
6
- metadata.gz: 45773941e2a9fd2775e2e75c736083072e2193f90b49e92711638e2776d9d2058f18649050ce97ad663e2eb0d7b82d929d0db23de859fd7ff96912c886f228fd
7
- data.tar.gz: 3d5cf0b390504b5cf2d342d8e92ecce6738798466579af5562f145d0c11866a924950d955e506e699c4af4d8c25c30ca8d4d186391482ce39dd23f469b3bd5a6
6
+ metadata.gz: e10bb005e424d5e25984ccbb92d3bf44b53ce0d4d48d220ef3f71ddc7d884f6bd97a803732c69583ea10dc15704a3d7c5dfd8ebb2548a1ade20c013344d3b8e3
7
+ data.tar.gz: deb15ab41c1b0c027017c363028a4beabed9a0b92741efb418ec3d8592eb2289ac871f70c947140a7afa2e93c38175d84eae17a98c89466d902510a04501b0d6
data/README.md CHANGED
@@ -2,24 +2,28 @@
2
2
 
3
3
  **\*Undercarriage is currently under development. It is not ready for production use.\***
4
4
 
5
+ [![CircleCI](https://circleci.com/gh/dfreerksen/undercarriage.svg?style=shield)](https://circleci.com/gh/dfreerksen/undercarriage)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/d15980a534f8db936469/maintainability)](https://codeclimate.com/github/dfreerksen/undercarriage/maintainability)
7
+ [![Test Coverage](https://api.codeclimate.com/v1/badges/d15980a534f8db936469/test_coverage)](https://codeclimate.com/github/dfreerksen/undercarriage/test_coverage)
8
+
5
9
  Undercarriage is a set of concerns to add to your application to trim some of the fat from controllers and models.
6
10
 
7
11
  ## Requirements
8
12
 
9
13
  * Ruby >= 2.5
10
- * Rails >= 6.0.3
14
+ * Rails >= 6.0
11
15
 
12
16
  ## Installation
13
17
 
14
18
  Add to your application's Gemfile
15
19
 
16
- ```ruby
17
- gem 'undercarriage', '~> 0.2'
20
+ ```
21
+ gem 'undercarriage', '~> 0.5'
18
22
  ```
19
23
 
20
24
  Run the bundle command
21
25
 
22
- ```bash
26
+ ```
23
27
  $ bundle install
24
28
  ```
25
29
 
@@ -31,9 +35,59 @@ TODO
31
35
 
32
36
  * [ ] Allow a way to set locale instead of relying on browser preferred language in `Undercarriage::Controllers::LocaleConcern`
33
37
 
38
+ ## Testing
39
+
40
+ Run tests with one of the following
41
+
42
+ ```
43
+ $ bundle exec rspec
44
+ $ bundle exec rspec spec
45
+ ```
46
+
47
+ ### Appraisal
48
+
49
+ Undercarriage uses [Appraisal](https://github.com/thoughtbot/appraisal) to ensure various dependency versions work as expected
50
+
51
+ When dependencies change, run
52
+
53
+ ```
54
+ $ bundle exec appraisal install
55
+ ```
56
+
57
+ To run tests with Appraisal, run
58
+
59
+ ```
60
+ $ bundle exec appraisal rspec
61
+ ```
62
+
34
63
  ## Code Analysis
35
64
 
36
- TODO
65
+ Various tools are used to ensure code is linted and formatted correctly.
66
+
67
+ ### RuboCop
68
+
69
+ [RuboCop](https://github.com/bbatsov/rubocop) is a Ruby static code analyzer.
70
+
71
+ ```
72
+ $ rubocop
73
+ ```
74
+
75
+ ## Documentation
76
+
77
+ [Yard](https://github.com/lsegal/yard) is used to generate documentation. [Online documentation is available](http://www.rubydoc.info/github/dfreerksen/undercarriage/master)
78
+
79
+ Build the documentation with one of the following
80
+
81
+ ```
82
+ $ yard
83
+ $ yard doc
84
+ ```
85
+
86
+ Build the documentation and list all undocumented objects
87
+
88
+ ```
89
+ $ yard stats --list-undoc
90
+ ```
37
91
 
38
92
  ## License
39
93
 
data/lib/undercarriage.rb CHANGED
@@ -12,12 +12,12 @@ require 'undercarriage/controllers/restful/actions/create_concern'
12
12
  require 'undercarriage/controllers/restful/actions/edit_concern'
13
13
  require 'undercarriage/controllers/restful/actions/update_concern'
14
14
  require 'undercarriage/controllers/restful/actions/destroy_concern'
15
+ require 'undercarriage/controllers/restful/flash_concern'
15
16
  require 'undercarriage/controllers/restful/location_after_concern'
16
17
  require 'undercarriage/controllers/restful/namespace_concern'
17
18
  require 'undercarriage/controllers/restful/permitted_attributes_concern'
18
19
  require 'undercarriage/controllers/restful/utility_concern'
19
-
20
- require 'undercarriage/railtie'
20
+ require 'undercarriage/models/published_concern'
21
21
 
22
22
  ##
23
23
  # Undercarriage
@@ -25,5 +25,4 @@ require 'undercarriage/railtie'
25
25
  # Undercarriage is a set of concerns to add to your application to trim some of the fat from controllers and models.
26
26
  #
27
27
  module Undercarriage
28
- # Your code goes here...
29
28
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
5
6
  ##
6
7
  # Action helpers
@@ -209,22 +210,39 @@ module Undercarriage
209
210
 
210
211
  protected
211
212
 
213
+ ##
214
+ # Action symbol
215
+ #
216
+ # Take `action_name` (string) and turn it into a symbol
217
+ #
212
218
  def action
213
219
  action_name.to_sym
214
220
  end
215
221
 
222
+ ##
223
+ # Collection actions
224
+ #
216
225
  def collection_actions
217
226
  %i[index]
218
227
  end
219
228
 
229
+ ##
230
+ # Member actions
231
+ #
220
232
  def member_actions
221
233
  %i[edit show update]
222
234
  end
223
235
 
236
+ ##
237
+ # Create actions
238
+ #
224
239
  def create_actions
225
240
  %i[create new]
226
241
  end
227
242
 
243
+ ##
244
+ # Update actions
245
+ #
228
246
  def update_actions
229
247
  %i[edit update]
230
248
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
5
6
  ##
6
7
  # Kaminari pagination
@@ -61,10 +62,20 @@ module Undercarriage
61
62
 
62
63
  protected
63
64
 
65
+ ##
66
+ # Items per page key
67
+ #
68
+ # Query param to be used to identify count to be returned
69
+ #
64
70
  def per_page_key
65
71
  :per
66
72
  end
67
73
 
74
+ ##
75
+ # Page numberkey
76
+ #
77
+ # Query param to be used to identify page offset
78
+ #
68
79
  def page_num_key
69
80
  Kaminari.config.param_name
70
81
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
5
6
  ##
6
7
  # Identify locale for translations
@@ -65,6 +66,11 @@ module Undercarriage
65
66
 
66
67
  protected
67
68
 
69
+ ##
70
+ # Set I18n locale
71
+ #
72
+ # Set I18n locale for the request
73
+ #
68
74
  def identify_locale(&action)
69
75
  I18n.with_locale(first_available_locale, &action)
70
76
  end
@@ -75,7 +81,7 @@ module Undercarriage
75
81
  preferred_locales = (accepted_languages_header << I18n.default_locale.to_s).uniq
76
82
  available_locales = I18n.available_locales.map(&:to_s)
77
83
 
78
- preferred_locales.intersection(available_locales).first
84
+ (preferred_locales & available_locales).first
79
85
  end
80
86
 
81
87
  def accepted_languages_header
@@ -1,15 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Base restful action
9
12
  #
10
13
  # Usage
11
14
  # class ExamplesController < ApplicationController
12
- # include Undercarriage::Controllers::RestfulConcern
15
+ # include Undercarriage::Controllers::Restful::Actions::BaseConcern
13
16
  # end
14
17
  #
15
18
  module BaseConcern
@@ -17,10 +20,42 @@ module Undercarriage
17
20
 
18
21
  protected
19
22
 
23
+ ##
24
+ # New content action
25
+ #
26
+ # Decide what content to load based on action name
27
+ #
20
28
  def resource_new_content
21
29
  action_name == 'new' ? new_resource_content : create_resource_content
22
30
  end
23
31
 
32
+ ##
33
+ # Resource action
34
+ #
35
+ # Used for `show`, `edit`, `update` and `destroy` actions unless overwritten
36
+ #
37
+ # Usage
38
+ # class ExamplesController < ApplicationController
39
+ # include Undercarriage::Controllers::RestfulConcern
40
+ #
41
+ # ##
42
+ # # This method is only needed if you want to override the query entirely. Otherwise, it is not needed.
43
+ # # Database resources can be accessed as `@example`
44
+ # #
45
+ # # def resource_content
46
+ # # ...
47
+ # # end
48
+ #
49
+ # ##
50
+ # # To add authorization through something like Pundit, the following could be used
51
+ # #
52
+ # # def resource_content
53
+ # # super
54
+ # #
55
+ # # authorize @example
56
+ # # end
57
+ # end
58
+ #
24
59
  def resource_content
25
60
  resource_id = params.fetch(:id)
26
61
  resource_query = model_class.find(resource_id)
@@ -28,12 +63,55 @@ module Undercarriage
28
63
  instance_variable_set("@#{instance_name}", resource_query)
29
64
  end
30
65
 
66
+ ##
67
+ # Build nested association before action
68
+ #
69
+ # Called first thing from `new`, `create`, `edit` and `update` actions. Meant to build a basic resource before
70
+ # the action is evaluated
71
+ #
72
+ # Usage
73
+ # nested_resource_pre_build
74
+ # @example.build_image if @example.image.blank?
75
+ # end
76
+ #
31
77
  def nested_resource_pre_build; end
32
78
 
79
+ ##
80
+ # Build nested association for action
81
+ #
82
+ # Similar to `nested_resource_pre_build` but called in different places. For the `new` and `edit` actions, it
83
+ # is called right after `nested_resource_pre_build`. For the `create` and `update` actions, it is only called
84
+ # after validation has failed and before the view is rendered.
85
+ #
86
+ # Usage
87
+ # nested_resource_build
88
+ # @example.build_image if @example.image.blank?
89
+ # end
90
+ #
33
91
  def nested_resource_build; end
34
92
 
93
+ ##
94
+ # After create callback
95
+ #
96
+ # Callback after `create` action has created the record.
97
+ #
98
+ # Usage
99
+ # after_create_action
100
+ # ExampleJob.perform_later(@example.id)
101
+ # end
102
+ #
35
103
  def after_create_action; end
36
104
 
105
+ ##
106
+ # After update callback
107
+ #
108
+ # Callback after `update` action has updated the record.
109
+ #
110
+ # Usage
111
+ # after_update_action
112
+ # ExampleJob.perform_later(@example.id)
113
+ # end
114
+ #
37
115
  def after_update_action; end
38
116
  end
39
117
  end
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Create restful action
@@ -38,17 +41,21 @@ module Undercarriage
38
41
  def create
39
42
  nested_resource_pre_build
40
43
 
41
- if @create_resource.save
42
- after_create_action
44
+ respond_to do |format|
45
+ if @create_resource.save
46
+ after_create_action
43
47
 
44
- respond_with(@create_resource) do |format|
45
- format.html { redirect_to location_after_create }
46
- end
47
- else
48
- nested_resource_build
48
+ format.html do
49
+ flash[flash_status_type] = flash_created_message
50
+
51
+ redirect_to location_after_create
52
+ end
53
+ format.json { render :show, status: :created, location: location_after_create }
54
+ else
55
+ nested_resource_build
49
56
 
50
- respond_with(@create_resource) do |format|
51
- format.html { render action: :new }
57
+ format.html { render :new, status: :unprocessable_entity }
58
+ format.json { render json: @create_resource.errors, status: :unprocessable_entity }
52
59
  end
53
60
  end
54
61
  end
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Destroy restful action
@@ -38,8 +41,13 @@ module Undercarriage
38
41
  def destroy
39
42
  @destroy_resource.destroy
40
43
 
41
- respond_with(@destroy_resource) do |format|
42
- format.html { redirect_to location_after_destroy }
44
+ respond_to do |format|
45
+ format.html do
46
+ flash[flash_status_type] = flash_destroyed_message
47
+
48
+ redirect_to location_after_destroy
49
+ end
50
+ format.json { head :no_content }
43
51
  end
44
52
  end
45
53
 
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Edit restful action
@@ -38,10 +41,6 @@ module Undercarriage
38
41
  def edit
39
42
  nested_resource_pre_build
40
43
  nested_resource_build
41
-
42
- respond_with(@edit_resource) do |format|
43
- format.html { render layout: !request.xhr? }
44
- end
45
44
  end
46
45
 
47
46
  protected
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Index restful action
@@ -35,12 +38,7 @@ module Undercarriage
35
38
  # # end
36
39
  # end
37
40
  #
38
- def index
39
- respond_with(@index_resources) do |format|
40
- format.html { render layout: !request.xhr? }
41
- format.json { render layout: false }
42
- end
43
- end
41
+ def index; end
44
42
 
45
43
  protected
46
44
 
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # New restful action
@@ -38,10 +41,6 @@ module Undercarriage
38
41
  def new
39
42
  nested_resource_pre_build
40
43
  nested_resource_build
41
-
42
- respond_with(@new_resource) do |format|
43
- format.html { render layout: !request.xhr? }
44
- end
45
44
  end
46
45
 
47
46
  protected
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Show restful action
@@ -35,12 +38,7 @@ module Undercarriage
35
38
  # # end
36
39
  # end
37
40
  #
38
- def show
39
- respond_with(@show_resource) do |format|
40
- format.html { render layout: !request.xhr? }
41
- format.json { render layout: false }
42
- end
43
- end
41
+ def show; end
44
42
 
45
43
  protected
46
44
 
@@ -1,8 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ # :nodoc:
6
9
  module Actions
7
10
  ##
8
11
  # Update restful action
@@ -38,17 +41,21 @@ module Undercarriage
38
41
  def update
39
42
  nested_resource_pre_build
40
43
 
41
- if @update_resource.update(update_resource_params)
42
- after_update_action
44
+ respond_to do |format|
45
+ if @update_resource.update(update_resource_params)
46
+ after_update_action
43
47
 
44
- respond_with(@update_resource) do |format|
45
- format.html { redirect_to location_after_update }
46
- end
47
- else
48
- nested_resource_build
48
+ format.html do
49
+ flash[flash_status_type] = flash_updated_message
50
+
51
+ redirect_to location_after_update
52
+ end
53
+ format.json { render :show, status: :ok, location: location_after_update }
54
+ else
55
+ nested_resource_build
49
56
 
50
- respond_with(@update_resource) do |format|
51
- format.html { render action: :edit }
57
+ format.html { render :edit }
58
+ format.json { render json: @post.errors, status: :unprocessable_entity }
52
59
  end
53
60
  end
54
61
  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
@@ -1,29 +1,61 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
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
+ #
6
18
  module LocationAfterConcern
7
19
  extend ActiveSupport::Concern
8
20
 
9
21
  protected
10
22
 
23
+ ##
24
+ # Location after create
25
+ #
26
+ # The path of the created resource
27
+ #
11
28
  def location_after_create
12
29
  resource_id = @create_resource
13
30
 
14
31
  resource_path(resource_id)
15
32
  end
16
33
 
34
+ ##
35
+ # Location after update
36
+ #
37
+ # The path of the updated resource
38
+ #
17
39
  def location_after_update
18
40
  resource_id = @update_resource
19
41
 
20
42
  resource_path(resource_id)
21
43
  end
22
44
 
45
+ ##
46
+ # Location after destroy
47
+ #
48
+ # The path of the resources
49
+ #
23
50
  def location_after_destroy
24
51
  location_after_save
25
52
  end
26
53
 
54
+ ##
55
+ # Location after save
56
+ #
57
+ # The path of the resources
58
+ #
27
59
  def location_after_save
28
60
  resources_path
29
61
  end
@@ -1,8 +1,18 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ ##
9
+ # Namespace
10
+ #
11
+ # Usage
12
+ # class ExamplesController < ApplicationController
13
+ # include Undercarriage::Controllers::Restful::NamespaceConcern
14
+ # end
15
+ #
6
16
  module NamespaceConcern
7
17
  extend ActiveSupport::Concern
8
18
 
@@ -1,31 +1,95 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ ##
9
+ # Permitted attributes
10
+ #
11
+ # Usage
12
+ # class ExamplesController < ApplicationController
13
+ # include Undercarriage::Controllers::Restful::PermittedAttributesConcern
14
+ # end
15
+ #
6
16
  module PermittedAttributesConcern
7
17
  extend ActiveSupport::Concern
8
18
 
9
19
  protected
10
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
+ #
11
40
  def permitted_create_attributes
12
41
  permitted_attributes_fallback
13
42
  end
14
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
+ #
15
63
  def permitted_update_attributes
16
64
  permitted_attributes_fallback
17
65
  end
18
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
+ #
19
73
  def resource_new_params
20
74
  action_name == 'new' ? nil : create_resource_params
21
75
  end
22
76
 
77
+ ##
78
+ # Permitted params for `create` action
79
+ #
80
+ # Permitted params for the `create` action scoped to the resource.
81
+ #
23
82
  def create_resource_params
24
83
  permitted = permitted_create_attributes
25
84
 
26
85
  params.require(resource_scope).permit(permitted)
27
86
  end
28
87
 
88
+ ##
89
+ # Permitted params for `update` action
90
+ #
91
+ # Permitted params for the `update` action scoped to the resource.
92
+ #
29
93
  def update_resource_params
30
94
  permitted = permitted_update_attributes
31
95
 
@@ -35,8 +99,7 @@ module Undercarriage
35
99
  private
36
100
 
37
101
  def permitted_attributes_fallback
38
- with_method = self.class.instance_methods(false)
39
- .include?(:permitted_attributes)
102
+ with_method = self.class.instance_methods(false).include?(:permitted_attributes)
40
103
 
41
104
  with_method ? permitted_attributes : []
42
105
  end
@@ -1,33 +1,70 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
6
+ # :nodoc:
5
7
  module Restful
8
+ ##
9
+ # Utility
10
+ #
11
+ # Utility helper methods
12
+ #
13
+ # Usage
14
+ # class ExamplesController < ApplicationController
15
+ # include Undercarriage::Controllers::Restful::UtilityConcern
16
+ # end
17
+ #
6
18
  module UtilityConcern
7
19
  extend ActiveSupport::Concern
8
20
 
9
21
  protected
10
22
 
23
+ ##
24
+ # Singular controller name
25
+ #
11
26
  def controller_name_singular
12
27
  controller_name.to_s.singularize
13
28
  end
14
29
 
30
+ ##
31
+ # Singular human name
32
+ #
33
+ def controller_name_singular_human
34
+ controller_name_singular.humanize
35
+ end
36
+
37
+ ##
38
+ # Model name
39
+ #
15
40
  def model_name
16
41
  controller_name_singular
17
42
  end
18
43
 
44
+ ##
45
+ # Model class
46
+ #
19
47
  def model_class
20
48
  model_name.classify.constantize
21
49
  end
22
50
 
51
+ ##
52
+ # Instances name
53
+ #
23
54
  def instances_name
24
55
  controller_name.to_s
25
56
  end
26
57
 
58
+ ##
59
+ # Instance name
60
+ #
27
61
  def instance_name
28
62
  model_name
29
63
  end
30
64
 
65
+ ##
66
+ # Resource scope
67
+ #
31
68
  def resource_scope
32
69
  model_name.to_sym
33
70
  end
@@ -1,6 +1,7 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
+ # :nodoc:
4
5
  module Controllers
5
6
  ##
6
7
  # Restful actions
@@ -14,6 +15,7 @@ module Undercarriage
14
15
  extend ActiveSupport::Concern
15
16
 
16
17
  included do
18
+ include Undercarriage::Controllers::Restful::FlashConcern
17
19
  include Undercarriage::Controllers::Restful::LocationAfterConcern
18
20
  include Undercarriage::Controllers::Restful::NamespaceConcern
19
21
  include Undercarriage::Controllers::Restful::PermittedAttributesConcern
@@ -0,0 +1,120 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Undercarriage
4
+ # :nodoc:
5
+ module Models
6
+ ##
7
+ # Published
8
+ #
9
+ # Based on the presence of a datetime in the `published_at` column (configurable) in the database. If there is a
10
+ # datetime in the column, it is considered published. You need to do your own validation to ensure the value is a
11
+ # datetime value
12
+ #
13
+ # Usage
14
+ # # Model
15
+ # class Example < ApplicationRecord
16
+ # include Undercarriage::Models::PublishedConcern
17
+ #
18
+ # ##
19
+ # # The name of the column is expected to be `published_at`. If that is not the case for you, uncomment the
20
+ # # following to change the column name
21
+ # #
22
+ # # self.published_column = :ready_at
23
+ #
24
+ # ##
25
+ # # The following are useful helpers for the model. They are not part of the concern
26
+ # #
27
+ # scope :available, -> { published.where("#{published_column} <= ?", Time.current) }
28
+ #
29
+ # def available?
30
+ # published? && self[published_column] <= Time.current
31
+ # end
32
+ #
33
+ # scope :scheduled, -> { published.where("#{published_column} > ?", , Time.current) }
34
+ #
35
+ # def scheduled?
36
+ # published? && self[published_column] > Time.current
37
+ # end
38
+ # end
39
+ #
40
+ # # Controller
41
+ # class PagesController < AdminController
42
+ # def index
43
+ # @examples = Example.published
44
+ # end
45
+ # end
46
+ #
47
+ # # View
48
+ # <% @examples.each do |example| %>
49
+ # Published?: <%= example.published? %>
50
+ # <% end %>
51
+ #
52
+ module PublishedConcern
53
+ extend ActiveSupport::Concern
54
+
55
+ included do
56
+ class_attribute :published_column
57
+ self.published_column = :published_at
58
+
59
+ ##
60
+ # Published scope
61
+ #
62
+ # Retrieve only published resources
63
+ #
64
+ # Usage
65
+ # class PagesController < AdminController
66
+ # def index
67
+ # @examples = Example.published
68
+ # end
69
+ # end
70
+ #
71
+ scope :published, -> { where.not(published_column => nil) }
72
+
73
+ ##
74
+ # Unpublished scope
75
+ #
76
+ # Retrieve only unpublished resources
77
+ #
78
+ # Usage
79
+ # class PagesController < AdminController
80
+ # def index
81
+ # @examples = Example.unpublished
82
+ # end
83
+ # end
84
+ #
85
+ scope :unpublished, -> { where(published_column => nil) }
86
+ end
87
+
88
+ ##
89
+ # Published check
90
+ #
91
+ # Check if an item is published based on the presence of a value in the published column. This does not take into
92
+ # account whether the item is not currently available (scheduled). See module documentation for more information
93
+ #
94
+ # Usage
95
+ # @example.published? => true
96
+ # @example.published? => false
97
+ #
98
+ # @return [Boolean] if resource is published
99
+ #
100
+ def published?
101
+ self[self.class.published_column].present?
102
+ end
103
+
104
+ ##
105
+ # Unpublished check
106
+ #
107
+ # Check if an item is unpublished based on the lack of presence of a value in the published column
108
+ #
109
+ # Usage
110
+ # @example.unpublished? => true
111
+ # @example.unpublished? => false
112
+ #
113
+ # @return [Boolean] if resource is unpublished
114
+ #
115
+ def unpublished?
116
+ !published?
117
+ end
118
+ end
119
+ end
120
+ end
@@ -1,5 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Undercarriage
4
- VERSION = '0.2.0'
4
+ ##
5
+ # Undercarriage version
6
+ #
7
+ VERSION = '0.5.0'
5
8
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undercarriage
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.5.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - David Freerksen
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-03-05 00:00:00.000000000 Z
11
+ date: 2021-03-16 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - ">="
18
18
  - !ruby/object:Gem::Version
19
- version: 6.0.3
19
+ version: '6.0'
20
20
  type: :runtime
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
- version: 6.0.3
26
+ version: '6.0'
27
27
  description: Undercarriage is a set of concerns to add to your application to trim
28
28
  some of the fat from controllers and models.
29
29
  email:
@@ -35,7 +35,6 @@ files:
35
35
  - MIT-LICENSE
36
36
  - README.md
37
37
  - Rakefile
38
- - lib/tasks/undercarriage_tasks.rake
39
38
  - lib/undercarriage.rb
40
39
  - lib/undercarriage/controllers/action_concern.rb
41
40
  - lib/undercarriage/controllers/kaminari_concern.rb
@@ -48,12 +47,13 @@ files:
48
47
  - lib/undercarriage/controllers/restful/actions/new_concern.rb
49
48
  - lib/undercarriage/controllers/restful/actions/show_concern.rb
50
49
  - lib/undercarriage/controllers/restful/actions/update_concern.rb
50
+ - lib/undercarriage/controllers/restful/flash_concern.rb
51
51
  - lib/undercarriage/controllers/restful/location_after_concern.rb
52
52
  - lib/undercarriage/controllers/restful/namespace_concern.rb
53
53
  - lib/undercarriage/controllers/restful/permitted_attributes_concern.rb
54
54
  - lib/undercarriage/controllers/restful/utility_concern.rb
55
55
  - lib/undercarriage/controllers/restful_concern.rb
56
- - lib/undercarriage/railtie.rb
56
+ - lib/undercarriage/models/published_concern.rb
57
57
  - lib/undercarriage/version.rb
58
58
  homepage: https://github.com/dfreerksen/undercarriage
59
59
  licenses:
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- # desc "Explaining what the task does"
4
- # task :undercarriage do
5
- # # Task goes here
6
- # end
@@ -1,6 +0,0 @@
1
- # frozen_string_literal: true
2
-
3
- module Undercarriage
4
- class Railtie < ::Rails::Railtie
5
- end
6
- end