rest_framework 0.9.5 → 0.9.7

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/LICENSE +1 -1
  3. data/README.md +130 -0
  4. data/VERSION +1 -1
  5. data/app/views/layouts/rest_framework.html.erb +9 -183
  6. data/app/views/rest_framework/_breadcrumbs.html.erb +27 -0
  7. data/app/views/rest_framework/_head.html.erb +347 -190
  8. data/app/views/rest_framework/_header.html.erb +15 -0
  9. data/app/views/rest_framework/_heading.html.erb +10 -0
  10. data/app/views/rest_framework/_payloads.html.erb +36 -0
  11. data/app/views/rest_framework/_request_metadata.html.erb +16 -0
  12. data/app/views/rest_framework/_routes_and_forms.html.erb +52 -0
  13. data/app/views/rest_framework/head/_external.html.erb +7 -2
  14. data/app/views/rest_framework/header/_mode.html.erb +14 -0
  15. data/app/views/rest_framework/heading/_actions.html.erb +9 -0
  16. data/app/views/rest_framework/{_routes.html.erb → routes_and_forms/_routes.html.erb} +2 -2
  17. data/lib/rest_framework/controller_mixins/base.rb +11 -12
  18. data/lib/rest_framework/engine.rb +5 -3
  19. data/lib/rest_framework/filters/ransack.rb +6 -6
  20. data/lib/rest_framework/version.rb +3 -8
  21. data/lib/rest_framework.rb +11 -2
  22. data/vendor/assets/javascripts/rest_framework/external.min.js +1256 -0
  23. data/vendor/assets/stylesheets/rest_framework/{bootstrap-icons.min.css → external.min.css} +415 -0
  24. data/vendor/assets/stylesheets/rest_framework/highlight-a11y-dark.min.css +1 -1
  25. data/vendor/assets/stylesheets/rest_framework/highlight-a11y-light.min.css +1 -1
  26. metadata +16 -33
  27. data/README.md +0 -1
  28. data/app/views/rest_framework/head/_shared.html +0 -164
  29. data/docs/CNAME +0 -1
  30. data/docs/Gemfile +0 -5
  31. data/docs/Gemfile.lock +0 -264
  32. data/docs/_config.yml +0 -19
  33. data/docs/_guide/1_routers.md +0 -110
  34. data/docs/_guide/2_controllers.md +0 -342
  35. data/docs/_guide/3_serializers.md +0 -60
  36. data/docs/_guide/4_filtering_and_ordering.md +0 -41
  37. data/docs/_guide/5_pagination.md +0 -21
  38. data/docs/_includes/anchor_headings.html +0 -144
  39. data/docs/_includes/external.html +0 -9
  40. data/docs/_includes/head.html +0 -155
  41. data/docs/_includes/header.html +0 -58
  42. data/docs/_includes/shared.html +0 -164
  43. data/docs/_layouts/default.html +0 -11
  44. data/docs/assets/images/favicon.ico +0 -0
  45. data/docs/index.md +0 -133
  46. data/vendor/assets/javascripts/rest_framework/bootstrap.min.js +0 -6
  47. data/vendor/assets/javascripts/rest_framework/highlight-json.min.js +0 -7
  48. data/vendor/assets/javascripts/rest_framework/highlight-xml.min.js +0 -29
  49. data/vendor/assets/javascripts/rest_framework/highlight.min.js +0 -1202
  50. data/vendor/assets/javascripts/rest_framework/neatjson.min.js +0 -7
  51. data/vendor/assets/javascripts/rest_framework/trix.min.js +0 -6
  52. data/vendor/assets/stylesheets/rest_framework/bootstrap.min.css +0 -5
  53. data/vendor/assets/stylesheets/rest_framework/trix.min.css +0 -410
  54. /data/app/views/rest_framework/{_html_form.html.erb → routes_and_forms/_html_form.html.erb} +0 -0
  55. /data/app/views/rest_framework/{_raw_form.html.erb → routes_and_forms/_raw_form.html.erb} +0 -0
  56. /data/app/views/rest_framework/{_route.html.erb → routes_and_forms/routes/_route.html.erb} +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a05761bba2e30e1d6ff017ee8f987cf1537d9adf99328539f1c9c6a60707948
4
- data.tar.gz: 4ee9e5369c834b9fd3305a7c406547b7706d8531ecd0eba785ff041c808aaf2d
3
+ metadata.gz: 8a9201bc66da6f1038a27aad8e0754d3b14973c20ca5bb3486b545c081e1cf31
4
+ data.tar.gz: af160d2b5f66a1d2ab4b40dcd366e5f10d46e5b4f075ac01926cfbcbc03a5c62
5
5
  SHA512:
6
- metadata.gz: eec50899e0d0b3b0dfe6cbcc4d6c2ada25107c94093b15974c5fed7d2bf6ac7d628f624c5eade1307002750c3880b70dac50d3edbbeb4fde9172c3ccdd1e5e0a
7
- data.tar.gz: 5f811d4561acc53b41376454c969c47d7762c33393a7bc1eb13d3e27724c56e7c3d38403337fea50e0aa08902106fa579a8d48f1f86dc78f8e76b126c1e138bc
6
+ metadata.gz: 756aa93e81e2cd240a6d383df774c8003a4063e514bd19acce8857a36ae6844c4ee3dddafdd2c9a246ab4f213f9c9b01bd52bcf2758d84b6ec09b59f73ae3257
7
+ data.tar.gz: e7b9e1e1730604c3702e9e1c8b744c87ac6d474db8cb70f32457467ddbc25817bc94404b26560c4b19f3ac0ecdd4704ff9393cbd7a88216052ee13071a97a23a
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2022 Gregory N. Schmit
3
+ Copyright (c) 2023 Gregory N. Schmit
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
data/README.md ADDED
@@ -0,0 +1,130 @@
1
+ # Rails REST Framework
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/rest_framework.svg)](https://badge.fury.io/rb/rest_framework)
4
+ [![Pipeline](https://github.com/gregschmit/rails-rest-framework/actions/workflows/pipeline.yml/badge.svg)](https://github.com/gregschmit/rails-rest-framework/actions/workflows/pipeline.yml)
5
+ [![Coverage](https://coveralls.io/repos/github/gregschmit/rails-rest-framework/badge.svg?branch=master)](https://coveralls.io/github/gregschmit/rails-rest-framework?branch=master)
6
+ [![Maintainability](https://api.codeclimate.com/v1/badges/ba5df7706cb544d78555/maintainability)](https://codeclimate.com/github/gregschmit/rails-rest-framework/maintainability)
7
+
8
+ A framework for DRY RESTful APIs in Ruby on Rails.
9
+
10
+ **The Problem**: Building controllers for APIs usually involves writing a lot of redundant CRUD
11
+ logic, and routing them can be obnoxious. Building and maintaining features like ordering,
12
+ filtering, and pagination can be tedious.
13
+
14
+ **The Solution**: This framework implements browsable API responses, CRUD actions for your models,
15
+ and features like ordering/filtering/pagination, so you can focus on building awesome APIs.
16
+
17
+ Website/Guide: [rails-rest-framework.com](https://rails-rest-framework.com)
18
+
19
+ Demo API: [rails-rest-framework.com/api/demo](https://rails-rest-framework.com/api/demo)
20
+
21
+ Source: [github.com/gregschmit/rails-rest-framework](https://github.com/gregschmit/rails-rest-framework)
22
+
23
+ YARD Docs: [rubydoc.info/gems/rest_framework](https://rubydoc.info/gems/rest_framework)
24
+
25
+ ## Installation
26
+
27
+ Add this line to your application's Gemfile:
28
+
29
+ ```ruby
30
+ gem 'rest_framework'
31
+ ```
32
+
33
+ And then execute:
34
+
35
+ ```shell
36
+ $ bundle install
37
+ ```
38
+
39
+ Or install it yourself with:
40
+
41
+ ```shell
42
+ $ gem install rest_framework
43
+ ```
44
+
45
+ ## Quick Usage Tutorial
46
+
47
+ ### Controller Mixins
48
+
49
+ To transform a controller into a RESTful controller, you can either include `BaseControllerMixin`,
50
+ `ReadOnlyModelControllerMixin`, or `ModelControllerMixin`. `BaseControllerMixin` provides a `root`
51
+ action and a simple interface for routing arbitrary additional actions:
52
+
53
+ ```ruby
54
+ class ApiController < ApplicationController
55
+ include RESTFramework::BaseControllerMixin
56
+ self.extra_actions = {test: :get}
57
+
58
+ def test
59
+ render api_response({message: "Test successful!"})
60
+ end
61
+ end
62
+ ```
63
+
64
+ `ModelControllerMixin` assists with providing the standard model CRUD for your controller.
65
+
66
+ ```ruby
67
+ class Api::MoviesController < ApiController
68
+ include RESTFramework::ModelControllerMixin
69
+
70
+ self.recordset = Movie.where(enabled: true)
71
+ end
72
+ ```
73
+
74
+ `ReadOnlyModelControllerMixin` only enables list/show actions, but since we're naming this
75
+ controller in a way that doesn't make the model obvious, we can set that explicitly:
76
+
77
+ ```ruby
78
+ class Api::ReadOnlyMoviesController < ApiController
79
+ include RESTFramework::ReadOnlyModelControllerMixin
80
+
81
+ self.model = Movie
82
+ end
83
+ ```
84
+
85
+ Note that you can also override the `get_recordset` instance method to override the API behavior
86
+ dynamically per-request.
87
+
88
+ ### Routing
89
+
90
+ You can use Rails' `resource`/`resources` routers to route your API, however if you want
91
+ `extra_actions` / `extra_member_actions` to be routed automatically, then you can use `rest_route`
92
+ for non-resourceful controllers, or `rest_resource` / `rest_resources` resourceful routers. You can
93
+ also use `rest_root` to route the root of your API:
94
+
95
+ ```ruby
96
+ Rails.application.routes.draw do
97
+ rest_root :api # will find `api_controller` and route the `root` action to '/api'
98
+ namespace :api do
99
+ rest_resources :movies
100
+ rest_resources :users
101
+ end
102
+ end
103
+ ```
104
+
105
+ Or if you want the API root to be routed to `Api::RootController#root`:
106
+
107
+ ```ruby
108
+ Rails.application.routes.draw do
109
+ namespace :api do
110
+ rest_root # will route `Api::RootController#root` to '/' in this namespace ('/api')
111
+ rest_resources :movies
112
+ rest_resources :users
113
+ end
114
+ end
115
+ ```
116
+
117
+ ## Development/Testing
118
+
119
+ After you clone the repository, cd'ing into the directory should create a new gemset if you are
120
+ using RVM. Then run `bundle install` to install the appropriate gems.
121
+
122
+ To run the test suite:
123
+
124
+ ```shell
125
+ $ rails test
126
+ ```
127
+
128
+ The top-level `bin/rails` proxies all Rails commands to the test project, so you can operate it via
129
+ the usual commands. Ensure you run `rails db:setup` before running `rails server` or
130
+ `rails console`.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.9.5
1
+ 0.9.7
@@ -8,195 +8,21 @@
8
8
  <%= csp_meta_tag rescue nil %>
9
9
 
10
10
  <%= render partial: "rest_framework/head", cached: true %>
11
+
12
+ <%= yield :head %>
11
13
  </head>
12
14
 
13
15
  <body>
14
16
  <header>
15
- <div class="w-100 m-0 p-0" id="rrfAccentBar"></div>
16
- <nav class="navbar py-0" data-bs-theme="dark">
17
- <div class="container">
18
- <span class="navbar-brand p-0">
19
- <h1 title="RRF v<%= RESTFramework::VERSION %>" class="text-light font-weight-light m-0 p-0" style="font-size: 1em">
20
- <%= @template_logo_text || "Rails REST Framework" %>
21
- </h1>
22
- </span>
23
- <div class="dropdown ms-auto" id="rrfModeComponent">
24
- <button class="btn btn-dark dropdown-toggle rounded-0 bg-black" style="border-color: black" data-bs-toggle="dropdown"></button>
25
- <div class="rrf-mode dropdown-menu dropdown-menu-end py-0 rounded-0" style="font-size: .8em; min-width: 0">
26
- <button class="dropdown-item text-end" data-rrf-mode-value="system">
27
- System<i class="bi bi-circle-half ms-2"></i>
28
- </button>
29
- <button class="dropdown-item text-end" data-rrf-mode-value="light">
30
- Light<i class="bi bi-sun-fill ms-2"></i>
31
- </button>
32
- <button class="dropdown-item text-end" data-rrf-mode-value="dark">
33
- Dark<i class="bi bi-moon-stars-fill ms-2"></i>
34
- </button>
35
- </div>
36
- </div>
37
- </div>
38
- </nav>
17
+ <%= render partial: "rest_framework/header" %>
39
18
  </header>
40
19
  <div class="container py-3">
41
- <div class="row">
42
- <nav>
43
- <ol class="breadcrumb">
44
- <%
45
- breadcrumbs = request.path.split("/").inject([]) { |breadcrumbs, part|
46
- # Ignore blank parts of the path (leading slash or double-slashes).
47
- next breadcrumbs if part.blank?
48
-
49
- last_path = breadcrumbs.last&.first || "/"
50
- breadcrumbs << [
51
- [last_path, part].join(last_path[-1] == "/" ? "" : "/"),
52
- part,
53
- ]
54
-
55
- next breadcrumbs
56
- }
57
- %>
58
- <% breadcrumbs.each_with_index do |(path, label), i| %>
59
- <% if i != breadcrumbs.size - 1 %>
60
- <li class="breadcrumb-item"><a href="<%= path %>"><%= label %></a></li>
61
- <% else %>
62
- <li class="breadcrumb-item active"><%= label %></li>
63
- <% end %>
64
- <% end %>
65
- </ol>
66
- </nav>
67
- </div>
68
- <div class="row">
69
- <div>
70
- <h1 class="m-0"><%= (@header_text if defined? @header_text) || @title %></h1>
71
- <div style="float: right">
72
- <% if @route_groups.values[0].any? { |r| r[:matches_path] && r[:verb] == "DELETE" && r[:action] == "destroy" } %>
73
- <button type="button" class="btn btn-danger" onclick="rrfDelete(this)">DELETE</button>
74
- <% end %>
75
- <% if @route_groups.values[0].any? { |r| r[:matches_path] && r[:verb] == "OPTIONS" } %>
76
- <button type="button" class="btn btn-primary" onclick="rrfOptions(this)">OPTIONS</button>
77
- <% end %>
78
- <button type="button" class="btn btn-primary" onclick="rrfGet(this)">GET</button>
79
- </div>
80
- <% if @description.present? %>
81
- <br><br><p style="display: inline-block; margin-bottom: 0"><%= @description %></p>
82
- <% end %>
83
- </div>
84
- </div>
85
- <hr/>
86
- <div class="row">
87
- <div>
88
- <pre style="white-space: normal">
89
- <code>
90
- <strong>
91
- <%= request.request_method %>
92
- <% if request.method != request.request_method %>
93
- (via <%= request.method %>)
94
- <% end %>
95
- </strong> <%= request.path %><br>
96
- </code>
97
- </pre>
98
- <pre style="white-space: normal">
99
- <code>
100
- <strong>HTTP <%= response.status %> <%= response.message %></strong><br>
101
- <strong>Content-Type:</strong> <%= response.content_type %>
102
- </code>
103
- </pre>
104
- </div>
105
- </div>
106
- <% if @json_payload.present? || @xml_payload.present? %>
107
- <div class="row">
108
- <div>
109
- <ul class="nav nav-tabs">
110
- <% if @json_payload.present? %>
111
- <li class="nav-item">
112
- <a class="nav-link active" href="#tab-json" data-bs-toggle="tab" role="tab">
113
- .json
114
- </a>
115
- </li>
116
- <% end %>
117
- <% if @xml_payload.present? %>
118
- <li class="nav-item">
119
- <a class="nav-link" href="#tab-xml" data-bs-toggle="tab" role="tab">
120
- .xml
121
- </a>
122
- </li>
123
- <% end %>
124
- </ul>
125
- </div>
126
- <div class="tab-content pt-2">
127
- <div class="tab-pane fade show active" id="tab-json" role="tabpanel">
128
- <% if @json_payload.present? %>
129
- <div><pre class="rrf-copy"><code class="auto-hljs language-json"><%=
130
- JSON.pretty_generate(
131
- JSON.parse(@json_payload)
132
- ) unless @json_payload == ''
133
- %></code></pre></div>
134
- <% end %>
135
- </div>
136
- <div class="tab-pane fade" id="tab-xml" role="tabpanel">
137
- <% if @xml_payload.present? %>
138
- <div><pre class="rrf-copy"><code class="auto-hljs language-xml"><%=
139
- CGI.unescapeHTML(@xml_payload)
140
- %></code></pre></div>
141
- <% end %>
142
- </div>
143
- </div>
144
- </div>
145
- <% end %>
146
- <% if @route_groups.present? %>
147
- <%
148
- @is_model_controller = controller.class.included_modules.include?(RESTFramework::ModelControllerMixin)
149
- %>
150
- <div class="row">
151
- <div>
152
- <ul class="nav nav-tabs">
153
- <li class="nav-item">
154
- <a class="nav-link active" href="#tab-routes" data-bs-toggle="tab" role="tab">
155
- Routes
156
- </a>
157
- </li>
158
- <% @_rrf_form_routes_raw = @route_groups.values[0].select { |r|
159
- r[:matches_params] && (
160
- r[:verb].in?(["POST", "PUT", "PATCH"]) ||
161
- (r[:verb] == "DELETE" && r[:action] == "destroy_all")
162
- )
163
- } %>
164
- <% @_rrf_form_routes_html = @route_groups.values[0].select { |r|
165
- r[:matches_params] && r[:verb].in?(["POST", "PUT", "PATCH"])
166
- } %>
167
- <% if @_rrf_form_routes_raw.present? %>
168
- <li class="nav-item">
169
- <a class="nav-link" href="#tabRawForm" data-bs-toggle="tab" role="tab">
170
- Raw Form
171
- </a>
172
- </li>
173
- <% end %>
174
- <% if @_rrf_form_routes_html.present? && @is_model_controller %>
175
- <li class="nav-item">
176
- <a class="nav-link" href="#tabHtmlForm" data-bs-toggle="tab" role="tab">
177
- HTML Form
178
- </a>
179
- </li>
180
- <% end %>
181
- </ul>
182
- </div>
183
- <div class="tab-content pt-2">
184
- <div class="tab-pane fade show active" id="tab-routes" role="tabpanel">
185
- <%= render partial: "rest_framework/routes" %>
186
- </div>
187
- <% if @_rrf_form_routes_raw.present? %>
188
- <div class="tab-pane fade" id="tabRawForm" role="tabpanel">
189
- <%= render partial: "rest_framework/raw_form" %>
190
- </div>
191
- <% end %>
192
- <% if @_rrf_form_routes_html.present? && @is_model_controller %>
193
- <div class="tab-pane fade" id="tabHtmlForm" role="tabpanel">
194
- <%= render partial: "rest_framework/html_form" %>
195
- </div>
196
- <% end %>
197
- </div>
198
- </div>
199
- <% end %>
20
+ <%= render partial: "rest_framework/breadcrumbs" unless @hide_breadcrumbs %>
21
+ <%= render partial: "rest_framework/heading" unless @hide_heading %>
22
+ <%= render partial: "rest_framework/request_metadata" unless @hide_request_metadata %>
23
+ <%= yield %>
24
+ <%= render partial: "rest_framework/payloads" if @json_payload.present? || @xml_payload.present? %>
25
+ <%= render partial: "rest_framework/routes_and_forms" if @route_groups.present? %>
200
26
  </div>
201
27
  </body>
202
28
  </html>
@@ -0,0 +1,27 @@
1
+ <div class="row">
2
+ <nav>
3
+ <ol class="breadcrumb">
4
+ <%
5
+ breadcrumbs = request.path.split("/").inject([]) { |breadcrumbs, part|
6
+ # Ignore blank parts of the path (leading slash or double-slashes).
7
+ next breadcrumbs if part.blank?
8
+
9
+ last_path = breadcrumbs.last&.first || "/"
10
+ breadcrumbs << [
11
+ [last_path, part].join(last_path[-1] == "/" ? "" : "/"),
12
+ part,
13
+ ]
14
+
15
+ next breadcrumbs
16
+ }
17
+ %>
18
+ <% breadcrumbs.each_with_index do |(path, label), i| %>
19
+ <% if i != breadcrumbs.size - 1 %>
20
+ <li class="breadcrumb-item"><a href="<%= path %>"><%= label %></a></li>
21
+ <% else %>
22
+ <li class="breadcrumb-item active"><%= label %></li>
23
+ <% end %>
24
+ <% end %>
25
+ </ol>
26
+ </nav>
27
+ </div>