resting_pug 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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: []