rails_on_rails 0.0.9

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (28) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +149 -0
  3. data/bin/rails_on_rails +5 -0
  4. data/lib/autogenerators/bash_commands/generate_controller.sh +1 -0
  5. data/lib/autogenerators/bash_commands/generate_model.sh +1 -0
  6. data/lib/autogenerators/bash_commands/install_rspec.sh +1 -0
  7. data/lib/autogenerators/generator_templates/application_record.txt +8 -0
  8. data/lib/autogenerators/generator_templates/controller.txt +14 -0
  9. data/lib/autogenerators/generator_templates/test_rspec_controller.txt +169 -0
  10. data/lib/autogenerators/generator_templates/test_seeder.txt +45 -0
  11. data/lib/autogenerators/handlers/controller.rb +28 -0
  12. data/lib/autogenerators/handlers/initialize_api_docs.rb +24 -0
  13. data/lib/autogenerators/handlers/initialize_global_controller.rb +7 -0
  14. data/lib/autogenerators/handlers/initialize_rspec.rb +23 -0
  15. data/lib/autogenerators/handlers/test_rspec_controller.rb +16 -0
  16. data/lib/autogenerators/handlers/test_seeder.rb +16 -0
  17. data/lib/autogenerators/rails_templates/api_documentation.rake +181 -0
  18. data/lib/autogenerators/rails_templates/auth_helper.rb +73 -0
  19. data/lib/autogenerators/rails_templates/documentation/index.html.erb +121 -0
  20. data/lib/autogenerators/rails_templates/documentation/layout.html.erb +14 -0
  21. data/lib/autogenerators/rails_templates/documentation_controller.rb +139 -0
  22. data/lib/autogenerators/rails_templates/global_controller.rb +411 -0
  23. data/lib/autogenerators/rails_templates/seeds.rb +91 -0
  24. data/lib/constants/cli_constants.rb +56 -0
  25. data/lib/constants/options.rb +61 -0
  26. data/lib/rails_on_rails.rb +124 -0
  27. data/lib/utils/rails_methods.rb +9 -0
  28. metadata +111 -0
@@ -0,0 +1,24 @@
1
+
2
+ dc_path = Dir.pwd + "/app/controllers/documentation_controller.rb"
3
+ dc_template_path = __dir__ + "/../rails_templates/documentation_controller.rb"
4
+
5
+ apr_path = Dir.pwd + "/lib/tasks/api_documentation.rake"
6
+ apr_template_path = __dir__ + "/../rails_templates/api_documentation.rake"
7
+
8
+ apvdt_path = Dir.pwd + "/app/views/documentation/index.html.erb"
9
+ apvdt_template_path = __dir__ + "/../rails_templates/documentation/index.html.erb"
10
+
11
+ apvlt_path = Dir.pwd + "/app/views/layouts/documentation.html.erb"
12
+ apvlt_template_path = __dir__ + "/../rails_templates/documentation/layout.html.erb"
13
+
14
+ system("bash #{__dir__}/../bash_commands/generate_controller.sh documentation")
15
+ dc_read_file = File.open(dc_template_path, 'r:UTF-8', &:read)
16
+ apr_read_file = File.open(apr_template_path, 'r:UTF-8', &:read)
17
+ apvdt_read_file = File.open(apvdt_template_path, 'r:UTF-8', &:read)
18
+ apvlt_read_file = File.open(apvlt_template_path, 'r:UTF-8', &:read)
19
+
20
+
21
+ File.write(dc_path, dc_read_file)
22
+ File.write(apr_path, apr_read_file)
23
+ File.write(apvdt_path, apvdt_read_file)
24
+ File.write(apvlt_path, apvlt_read_file)
@@ -0,0 +1,7 @@
1
+
2
+ controller_path = Dir.pwd + "/app/controllers/global_controller.rb"
3
+ template_path = __dir__ + "/../rails_templates/global_controller.rb"
4
+
5
+ read_file = File.open(template_path, 'r:UTF-8', &:read)
6
+
7
+ File.write(controller_path, read_file)
@@ -0,0 +1,23 @@
1
+
2
+ available_envs = Dir.glob("#{Dir.pwd}/config/environments/*.rb").map { |filename| File.basename(filename, ".rb") }
3
+ system("bash #{__dir__}/../bash_commands/install_rspec.sh")
4
+ system("mkdir #{Dir.pwd}/spec/controllers")
5
+ system("touch #{Dir.pwd}/spec/controllers/.gitkeep")
6
+ system("mkdir #{Dir.pwd}/spec/support")
7
+ system("mkdir #{Dir.pwd}/db/seedfiles")
8
+ ['common'].concat(available_envs).each do |env|
9
+ system("mkdir #{Dir.pwd}/db/seedfiles/#{env}")
10
+ system("touch #{Dir.pwd}/db/seedfiles/#{env}/.gitkeep")
11
+ end
12
+
13
+ seeds_path = Dir.pwd + "/db/seeds.rb"
14
+ seeds_template = __dir__ + "/../rails_templates/seeds.rb"
15
+
16
+ helper_path = Dir.pwd + "/spec/support/auth_helper.rb"
17
+ helper_template = __dir__ + "/../rails_templates/auth_helper.rb"
18
+
19
+ seeds_file = File.open(seeds_template, 'r:UTF-8', &:read)
20
+ helper_file = File.open(helper_template, 'r:UTF-8', &:read)
21
+
22
+ File.write(seeds_path, seeds_file)
23
+ File.write(helper_path, helper_file)
@@ -0,0 +1,16 @@
1
+ require_relative '../../utils/rails_methods.rb'
2
+
3
+ MODEL_NAME = ARGV[0]
4
+ MODEL_SNAKE_CASE = MODEL_NAME.underscore
5
+ API_ROUTE = "/#{MODEL_SNAKE_CASE}"
6
+
7
+
8
+ controller_path = Dir.pwd + "/spec/controllers/#{MODEL_SNAKE_CASE}_controller_spec.rb"
9
+ template_path = __dir__ + "/../generator_templates/test_rspec_controller.txt"
10
+
11
+ read_file = File.open(template_path, 'r:UTF-8', &:read)
12
+
13
+ read_file = read_file.gsub! '{{ MODEL }}', MODEL_NAME
14
+ read_file = read_file.gsub! '{{ API_ROUTE }}', API_ROUTE
15
+
16
+ File.write(controller_path, read_file)
@@ -0,0 +1,16 @@
1
+ require 'date'
2
+ require_relative '../../utils/rails_methods.rb'
3
+
4
+ MODEL_NAME = ARGV[0]
5
+ MODEL_SNAKE_CASE = MODEL_NAME.underscore
6
+
7
+ TIMESTAMP = DateTime.now.to_s.split('-').join('').split(':').join('').split('T').join('').slice(0, 14)
8
+
9
+ controller_path = Dir.pwd + "/db/seedfiles/test/#{TIMESTAMP}_#{MODEL_SNAKE_CASE}.rb"
10
+ template_path = __dir__ + "/../generator_templates/test_seeder.txt"
11
+
12
+ read_file = File.open(template_path, 'r:UTF-8', &:read)
13
+
14
+ read_file = read_file.gsub! '{{ MODEL }}', MODEL_NAME
15
+
16
+ File.write(controller_path, read_file)
@@ -0,0 +1,181 @@
1
+ namespace :api_documentation do
2
+ desc "TODO"
3
+ task frontend_javascript: :environment do
4
+ outpath = __dir__ + '/../../app/assets/javascripts/docs.js'
5
+
6
+ allRoutes = Rails.application.routes.routes.map do |e|
7
+ route = e.path.spec.to_s.split('(')[0]
8
+ method = e.verb
9
+ { route: route, method: method }
10
+ end.reject do |e|
11
+ first_path = e[:route].split('/')[1].to_s
12
+ first_path == 'rails' || first_path == 'assets' || first_path == 'docs' || first_path == 'cable'
13
+ end
14
+
15
+ javascriptString = ''
16
+ allRoutes.each do |route|
17
+
18
+ camelCased = ''
19
+ camelCased += route[:method].downcase
20
+
21
+ tempRoute = route[:route]
22
+
23
+ tempRoute.split('/').each do |line|
24
+ cap = line[0]
25
+ if cap == ':'
26
+ line[0] = ''
27
+ ln = ''
28
+ line.split('-').each do |l|
29
+ ln += l.capitalize
30
+ end
31
+ camelCased += ln.capitalize + 'Param'
32
+ else
33
+ ln = ''
34
+ line.split('-').each do |l|
35
+ ln += l.capitalize
36
+ end
37
+ camelCased += ln.capitalize
38
+ end
39
+ end
40
+
41
+ javascriptString += "window.#{camelCased} = function() {
42
+ var allData = {
43
+ method: '#{route[:method]}',
44
+ route: '#{route[:route]}',
45
+ };
46
+ var paramList = document.getElementById('#{camelCased}ParamsForm') && document.getElementById('#{camelCased}ParamsForm').elements ? document.getElementById('#{camelCased}ParamsForm').elements : [];
47
+
48
+ var csrfHeader = { headers: { 'X-CSRF-Token': null } };
49
+ var jsonWebToken = document.getElementById('#{camelCased}AuthorizationToken');
50
+ if (jsonWebToken && jsonWebToken.value) csrfHeader.headers['Authorization'] = jsonWebToken.value;
51
+
52
+ var paramObject = {};
53
+ var tempParamKey = null;
54
+ for (var i = 0; i < paramList.length; i++) {
55
+ var eleParam = paramList[i].value;
56
+ if (i % 2 !== 0) {
57
+ paramObject[':' + tempParamKey] = eleParam;
58
+ tempParamKey = null;
59
+ } else {
60
+ tempParamKey = eleParam;
61
+ }
62
+ }
63
+
64
+ var routeName = allData.route.split('/').map(e => paramObject[e] ? paramObject[e] : e).join('/');
65
+
66
+ if (allData.method !== 'GET' || allData.method !== 'DELETE') {
67
+ var bodyDataType = document.getElementById('#{camelCased}DataType') && document.getElementById('#{camelCased}DataType').value ? document.getElementById('#{camelCased}DataType').value : false;
68
+ var formBoolean = bodyDataType === 'Form Data';
69
+
70
+ var bodyElements = [];
71
+ var bodyRawElements = document.getElementById('#{camelCased}BodyForm') && document.getElementById('#{camelCased}BodyForm').elements ? document.getElementById('#{camelCased}BodyForm').elements : [];
72
+ for (var i = 0; i < bodyRawElements.length; i++) {
73
+ var eleParam = bodyRawElements[i].files ? bodyRawElements[i].files[0] : (bodyRawElements[i].value || null);
74
+ bodyElements.push(eleParam);
75
+ }
76
+
77
+ bodyElements = bodyElements.filter(e => !!e);
78
+
79
+ var bodyObject = bodyDataType === 'Form Data' ? new FormData() : {};
80
+ var tempBodyKey = null;
81
+ bodyElements.forEach((e, i) => {
82
+ if (i % 2 !== 0) {
83
+ if (formBoolean) {
84
+ bodyObject.append(tempBodyKey, e);
85
+ tempBodyKey = null;
86
+ } else {
87
+ bodyObject[tempBodyKey] = e;
88
+ tempBodyKey = null;
89
+ }
90
+ } else {
91
+ if (formBoolean) {
92
+ tempBodyKey = e;
93
+ } else {
94
+ bodyObject[e] = null;
95
+ tempBodyKey = e;
96
+ }
97
+ }
98
+ });
99
+ }
100
+
101
+ var qsElements = [];
102
+ var qsRawElements = document.getElementById('#{camelCased}QSForm') && document.getElementById('#{camelCased}QSForm').elements ? document.getElementById('#{camelCased}QSForm').elements : [];
103
+ for (var i = 0; i < qsRawElements.length; i++) {
104
+ var eleParam = qsRawElements[i].value || null;
105
+ qsElements.push(eleParam);
106
+ }
107
+
108
+ qsElements = qsElements.filter(e => !!e);
109
+
110
+ var qsObject = {};
111
+ var tempQSKey = null;
112
+ qsElements.forEach((e, i) => {
113
+ if (i % 2 !== 0) {
114
+ qsObject[tempQSKey] = e;
115
+ tempQSKey = null;
116
+ } else {
117
+ qsObject[e] = null;
118
+ tempQSKey = e;
119
+ }
120
+ });
121
+
122
+ var qsLength = Object.keys(qsObject).length;
123
+ var querystring = qsLength > 0 ? '?' : '';
124
+ var qsCount = 0;
125
+ if (querystring === '?') {
126
+ for (var qs in qsObject) {
127
+ if (qsLength - 1 === qsCount) {
128
+ querystring += qs + '=' + qsObject[qs];
129
+ } else {
130
+ querystring += qs + '=' + qsObject[qs] + '&';
131
+ }
132
+ }
133
+ }
134
+
135
+ var args = allData.method === 'GET' || allData.method === 'DELETE' ? [routeName + querystring, csrfHeader] : [routeName + querystring, bodyObject, csrfHeader];
136
+ var resultElement = document.getElementById('#{camelCased}-results');
137
+
138
+ axios[allData.method.toLowerCase()](...args)
139
+ .then((resp) => {
140
+ if (resp.status <= 300) {
141
+ resultElement.innerText = JSON.stringify(resp.data, null, 4);
142
+ } else {
143
+ resultElement.innerText = JSON.stringify(resp.data, null, 4);
144
+ }
145
+ })
146
+ .catch((err) => {
147
+ var error_ajax = err && err.response && err.response.data ? err.response.data : err;
148
+ resultElement.innerText = JSON.stringify(error_ajax, null, 4);
149
+ });
150
+ };
151
+ "
152
+
153
+ javascriptString += "window.#{camelCased}NewBody = function() {
154
+ var ele = document.getElementById('#{camelCased}BodyForm');
155
+ ele.innerHTML += '<div class=\"d-flex f-row\"><input class=\"w-100 m-1 form-control\" type=\"text\" placeholder=\"Enter key\"><input class=\"w-100 m-1 form-control\" type=\"text\" placeholder=\"Enter value\"></div>';
156
+ };
157
+
158
+ "
159
+
160
+ javascriptString += "window.#{camelCased}NewBodyFile = function() {
161
+ var ele = document.getElementById('#{camelCased}BodyForm');
162
+ ele.innerHTML += '<div class=\"d-flex f-row\"><input class=\"w-100 m-1 form-control\" type=\"text\" placeholder=\"Enter key\"><input class=\"w-100 m-1 form-control\" type=\"file\" multiple accept=\"*/*\" placeholder=\"Enter value\"></div>';
163
+ };
164
+
165
+ "
166
+
167
+ javascriptString += "window.#{camelCased}NewQS = function() {
168
+ var ele = document.getElementById('#{camelCased}QSForm');
169
+ ele.innerHTML += '<div class=\"d-flex f-row\"><input class=\"w-100 m-1 form-control\" type=\"text\" placeholder=\"Enter key\"><input class=\"w-100 m-1 form-control\" type=\"text\" placeholder=\"Enter value\"></div>';
170
+ };
171
+ "
172
+ end
173
+
174
+ File.open(outpath, "w+") do |f|
175
+ f.write(javascriptString)
176
+ end
177
+
178
+ end
179
+
180
+ end
181
+
@@ -0,0 +1,73 @@
1
+ def login_user
2
+ # Update your own login authenication endpoint
3
+ post '/login', params: { email: @user[:email], password: @user[:password] }
4
+ auth_header = response.headers['Authorization']
5
+ { Authorization: auth_header }
6
+ end
7
+
8
+ def objects_list_to_querystring qs, object
9
+ querystring = "#{qs}="
10
+ v = object.map { |key, val| "#{key.to_s}:#{val.to_s}" }.join(',')
11
+ querystring + v
12
+ end
13
+
14
+ def string_list_to_querystring qs, array
15
+ array = array.is_a?(Array) ? array : [array]
16
+ querystring = "#{qs}="
17
+ v = array.join(',')
18
+ querystring + v
19
+ end
20
+
21
+ def string_permuations array
22
+ index = 0
23
+ perms = array.each_with_object([]) do |e, acc|
24
+ index += 1
25
+ acc.push(array.slice(0, index))
26
+ end
27
+ order = perms.each_with_object([]) do |e, acc|
28
+ acc.push(e.permutation.to_a.map { |d| d.join(',') })
29
+ end
30
+ order.each_with_object([]) do |e, acc|
31
+ acc = acc.concat(e)
32
+ acc
33
+ end
34
+ end
35
+
36
+ def order_options array
37
+ array.each_with_object([]) do |e, acc|
38
+ acc.push("#{e} ASC")
39
+ acc.push("#{e} DESC")
40
+ end
41
+ end
42
+
43
+ def concat_all_with_default array
44
+ array.each_with_object(['']) do |e, acc|
45
+ acc = acc.concat(e)
46
+ acc
47
+ end
48
+ end
49
+
50
+ def include_querystrings array
51
+ [''].concat(string_permuations(array).map { |e| string_list_to_querystring('include', e) })
52
+ end
53
+
54
+ def where_querystrings array
55
+ [''].concat(array.map { |e| objects_list_to_querystring('where', e) })
56
+ end
57
+
58
+ def like_querystrings array
59
+ [''].concat(array.map { |e| objects_list_to_querystring('like', e) })
60
+ end
61
+
62
+ def order_querystrings array
63
+ [''].concat(array.map { |e| string_list_to_querystring('like', e) })
64
+ end
65
+
66
+ def get_associations model
67
+ model.reflect_on_all_associations.map(&:name)
68
+ .reject do |e|
69
+ model.reflect_on_association(e).is_a?(ActiveRecord::Reflection::ThroughReflection)
70
+ end.map { |e| e.to_s }
71
+ end
72
+
73
+
@@ -0,0 +1,121 @@
1
+ <div class="header p-3 bg-dark card-shadow d-flex flex-row justify-content-between">
2
+ <div class="d-flex flex-row">
3
+ <a href='/' class="h-100">
4
+ <img class="d-flex flex-column align-items-center justify-content-center" src="https://s3-us-west-1.amazonaws.com/manoftech/ruby.png" alt="" height='50' width='50' />
5
+ </a>
6
+ <h1 class="h1 h-100 align-items-center text-white ml-3">API Documentation</h1>
7
+ </div>
8
+ <a class="d-flex align-items-center cursor-pointer">
9
+ <h2 class="h5 text-white" onclick="goBack()">Go Back</h2>
10
+ </a>
11
+ </div>
12
+
13
+ <div class="card-body p-3 w-100 p-1">
14
+ <% @allRoutes.each do |data| %>
15
+ <div class="card card-outline-secondary w-100 flex-respond-row card-shadow">
16
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 p-1 card-shadow">
17
+ <div class='card-header <%= "#{data[:routeHeader]}" %>'>
18
+ <span class="mr-1"><%= data[:method] %>:</span>
19
+ <span><%= data[:route] %></span>
20
+ </div>
21
+ <div class="card-body p-2 w-100" style="max-height: 550px; overflow: auto;">
22
+ <% if data[:middleware] && data[:middleware].length > 0 %>
23
+ <h2 class="h5">Middleware Used:</h2>
24
+ <ul>
25
+ <% data[:middleware].each do |ware| %>
26
+ <li class="h6"><%= "#{ware}" %></li>
27
+ <% end %>
28
+ </ul>
29
+ <% end %>
30
+
31
+ <h2 class="h5">Description:
32
+ <ul>
33
+ <% data[:description].each do |ware| %>
34
+ <li class="h6"><%= "#{ware}" %></li>
35
+ <% end %>
36
+ </ul>
37
+ </h2>
38
+ <div class="d-flex f-row w-100">
39
+ <h2 class="w-100 h6">Authorization Header</h2>
40
+ </div>
41
+ <div class="d-flex f-row w-100">
42
+ <input id="<%= "#{data[:camelCased]}AuthorizationToken" %>" type="text" class="w-100 m-1 form-control" placeholder="Enter token">
43
+ </div>
44
+
45
+ <% if data[:allowParams] %>
46
+ <div class="d-flex f-row w-100">
47
+ <h2 class="w-100 h6">Params:</h2>
48
+ </div>
49
+ <div class="d-flex f-row w-100">
50
+ <form id="<%= "#{data[:camelCased]}ParamsForm" %>" class="w-100">
51
+ <%= data[:params].each do |param| %>
52
+ <div class="d-flex f-row">
53
+ <input id="<%= "#{data[:camelCased]}-#{param}" %>" type="text" class="w-100 m-1 d-flex f-row form-control" value="<%= "#{param}" %>">
54
+ <input id="<%= "#{data[:camelCased]}-#{param}-value" %>" type="text" class="w-100 m-1 form-control" placeholder="Enter value">
55
+ </div>
56
+ <% end %>
57
+ </form>
58
+ </div>
59
+ <% else %>
60
+ <span></span>
61
+ <% end %>
62
+ <% if data[:allowBody] %>
63
+ <div class="d-flex f-row w-100">
64
+ <h2 class="w-100 h6">Body:</h2>
65
+ <button class="<%= "#{data[:submitButtonColor]} rounded mr-2" %>" onclick="<%= "#{data[:camelCased]}NewBodyFile()" %>">Add File</button>
66
+ <button class="<%= "#{data[:submitButtonColor]} rounded-circle" %>" onclick="<%= "#{data[:camelCased]}NewBody()" %>">+</button>
67
+ </div>
68
+ <div class="d-flex f-row w-100">
69
+ <form id='<%= "#{data[:camelCased]}BodyForm" %>'class='w-100'>
70
+ <div class='d-flex f-row'>
71
+ <input type='text' class='w-100 m-1 form-control' placeholder='Enter key'>
72
+ <input type='text' class='w-100 m-1 form-control' placeholder='Enter value'>
73
+ </div>
74
+ </form>
75
+ </div>
76
+ <% else %>
77
+ <span></span>
78
+ <% end %>
79
+ <div class="d-flex f-row w-100">
80
+ <h2 class="w-100 h6">Querystrings: </h2>
81
+ <button class="<%= "#{data[:submitButtonColor]} rounded-circle" %>" onclick="<%= "#{data[:camelCased]}NewQS()" %>">+</button>
82
+ </div>
83
+ <div class="d-flex f-row w-100">
84
+ <form id='<%= "#{data[:camelCased]}QSForm" %>' class="w-100">
85
+ <div class="d-flex f-row">
86
+ <input type="text" class="w-100 m-1 form-control" placeholder="Enter key">
87
+ <input type="text" class="w-100 m-1 form-control" placeholder="Enter value">
88
+ </div>
89
+ </form>
90
+ </div>
91
+ <% if data[:allowBody] %>
92
+ <h2 class="h6">Body Data Type:</h2>
93
+ <select id="<%= "#{data[:camelCased]}DataType" %>" class='form-control'>
94
+ <option value=''></option>
95
+ <option value='JSON'>JSON</option>
96
+ <option value='Form Data'>Form Data</option>
97
+ </select>
98
+ <% else %>
99
+ <span></span>
100
+ <% end %>
101
+ <div class="w-100 mt-2">
102
+ <button class="<%= "#{data[:submitButtonColor]} w-100" %>" onclick="<%= "#{data[:camelCased]}()" %>">Submit</button>
103
+ </div>
104
+ </div>
105
+ </div>
106
+ <div class="col-xs-12 col-sm-12 col-md-12 col-lg-6 col-xl-6 p-1 card-shadow p-1">
107
+ <div class="card-header">
108
+ <h2 class="h5">Sample Data</h2>
109
+ </div>
110
+ <div class='card-body' style="max-height: 550px; overflow: auto;">
111
+ <code style="overflow: auto; display: block;">
112
+ <span id="<%= "#{data[:camelCased]}-results" %>" style="white-space: pre;"></span>
113
+ </code>
114
+ </div>
115
+ </div>
116
+ </div>
117
+ <% end %>
118
+ </div>
119
+
120
+ <script>function goBack() { window.history.back(); }</script>
121
+ <script src="https://cdnjs.cloudflare.com/ajax/libs/axios/0.18.0/axios.min.js"></script>