resting_pug 0.1.0

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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: f7d99d102f6977a7fce1ac74ae7b1489d95273d7
4
+ data.tar.gz: ba714667deb6cfc2bc48a39085bf1f18a2954845
5
+ SHA512:
6
+ metadata.gz: 062416d0fe7ee490e6ddd9cfb7b7b3fe8cd94d738a5579e0d8801794dd940012a9c3ccf456b223e42a2d41cc4c5f82d0d61857c7d62663378748fff484e9f487
7
+ data.tar.gz: ebb18d667055f77993629cb8320920e410fed4b221dde060ab0709a267ceb11d46701ad1e168bf70708ac88e2c478a69e06b127ef6dab818d71520dc9007356b
@@ -0,0 +1,20 @@
1
+ Copyright 2017 Slava Korolev
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,54 @@
1
+
2
+ <h1 align="center">
3
+ <br>
4
+ <a href="https://korolvs.github.com/resting_pug"><img src="https://korolvs.github.com/resting_pug/resting_pug.png" alt="Markdownify" width="80%"></a>
5
+ <br>
6
+ </h1>
7
+
8
+ # Basic Overview
9
+ Resting Pug allows you to create a JSON API with just adding one line to your controller and fully customize it with overriding small and simple helper methods.
10
+
11
+ ## Usage
12
+ Include ```RestingPug::Base``` into controller to add CRUD actions to it:
13
+
14
+ ```ruby
15
+ class BooksController < ApplicationController
16
+ include RestingPug::Base
17
+ end
18
+ ```
19
+
20
+ You can add CRUD actions to all controllers by including this module into ```ApplicationController```:
21
+
22
+ ```ruby
23
+ class ApplicationController < ActionController::Base
24
+ include RestingPug::Base
25
+ end
26
+ ```
27
+
28
+ Don't forget to add a route to ```config/routes.rb```
29
+
30
+ ```ruby
31
+ Rails.application.routes.draw do
32
+ resources :books
33
+ end
34
+ ```
35
+
36
+ ## Installation
37
+ Add this line to your application's Gemfile:
38
+
39
+ ```ruby
40
+ gem 'resting_pug'
41
+ ```
42
+
43
+ And then execute:
44
+ ```bash
45
+ $ bundle
46
+ ```
47
+
48
+ ## Contributing
49
+ Contribution directions go here.
50
+
51
+ ## License
52
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
53
+
54
+ Logo is [Designed by Freepik](https://www.freepik.com/free-vector/happy-pug-resting-on-the-sofa_1357299.htm)
@@ -0,0 +1,23 @@
1
+ begin
2
+ require 'bundler/setup'
3
+ rescue LoadError
4
+ puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
5
+ end
6
+
7
+ require 'rdoc/task'
8
+
9
+ RDoc::Task.new(:rdoc) do |rdoc|
10
+ rdoc.rdoc_dir = 'rdoc'
11
+ rdoc.title = 'RestingPug'
12
+ rdoc.options << '--line-numbers'
13
+ rdoc.rdoc_files.include('README.md')
14
+ rdoc.rdoc_files.include('lib/**/*.rb')
15
+ end
16
+
17
+
18
+
19
+
20
+
21
+
22
+ require 'bundler/gem_tasks'
23
+
@@ -0,0 +1,4 @@
1
+ require "resting_pug/base"
2
+
3
+ module RestingPug
4
+ end
@@ -0,0 +1,168 @@
1
+ module RestingPug
2
+ # Describes basic CRUD actions
3
+ # @see https://en.wikipedia.org/wiki/Create,_read,_update_and_delete
4
+ # @used_in {Base.included}
5
+ module Actions
6
+ # Creates a subject with attributes from params and returns it.
7
+ # @example
8
+ # Request:
9
+ # POST http://your.awesome/api/books
10
+ # {
11
+ # "name": "11/22/63",
12
+ # "author": "Stephen King"
13
+ # }
14
+ #
15
+ # Response:
16
+ # 200 OK
17
+ # {
18
+ # "book": {
19
+ # "id": 1,
20
+ # "name": "11/22/63",
21
+ # "author": "Stephen King"
22
+ # }
23
+ # }
24
+ # @note You can sustomize creating action:
25
+ # - override {Subject#subject_model} to set what model will be created
26
+ # - override {Chains#create_chain} to add or remove methods which will be called while creating a subject
27
+ # - override {Params#permitted_fields_for_create} to set which params can be set in a new subject
28
+ # - override {Params#permitted_fields_for_show} to set which params will be shown in response
29
+ # - override {Render#decide_what_to_render} to set how it will be decided what to render in response
30
+ # - override {Render#render_subject} to set how subject will be rendered
31
+ # - override {Render#render_errors} to set how errors will be rendered
32
+ # @use {#run_chain}
33
+ # @use {Chains#create_chain}
34
+ def create
35
+ run_chain(create_chain)
36
+ end
37
+
38
+ # Updates a subject by id with attributes from params and returns it.
39
+ # @example
40
+ # Request:
41
+ # PATCH http://your.awesome/api/books/1
42
+ # {
43
+ # "name": "The Green Mile",
44
+ # }
45
+ #
46
+ # Response:
47
+ # 200 OK
48
+ # {
49
+ # "book": {
50
+ # "id": 1,
51
+ # "name": "The Green Mile",
52
+ # "author": "Stephen King"
53
+ # }
54
+ # }
55
+ # @note You can sustomize creating action:
56
+ # - override {Subject#subject_model} to set what model will be updated
57
+ # - override {Chains#update_chain} to add or remove methods which will be called while updating a subject
58
+ # - override {Params#permitted_fields_for_update} to set which params can be updated
59
+ # - override {Params#permitted_fields_for_show} to set which params will be shown in response
60
+ # - override {Render#decide_what_to_render} to set how it will be decided what to render in response
61
+ # - override {Render#render_subject} to set how subject will be rendered
62
+ # - override {Render#render_errors} to set how errors will be rendered
63
+ # - override {Render#render_not_found} to set what to render when subject with ID from params is not found
64
+ # @use {#run_chain}
65
+ # @use {Chains#update_chain}
66
+ def update
67
+ run_chain(update_chain)
68
+ end
69
+
70
+ # Destroys a subject by id
71
+ # @example
72
+ # Request:
73
+ # DELETE http://your.awesome/api/books/1
74
+ #
75
+ # Response:
76
+ # 204 No Content
77
+ # @note You can sustomize creating action:
78
+ # - override {Subject#subject_model} to set what model will be deleted
79
+ # - override {Chains#destroy_chain} to add or remove methods which will be called while deleting a subject
80
+ # - override {Subject#destroy_subject} to set how it will be destroyed
81
+ # - override {Render#render_nothing} to set what to render when subject is destroyed
82
+ # - override {Render#render_errors} to set how errors will be rendered
83
+ # - override {Render#render_not_found} to set what to render when subject with ID from params is not found
84
+ # @use {#run_chain}
85
+ # @use {Chains#destroy_chain}
86
+ def destroy
87
+ run_chain(destroy_chain)
88
+ end
89
+
90
+ # Shows a subject by id
91
+ # @example
92
+ # Request:
93
+ # GET http://your.awesome/api/books/1
94
+ #
95
+ # Response:
96
+ # 200 OK
97
+ # {
98
+ # "book": {
99
+ # "id": 1,
100
+ # "name": "The Green Mile",
101
+ # "author": "Stephen King"
102
+ # }
103
+ # }
104
+ # @note You can sustomize creating action:
105
+ # - override {Subject#subject_model} to set what model will be shown
106
+ # - override {Chains#show_chain} to add or remove methods which will be called while updating a subject
107
+ # - override {Params#permitted_fields_for_show} to set which params will be shown in response
108
+ # - override {Render#render_subject} to set how subject will be rendered
109
+ # - override {Render#render_not_found} to set what to render when subject with ID from params is not found
110
+ # @use {#run_chain}
111
+ # @use {Chains#show_chain}
112
+ def show
113
+ run_chain(show_chain)
114
+ end
115
+
116
+ # Shows a list of subjects.
117
+ # You can filter subjects by attributes using *filter* param.
118
+ # You can sort subjects using *sort* param. It is a string of comma-separated attributes with minus before attributes you wants to sort descending.
119
+ # You can paginate subjcts with *page* and *per_page* params.
120
+ # @example
121
+ # Request:
122
+ # GET http://your.awesome/api/books
123
+ # GET http://your.awesome/api/books?filter[author]="King"
124
+ # GET http://your.awesome/api/books?filter[author][]="King"&filter[author][]="Kesey"
125
+ # GET http://your.awesome/api/books?sort=-id,name,-author
126
+ # GET http://your.awesome/api/books?page=3&per_page=10
127
+ # GET http://your.awesome/api/books?filter[author]="King"&sort=-id?page=3&per_page=10
128
+ #
129
+ # Response:
130
+ # 200 OK
131
+ # {
132
+ # "books": [{
133
+ # "id": 2,
134
+ # "name": "The Green Mile",
135
+ # "author": "Stephen King"
136
+ # }, {
137
+ # "id": 1,
138
+ # "name": "11/22/63",
139
+ # "author": "Stephen King"
140
+ # }]
141
+ # }
142
+ # @note You can sustomize creating action:
143
+ # - override {Subject#subject_model} to set what model will be shown
144
+ # - override {Chains#index_chain} to add or remove methods which will be called while updating a subject
145
+ # - override {Params#permitted_fields_for_show} to set which params will be shown in response
146
+ # - override {Params#permitted_fields_for_filter} to set which params can be used for filtering
147
+ # - override {Params#permitted_fields_for_sort} to set which params can be used for sorting
148
+ # - override {Params#default_sort_params} to set default sort params
149
+ # - override {Params#per_page_default} to set default per_page param
150
+ # - override {Params#per_page_range} to set minimum and maximum possible per_page value
151
+ # - override {Render#render_subjects} to set how subjects will be rendered
152
+ # @use {#run_chain}
153
+ # @use {Chains#index_chain}
154
+ def index
155
+ run_chain(index_chain)
156
+ end
157
+
158
+ protected
159
+
160
+ # Executes each method in a chain one by one
161
+ # @param chain [Array] array of methods to execute
162
+ def run_chain(chain)
163
+ chain.each do |action|
164
+ self.send(action)
165
+ end
166
+ end
167
+ end
168
+ end
@@ -0,0 +1,28 @@
1
+ require_relative './actions'
2
+ require_relative './chains'
3
+ require_relative './render'
4
+ require_relative './subject'
5
+ require_relative './params'
6
+ require_relative './modificators'
7
+ require 'will_paginate/active_record'
8
+
9
+ module RestingPug
10
+ # Main module
11
+ module Base
12
+ # Includes all methods in controller
13
+ # @param base [ActionController::Base]
14
+ def self.included(base)
15
+ base.class_eval do
16
+ include RestingPug::Actions
17
+ include RestingPug::Chains
18
+ include RestingPug::Render
19
+ include RestingPug::Subject
20
+ include RestingPug::Params
21
+ include RestingPug::Modificators
22
+
23
+ rescue_from ActionController::ParameterMissing, with: :render_param_missing
24
+ rescue_from ActiveRecord::RecordNotFound, with: :render_not_found
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,56 @@
1
+ module RestingPug
2
+ # Describes chains of methods for actions. Each chain is an array of methods running one by one.
3
+ # @used_in {Base.included}
4
+ module Chains
5
+ protected
6
+
7
+ # Creates a chain of methods for creating a subject
8
+ # @note Override this method to add or remove methods executed while creating a subject
9
+ # @used_in {Actions#create}
10
+ # @use {Subject#create_subject}
11
+ # @use {Render#decide_what_to_render}
12
+ def create_chain
13
+ [:create_subject, :decide_what_to_render]
14
+ end
15
+
16
+ # Creates a chain of methods for updating a subject
17
+ # @note Override this method to add or remove methods executed while updating a subject
18
+ # @used_in {Actions#update}
19
+ # @use {Subject#fetch_subject}
20
+ # @use {Subject#update_subject}
21
+ # @use {Render#decide_what_to_render}
22
+ def update_chain
23
+ [:fetch_subject, :update_subject, :decide_what_to_render]
24
+ end
25
+
26
+ # Creates a chain of methods for deleting a subject
27
+ # @note Override this method to add or remove methods executed while deleting a subject
28
+ # @used_in {Actions#destroy}
29
+ # @use {Subject#fetch_subject}
30
+ # @use {Subject#destroy_subject}
31
+ def destroy_chain
32
+ [:fetch_subject, :destroy_subject]
33
+ end
34
+
35
+ # Creates a chain of methods for showing a subject
36
+ # @note Override this method to add or remove methods executed while showing a subject
37
+ # @used_in {Actions#show}
38
+ # @use {Subject#fetch_subject}
39
+ # @use {Render#render_subject}
40
+ def show_chain
41
+ [:fetch_subject, :render_subject]
42
+ end
43
+
44
+ # Creates a chain of methods for showing a list of subjects
45
+ # @note Override this method to add or remove methods executed while showing a list of subjects
46
+ # @used_in {Actions#index}
47
+ # @use {Subject#fetch_subjects}
48
+ # @use {Modificators#filter_subjects}
49
+ # @use {Modificators#sort_subjects}
50
+ # @use {Modificators#paginate_subjects}
51
+ # @use {Render#render_subjects}
52
+ def index_chain
53
+ [:fetch_subjects, :filter_subjects, :sort_subjects, :paginate_subjects, :render_subjects]
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,31 @@
1
+ module RestingPug
2
+ # Describes methods which modificate subject/subjects
3
+ # @used_in {Base.included}
4
+ module Modificators
5
+ protected
6
+
7
+ # Selects certain page from all subjects using pagination params
8
+ # @note Override this method to change pagination of subjects
9
+ # @used_in {Chains#index_chain}
10
+ # @use {Params#pagination_params}
11
+ def paginate_subjects
12
+ @subjects = @subjects.paginate(page: pagination_params[:page], per_page: pagination_params[:per_page])
13
+ end
14
+
15
+ # Sorts subjects using sorting params
16
+ # @note Override this method to change sorting of subjects
17
+ # @used_in {Chains#index_chain}
18
+ # @use {Params#sort_params}
19
+ def sort_subjects
20
+ @subjects = @subjects.order(sort_params)
21
+ end
22
+
23
+ # Filters subjects using filter params
24
+ # @note Override this method to change how subjects are filtered
25
+ # @used_in {Chains#index_chain}
26
+ # @use {Params#pagination_params}
27
+ def filter_subjects
28
+ @subjects = @subjects.where(filter_params)
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,189 @@
1
+ module RestingPug
2
+ # Describes transformations with params
3
+ # @used_in {Base.included}
4
+ module Params
5
+ protected
6
+
7
+ ### PERMITTED FIELDS
8
+
9
+ # Returns an array with all fields that API can use
10
+ # @note Override this method to add or remove fields that you don't want API to use.
11
+ # @return [Array] of symbols representing attributes
12
+ # @used_in {#permitted_fields_for_show}
13
+ # @used_in {#permitted_fields_for_create}
14
+ # @used_in {#permitted_fields_for_update}
15
+ # @used_in {#permitted_fields_for_sort}
16
+ # @used_in {#permitted_fields_for_filter}
17
+ # @use {Subject#subject_model}
18
+ def permitted_fields
19
+ subject_model.column_names.map(&:to_sym)
20
+ end
21
+
22
+ # Returns an array with all fields that API will show
23
+ # @note Override this method to add or remove fields that you don't want API to show.
24
+ # @return [Array] of symbols representing attributes
25
+ # @used_in {Render#render_subject}
26
+ # @used_in {Render#render_subjects}
27
+ # @use {#permitted_fields}
28
+ def permitted_fields_for_show
29
+ permitted_fields
30
+ end
31
+
32
+ # Returns an array with all fields that API will allow to use while creating a subject
33
+ # @note Override this method to add or remove fields that you don't want API to use for creating.
34
+ # @return [Array] of symbols representing attributes
35
+ # @used_in {#params_for_create}
36
+ # @use {#permitted_fields}
37
+ def permitted_fields_for_create
38
+ permitted_fields - [:id, :created_at, :updated_at]
39
+ end
40
+
41
+ # Returns an array with all fields that API will allow to use while updating a subject
42
+ # @note Override this method to add or remove fields that you don't want API to use for updating.
43
+ # @return [Array] of symbols representing attributes
44
+ # @used_in {#params_for_update}
45
+ # @use {#permitted_fields}
46
+ def permitted_fields_for_update
47
+ permitted_fields - [:id, :created_at, :updated_at]
48
+ end
49
+
50
+ # Returns an array with all fields that API will allow to use while sorting subjects
51
+ # @note Override this method to add or remove fields that you don't want API to use for sorting.
52
+ # @return [Array] of symbols representing attributes
53
+ # @used_in {#sort_params}
54
+ # @use {#permitted_fields}
55
+ def permitted_fields_for_sort
56
+ permitted_fields
57
+ end
58
+
59
+ # Returns an array with all fields that API will allow to use while filtering subjects by single value
60
+ # @note Override this method to add or remove fields that you don't want API to use for filtering by single value.
61
+ # If you want to change attributes that can be filtered by arrays of values check {#permitted_fields_for_filter_arrays}
62
+ # @return [Array] of symbols representing attributes
63
+ # @used_in {#permitted_fields_for_filter_arrays}
64
+ # @used_in {#permitted_fields_for_filter_with_arrays}
65
+ # @use {#permitted_fields}
66
+ def permitted_fields_for_filter
67
+ permitted_fields - [:created_at, :updated_at]
68
+ end
69
+
70
+ # Returns an array with all fields that API will allow to use while filtering subjects by array of values
71
+ # @note Override this method to add or remove fields that you don't want API to use for filtering by array of values.
72
+ # If you want to change attributes that can be filtered by single value check {#permitted_fields_for_filter}
73
+ # @return [Array] of symbols representing attributes
74
+ # @used_in {#permitted_fields_for_filter_with_arrays}
75
+ # @use {#permitted_fields_for_filter}
76
+ def permitted_fields_for_filter_arrays
77
+ permitted_fields_for_filter.map { |field| { field => [] } }
78
+ end
79
+
80
+ # Returns an array with all fields that API will allow to use while filtering subjects both by single values and by array of values
81
+ # @note To set fields that can be used check {#permitted_fields_for_filter} and {#permitted_fields_for_filter_arrays}
82
+ # @return [Array] of symbols representing attributes
83
+ # @used_in {#filter_params}
84
+ # @use {#permitted_fields_for_filter}
85
+ # @use {#permitted_fields_for_filter_arrays}
86
+ def permitted_fields_for_filter_with_arrays
87
+ permitted_fields_for_filter + permitted_fields_for_filter_arrays
88
+ end
89
+
90
+ # PARAMS
91
+
92
+ # Returns strong parameters which are used in creating action
93
+ # @note Override {#permitted_fields_for_create} to set allowed fields.
94
+ # Override {Subject#subject_model_sym} to change the root attrubute of params.
95
+ # @see http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
96
+ # @used_in {Subject#create_subject}
97
+ # @use {Subject#subject_model_sym}
98
+ # @use {#permitted_fields_for_create}
99
+ def params_for_create
100
+ params.require(subject_model_sym).permit(permitted_fields_for_create)
101
+ end
102
+
103
+ # Returns strong parameters which are used in updating action
104
+ # @note Override {#permitted_fields_for_update} to set allowed fields.
105
+ # Override {Subject#subject_model_sym} to change the root attrubute of params.
106
+ # @see http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
107
+ # @used_in {Subject#update_subject}
108
+ # @use {Subject#subject_model_sym}
109
+ # @use {#permitted_fields_for_update}
110
+ def params_for_update
111
+ params.require(subject_model_sym).permit(permitted_fields_for_update)
112
+ end
113
+
114
+ # FILTERING
115
+
116
+ # Returns strong parameters which are used for filtering subjects
117
+ # @note Override {#permitted_fields_for_filter} and {permitted_fields_for_filter_arrays} to set allowed fields.
118
+ # @see http://guides.rubyonrails.org/action_controller_overview.html#strong-parameters
119
+ # @used_in {Modificators#filter_subjects}
120
+ # @use {#permitted_fields_for_filter_with_arrays}
121
+ def filter_params
122
+ params[:filter] ? params.require(:filter).permit(permitted_fields_for_filter_with_arrays) : nil
123
+ end
124
+
125
+ # SORT
126
+
127
+ # Transforms a string like "-id,name" to a hash { id: :desc, name: :asc }
128
+ # @note Override {#permitted_fields_for_sort} to set allowed fields to sort.
129
+ # Override {#default_sort_params} to set default sort params.
130
+ # @used_in {Modificators#sort_subjects}
131
+ # @use {#permitted_fields_for_sort}
132
+ # @use {#default_sort_params}
133
+ def sort_params
134
+ sort_hash = nil
135
+ if params[:sort]
136
+ sort_array = params[:sort].split(',')
137
+ sort_array = sort_array.map do |field|
138
+ is_desc = field.split('-').count > 1
139
+ name = field.split('-').last
140
+ { name: name.to_sym, is_desc: is_desc }
141
+ end
142
+ sort_array.select! do |field|
143
+ permitted_fields_for_sort.include? field[:name]
144
+ end
145
+ sort_array.each do |field|
146
+ sort_hash ||= {}
147
+ sort_hash[field[:name]] = field[:is_desc] ? :desc : :asc
148
+ end
149
+ end
150
+ sort_hash || default_sort_params
151
+ end
152
+
153
+ # Returns a hash with default sorting params
154
+ # @note Override {#permitted_fields_for_sort} to set allowed fields to sort.
155
+ # @see http://guides.rubyonrails.org/active_record_querying.html#ordering
156
+ # @used_in {#sort_params}
157
+ def default_sort_params
158
+ {id: :desc}
159
+ end
160
+
161
+ # PAGINATION
162
+
163
+ # Handles pagination params and return a hash like { page: 1, per_page: 10 }
164
+ # @note Override {#per_page_range} to set minimum and maximum per_page param.
165
+ # Override {#per_page_default} to set default per_page param.
166
+ # @used_in {Modificators#paginate_subjects}
167
+ # @use {#per_page_range}
168
+ # @use {#per_page_default}
169
+ def pagination_params
170
+ page = params[:page].try(:to_i) || 1
171
+ per_page = [per_page_range[:min], params[:per_page].try(:to_i) || per_page_default, per_page_range[:max]].sort[1]
172
+ return { page: page, per_page: per_page }
173
+ end
174
+
175
+ # Returns a hash minimum and maximum per_page param like { page: 1, per_page: 10 }
176
+ # @note Override {#per_page_default} to set default per_page param.
177
+ # @used_in {#pagination_params}
178
+ def per_page_range
179
+ { min: 5, max: 100 }
180
+ end
181
+
182
+ # Returns a default per_page param
183
+ # @note Override {#per_page_range} to set minimum and maximum per_page param
184
+ # @used_in {#pagination_params}
185
+ def per_page_default
186
+ 10
187
+ end
188
+ end
189
+ end
@@ -0,0 +1,72 @@
1
+ module RestingPug
2
+ # Contains methods responsible for rendering response
3
+ # @used_in {Base.included}
4
+ module Render
5
+ protected
6
+
7
+ # Calls {#render_subject} if subject is valid and {#render_errors} otherwise
8
+ # @note Override {#render_subject} and {#render_errors} to change rendering behaviour
9
+ # @used_in {Chains#create_chain}
10
+ # @used_in {Chains#update_chain}
11
+ # @use {#render_subject}
12
+ # @use {#render_errors}
13
+ def decide_what_to_render
14
+ if @subject.valid?
15
+ render_subject
16
+ else
17
+ render_errors
18
+ end
19
+ end
20
+
21
+ # Renders json with a subject
22
+ # @note Override this method to add more complicated logic of rendering.
23
+ # Override {Subject#subject_model_sym} to change root attribute.
24
+ # Override {Params#permitted_fields_for_show} to change shown attributes.
25
+ # @used_in {#decide_what_to_render}
26
+ # @used_in {Chains#show_chain}
27
+ # @use {Subject#subject_model_sym}
28
+ # @use {Params#permitted_fields_for_show}
29
+ def render_subject
30
+ render json: { subject_model_sym => @subject.as_json(only: permitted_fields_for_show) }
31
+ end
32
+
33
+ # Renders json with subjects
34
+ # @note Override this method to add more complicated logic of rendering.
35
+ # Override {Subject#subject_model_sym_plural} to change root attribute.
36
+ # Override {Params#permitted_fields_for_show} to change shown attributes.
37
+ # @used_in {Chains#index_chain}
38
+ # @use {Subject#subject_model_sym_plural}
39
+ # @use {Params#permitted_fields_for_show}
40
+ def render_subjects
41
+ render json: { subject_model_sym_plural => @subjects.as_json(only: permitted_fields_for_show) }
42
+ end
43
+
44
+ # Renders empty response
45
+ # @note Override this method to add more complicated logic of rendering.
46
+ # @used_in {Subject#destroy_subject}
47
+ def render_nothing
48
+ render json: {}, status: 204
49
+ end
50
+
51
+ # Renders errors
52
+ # @note Override this method to add more complicated logic of rendering.
53
+ # @used_in {#decide_what_to_render}
54
+ def render_errors
55
+ render json: { errors: @subject.errors }, status: 422
56
+ end
57
+
58
+ # Renders error when required params are missing
59
+ # @note Override this method to add more complicated logic of rendering.
60
+ # @used_in {Base.included}
61
+ def render_param_missing
62
+ render json: { errors: { subject_model_sym => ['param is missing'] } }, status: 400
63
+ end
64
+
65
+ # Renders error when required params are missing
66
+ # @note Override this method to add more complicated logic of rendering.
67
+ # @used_in {Base.included}
68
+ def render_not_found
69
+ render json: {}, status: 404
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,87 @@
1
+ module RestingPug
2
+ # Defines everything related to subject basic operations(creation, updating etc)
3
+ # @used_in {Base.included}
4
+ module Subject
5
+ protected
6
+
7
+ # Gets a subject model from a controller class name
8
+ # @note Override this method if you want to use another model.
9
+ # @used_in {#subject_model_sym}
10
+ # @used_in {#subject_model_sym_plural}
11
+ # @used_in {#create_subject}
12
+ # @used_in {#fetch_subject}
13
+ # @used_in {#fetch_subjects}
14
+ # @used_in {Params#permitted_fields}
15
+ def subject_model
16
+ controller_name.classify.constantize
17
+ end
18
+
19
+ # Returns a symbol out of the subject model name
20
+ # @note Override this method to get another root for params and JSON responses.
21
+ # @use {#subject_model}
22
+ # @used_in {Params#params_for_create}
23
+ # @used_in {Params#params_for_update}
24
+ # @used_in {Render#render_subject}
25
+ # @used_in {Render#render_param_missing}
26
+ def subject_model_sym
27
+ subject_model.to_s.underscore.to_sym
28
+ end
29
+
30
+ # Returns a symbol out of the subject model name(plural)
31
+ # @note Override this method to get another root JSON response.
32
+ # @use {#subject_model}
33
+ # @used_in {Render#render_subjects}
34
+ def subject_model_sym_plural
35
+ subject_model.to_s.pluralize.underscore.to_sym
36
+ end
37
+
38
+ # Creates a subject
39
+ # @note Override this method to add some custom logic to creating process.
40
+ # @used_in {Chains#create_chain}
41
+ # @use {#subject_model}
42
+ # @use {Params#params_for_create}
43
+ def create_subject
44
+ @subject = subject_model.create(params_for_create)
45
+ end
46
+
47
+ # Updates a subject
48
+ # @note Override this method to add some custom logic to updating process.
49
+ # @used_in {Chains#update_chain}
50
+ # @use {Params#params_for_update}
51
+ def update_subject
52
+ @subject.update(params_for_update)
53
+ end
54
+
55
+ # Destroys a subject and render nothing or errors
56
+ # @note Override this method to add some custom logic to destroying process.
57
+ # @used_in {Chains#destroy_chain}
58
+ # @use {Render#render_nothing}
59
+ # @use {Render#render_errors}
60
+ def destroy_subject
61
+ if @subject.destroy
62
+ render_nothing
63
+ else
64
+ render_errors
65
+ end
66
+ end
67
+
68
+ # Finds a subject by id
69
+ # @note Override this method to add some custom logic to fetching process.
70
+ # @used_in {Chains#create_chain}
71
+ # @used_in {Chains#update_chain}
72
+ # @used_in {Chains#destroy_chain}
73
+ # @used_in {Chains#show_chain}
74
+ # @use {#subject_model}
75
+ def fetch_subject
76
+ @subject = subject_model.find(params[:id])
77
+ end
78
+
79
+ # Returns all subjects accessable for API
80
+ # @note Override this method to add some custom logic to fetching process.
81
+ # @used_in {Chains#index_chain}
82
+ # @use {#subject_model}
83
+ def fetch_subjects
84
+ @subjects = subject_model.all
85
+ end
86
+ end
87
+ end
@@ -0,0 +1,3 @@
1
+ module RestingPug
2
+ VERSION = '0.1.0'
3
+ end
@@ -0,0 +1,4 @@
1
+ # desc "Explaining what the task does"
2
+ # task :resting_pug do
3
+ # # Task goes here
4
+ # end
metadata ADDED
@@ -0,0 +1,157 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: resting_pug
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Slava Korolev
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2017-11-02 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: will_paginate
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rails
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '5.1'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '5.1'
41
+ - !ruby/object:Gem::Dependency
42
+ name: sqlite3
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec-rails
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '3.6'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '3.6'
69
+ - !ruby/object:Gem::Dependency
70
+ name: shoulda-matchers
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '3.1'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '3.1'
83
+ - !ruby/object:Gem::Dependency
84
+ name: factory_girl
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - "~>"
88
+ - !ruby/object:Gem::Version
89
+ version: '4.8'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - "~>"
95
+ - !ruby/object:Gem::Version
96
+ version: '4.8'
97
+ - !ruby/object:Gem::Dependency
98
+ name: faker
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - "~>"
102
+ - !ruby/object:Gem::Version
103
+ version: '1.8'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - "~>"
109
+ - !ruby/object:Gem::Version
110
+ version: '1.8'
111
+ description: Resting Pug allows you to create a JSON API with just adding one line
112
+ to your controller and fully customize it with overriding small and simple helper
113
+ methods.
114
+ email:
115
+ - korolvs@gmail.com
116
+ executables: []
117
+ extensions: []
118
+ extra_rdoc_files: []
119
+ files:
120
+ - MIT-LICENSE
121
+ - README.md
122
+ - Rakefile
123
+ - lib/resting_pug.rb
124
+ - lib/resting_pug/actions.rb
125
+ - lib/resting_pug/base.rb
126
+ - lib/resting_pug/chains.rb
127
+ - lib/resting_pug/modificators.rb
128
+ - lib/resting_pug/params.rb
129
+ - lib/resting_pug/render.rb
130
+ - lib/resting_pug/subject.rb
131
+ - lib/resting_pug/version.rb
132
+ - lib/tasks/resting_pug_tasks.rake
133
+ homepage: https://korolvs.github.io/resting_pug/
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - ">="
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - ">="
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.6.11
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: A simple and fully customizable way to create an API in your Rails application.
157
+ test_files: []