rest_framework 0.9.5 → 0.9.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/LICENSE +1 -1
- data/README.md +130 -0
- data/VERSION +1 -1
- data/app/views/layouts/rest_framework.html.erb +9 -183
- data/app/views/rest_framework/_breadcrumbs.html.erb +27 -0
- data/app/views/rest_framework/_head.html.erb +348 -190
- data/app/views/rest_framework/_header.html.erb +15 -0
- data/app/views/rest_framework/_heading.html.erb +10 -0
- data/app/views/rest_framework/_payloads.html.erb +36 -0
- data/app/views/rest_framework/_request_metadata.html.erb +16 -0
- data/app/views/rest_framework/_routes_and_forms.html.erb +52 -0
- data/app/views/rest_framework/head/_external.html.erb +7 -2
- data/app/views/rest_framework/header/_mode.html.erb +14 -0
- data/app/views/rest_framework/heading/_actions.html.erb +9 -0
- data/app/views/rest_framework/{_routes.html.erb → routes_and_forms/_routes.html.erb} +2 -2
- data/lib/rest_framework/controller_mixins/base.rb +11 -12
- data/lib/rest_framework/engine.rb +5 -3
- data/lib/rest_framework/filters/ransack.rb +6 -6
- data/lib/rest_framework/version.rb +0 -6
- data/lib/rest_framework.rb +11 -2
- data/vendor/assets/javascripts/rest_framework/external.min.js +1256 -0
- data/vendor/assets/stylesheets/rest_framework/{bootstrap-icons.min.css → external.min.css} +415 -0
- data/vendor/assets/stylesheets/rest_framework/highlight-a11y-dark.min.css +1 -1
- data/vendor/assets/stylesheets/rest_framework/highlight-a11y-light.min.css +1 -1
- metadata +16 -33
- data/README.md +0 -1
- data/app/views/rest_framework/head/_shared.html +0 -164
- data/docs/CNAME +0 -1
- data/docs/Gemfile +0 -5
- data/docs/Gemfile.lock +0 -264
- data/docs/_config.yml +0 -19
- data/docs/_guide/1_routers.md +0 -110
- data/docs/_guide/2_controllers.md +0 -342
- data/docs/_guide/3_serializers.md +0 -60
- data/docs/_guide/4_filtering_and_ordering.md +0 -41
- data/docs/_guide/5_pagination.md +0 -21
- data/docs/_includes/anchor_headings.html +0 -144
- data/docs/_includes/external.html +0 -9
- data/docs/_includes/head.html +0 -155
- data/docs/_includes/header.html +0 -58
- data/docs/_includes/shared.html +0 -164
- data/docs/_layouts/default.html +0 -11
- data/docs/assets/images/favicon.ico +0 -0
- data/docs/index.md +0 -133
- data/vendor/assets/javascripts/rest_framework/bootstrap.min.js +0 -6
- data/vendor/assets/javascripts/rest_framework/highlight-json.min.js +0 -7
- data/vendor/assets/javascripts/rest_framework/highlight-xml.min.js +0 -29
- data/vendor/assets/javascripts/rest_framework/highlight.min.js +0 -1202
- data/vendor/assets/javascripts/rest_framework/neatjson.min.js +0 -7
- data/vendor/assets/javascripts/rest_framework/trix.min.js +0 -6
- data/vendor/assets/stylesheets/rest_framework/bootstrap.min.css +0 -5
- data/vendor/assets/stylesheets/rest_framework/trix.min.css +0 -410
- /data/app/views/rest_framework/{_html_form.html.erb → routes_and_forms/_html_form.html.erb} +0 -0
- /data/app/views/rest_framework/{_raw_form.html.erb → routes_and_forms/_raw_form.html.erb} +0 -0
- /data/app/views/rest_framework/{_route.html.erb → routes_and_forms/routes/_route.html.erb} +0 -0
@@ -0,0 +1,52 @@
|
|
1
|
+
<%
|
2
|
+
@is_model_controller = controller.class.included_modules.include?(RESTFramework::ModelControllerMixin)
|
3
|
+
%>
|
4
|
+
<div class="row">
|
5
|
+
<div>
|
6
|
+
<ul class="nav nav-tabs">
|
7
|
+
<li class="nav-item">
|
8
|
+
<a class="nav-link active" href="#tab-routes" data-bs-toggle="tab" role="tab">
|
9
|
+
Routes
|
10
|
+
</a>
|
11
|
+
</li>
|
12
|
+
<% @_rrf_form_routes_raw = @route_groups.values[0].select { |r|
|
13
|
+
r[:matches_params] && (
|
14
|
+
r[:verb].in?(["POST", "PUT", "PATCH"]) ||
|
15
|
+
(r[:verb] == "DELETE" && r[:action] == "destroy_all")
|
16
|
+
)
|
17
|
+
} %>
|
18
|
+
<% @_rrf_form_routes_html = @route_groups.values[0].select { |r|
|
19
|
+
r[:matches_params] && r[:verb].in?(["POST", "PUT", "PATCH"])
|
20
|
+
} %>
|
21
|
+
<% if @_rrf_form_routes_raw.present? %>
|
22
|
+
<li class="nav-item">
|
23
|
+
<a class="nav-link" href="#tabRawForm" data-bs-toggle="tab" role="tab">
|
24
|
+
Raw Form
|
25
|
+
</a>
|
26
|
+
</li>
|
27
|
+
<% end %>
|
28
|
+
<% if @_rrf_form_routes_html.present? && @is_model_controller %>
|
29
|
+
<li class="nav-item">
|
30
|
+
<a class="nav-link" href="#tabHtmlForm" data-bs-toggle="tab" role="tab">
|
31
|
+
HTML Form
|
32
|
+
</a>
|
33
|
+
</li>
|
34
|
+
<% end %>
|
35
|
+
</ul>
|
36
|
+
</div>
|
37
|
+
<div class="tab-content pt-2">
|
38
|
+
<div class="tab-pane fade show active" id="tab-routes" role="tabpanel">
|
39
|
+
<%= render partial: "rest_framework/routes_and_forms/routes" %>
|
40
|
+
</div>
|
41
|
+
<% if @_rrf_form_routes_raw.present? %>
|
42
|
+
<div class="tab-pane fade" id="tabRawForm" role="tabpanel">
|
43
|
+
<%= render partial: "rest_framework/routes_and_forms/raw_form" %>
|
44
|
+
</div>
|
45
|
+
<% end %>
|
46
|
+
<% if @_rrf_form_routes_html.present? && @is_model_controller %>
|
47
|
+
<div class="tab-pane fade" id="tabHtmlForm" role="tabpanel">
|
48
|
+
<%= render partial: "rest_framework/routes_and_forms/html_form" %>
|
49
|
+
</div>
|
50
|
+
<% end %>
|
51
|
+
</div>
|
52
|
+
</div>
|
@@ -1,9 +1,14 @@
|
|
1
1
|
<% if RESTFramework.config.use_vendored_assets %>
|
2
|
-
|
2
|
+
<%= javascript_include_tag RESTFramework::EXTERNAL_JS_NAME, defer: true %>
|
3
|
+
<%= stylesheet_link_tag RESTFramework::EXTERNAL_CSS_NAME %>
|
4
|
+
|
5
|
+
<% RESTFramework::EXTERNAL_UNSUMMARIZED_ASSETS.each do |name, cfg| %>
|
3
6
|
<% if cfg[:place] == "javascripts" %>
|
4
7
|
<%= javascript_include_tag "rest_framework/#{name}", defer: true, **cfg[:extra_tag_attrs] %>
|
5
|
-
<%
|
8
|
+
<% elsif cfg[:place] == "stylesheets" %>
|
6
9
|
<%= stylesheet_link_tag "rest_framework/#{name}", **cfg[:extra_tag_attrs] %>
|
10
|
+
<% else %>
|
11
|
+
<% raise "Unknown asset place." %>
|
7
12
|
<% end %>
|
8
13
|
<% end %>
|
9
14
|
<% else %>
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<div class="dropdown float-end" id="rrfModeComponent">
|
2
|
+
<button class="btn btn-dark dropdown-toggle rounded-0 bg-black" style="border-color: black" data-bs-toggle="dropdown"></button>
|
3
|
+
<div class="rrf-mode dropdown-menu dropdown-menu-end py-0 rounded-0" style="font-size: .8em; min-width: 0">
|
4
|
+
<button class="dropdown-item text-end" data-rrf-mode-value="system">
|
5
|
+
System<i class="bi bi-circle-half ms-2"></i>
|
6
|
+
</button>
|
7
|
+
<button class="dropdown-item text-end" data-rrf-mode-value="light">
|
8
|
+
Light<i class="bi bi-sun-fill ms-2"></i>
|
9
|
+
</button>
|
10
|
+
<button class="dropdown-item text-end" data-rrf-mode-value="dark">
|
11
|
+
Dark<i class="bi bi-moon-stars-fill ms-2"></i>
|
12
|
+
</button>
|
13
|
+
</div>
|
14
|
+
</div>
|
@@ -0,0 +1,9 @@
|
|
1
|
+
<div style="float: right">
|
2
|
+
<% if @route_groups.values[0].any? { |r| r[:matches_path] && r[:verb] == "DELETE" && r[:action] == "destroy" } %>
|
3
|
+
<button type="button" class="btn btn-danger" onclick="rrfDelete(this)">DELETE</button>
|
4
|
+
<% end %>
|
5
|
+
<% if @route_groups.values[0].any? { |r| r[:matches_path] && r[:verb] == "OPTIONS" } %>
|
6
|
+
<button type="button" class="btn btn-primary" onclick="rrfOptions(this)">OPTIONS</button>
|
7
|
+
<% end %>
|
8
|
+
<button type="button" class="btn btn-primary" onclick="rrfGet(this)">GET</button>
|
9
|
+
</div>
|
@@ -10,7 +10,7 @@
|
|
10
10
|
<%# Render first group of routes directly. %>
|
11
11
|
<tbody>
|
12
12
|
<% @route_groups.values[0].each do |route| %>
|
13
|
-
<%= render partial: "rest_framework/route", locals: {route: route} %>
|
13
|
+
<%= render partial: "rest_framework/routes_and_forms/routes/route", locals: {route: route} %>
|
14
14
|
<% end %>
|
15
15
|
</tbody>
|
16
16
|
<%# Render any other groups under dropdowns. %>
|
@@ -20,7 +20,7 @@
|
|
20
20
|
</tr>
|
21
21
|
<tbody id="route-group-<%= index %>" class="collapse">
|
22
22
|
<% route_group.each do |route| %>
|
23
|
-
<%= render partial: "rest_framework/route", locals: {route: route} %>
|
23
|
+
<%= render partial: "rest_framework/routes_and_forms/routes/route", locals: {route: route} %>
|
24
24
|
<% end %>
|
25
25
|
</tbody>
|
26
26
|
<% end %>
|
@@ -146,6 +146,9 @@ module RESTFramework::BaseControllerMixin
|
|
146
146
|
|
147
147
|
base.extend(ClassMethods)
|
148
148
|
|
149
|
+
# By default, the layout should be set to `rest_framework`.
|
150
|
+
base.layout("rest_framework")
|
151
|
+
|
149
152
|
# Add class attributes (with defaults) unless they already exist.
|
150
153
|
RRF_BASE_CONFIG.each do |a, default|
|
151
154
|
next if base.respond_to?(a)
|
@@ -267,8 +270,8 @@ module RESTFramework::BaseControllerMixin
|
|
267
270
|
|
268
271
|
# Render a browsable API for `html` format, along with basic `json`/`xml` formats, and with
|
269
272
|
# support or passing custom `kwargs` to the underlying `render` calls.
|
270
|
-
def api_response(payload,
|
271
|
-
html_kwargs
|
273
|
+
def api_response(payload, **kwargs)
|
274
|
+
html_kwargs = kwargs.delete(:html_kwargs) || {}
|
272
275
|
json_kwargs = kwargs.delete(:json_kwargs) || {}
|
273
276
|
xml_kwargs = kwargs.delete(:xml_kwargs) || {}
|
274
277
|
|
@@ -300,12 +303,10 @@ module RESTFramework::BaseControllerMixin
|
|
300
303
|
format.xml { head(kwargs[:status] || :no_content) } if self.serialize_to_xml
|
301
304
|
else
|
302
305
|
format.json {
|
303
|
-
|
304
|
-
render(json: payload, layout: false, **jkwargs)
|
306
|
+
render(json: payload, **kwargs.merge(json_kwargs))
|
305
307
|
} if self.serialize_to_json
|
306
308
|
format.xml {
|
307
|
-
|
308
|
-
render(xml: payload, layout: false, **xkwargs)
|
309
|
+
render(xml: payload, **kwargs.merge(xml_kwargs))
|
309
310
|
} if self.serialize_to_xml
|
310
311
|
# TODO: possibly support more formats here if supported?
|
311
312
|
end
|
@@ -323,13 +324,11 @@ module RESTFramework::BaseControllerMixin
|
|
323
324
|
@route_props, @route_groups = RESTFramework::Utils.get_routes(
|
324
325
|
Rails.application.routes, request
|
325
326
|
)
|
326
|
-
hkwargs = kwargs.merge(html_kwargs)
|
327
327
|
begin
|
328
|
-
render(**
|
329
|
-
rescue ActionView::MissingTemplate
|
330
|
-
|
331
|
-
|
332
|
-
render(**hkwargs)
|
328
|
+
render(**kwargs.merge(html_kwargs))
|
329
|
+
rescue ActionView::MissingTemplate
|
330
|
+
# A view is not required, so just use `html: ""`.
|
331
|
+
render(html: "", layout: true, **kwargs.merge(html_kwargs))
|
333
332
|
end
|
334
333
|
}
|
335
334
|
end
|
@@ -2,9 +2,11 @@ class RESTFramework::Engine < Rails::Engine
|
|
2
2
|
initializer "rest_framework.assets" do
|
3
3
|
config.after_initialize do |app|
|
4
4
|
if RESTFramework.config.use_vendored_assets
|
5
|
-
app.config.assets.precompile +=
|
6
|
-
|
7
|
-
|
5
|
+
app.config.assets.precompile += [
|
6
|
+
RESTFramework::EXTERNAL_CSS_NAME,
|
7
|
+
RESTFramework::EXTERNAL_JS_NAME,
|
8
|
+
*RESTFramework::EXTERNAL_UNSUMMARIZED_ASSETS.keys.map { |name| "rest_framework/#{name}" },
|
9
|
+
]
|
8
10
|
end
|
9
11
|
end
|
10
12
|
end
|
@@ -9,15 +9,15 @@ class RESTFramework::RansackFilter < RESTFramework::BaseFilter
|
|
9
9
|
|
10
10
|
# Determine if `distinct` is determined by query param.
|
11
11
|
if distinct_query_param = @controller.ransack_distinct_query_param
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
12
|
+
if distinct_query = @controller.request.query_parameters[distinct_query_param].presence
|
13
|
+
distinct_from_query = ActiveRecord::Type::Boolean.new.cast(distinct_query)
|
14
|
+
unless distinct_from_query.nil?
|
15
|
+
distinct = distinct_from_query
|
16
|
+
end
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
|
-
return data.ransack(q, @controller.ransack_options).result(distinct: distinct)
|
20
|
+
return data.ransack(q, @controller.ransack_options || {}).result(distinct: distinct)
|
21
21
|
end
|
22
22
|
|
23
23
|
return data
|
@@ -17,12 +17,6 @@ module RESTFramework
|
|
17
17
|
rescue SystemCallError
|
18
18
|
end
|
19
19
|
|
20
|
-
# If that fails, then try to get a plain commit SHA from git.
|
21
|
-
unless skip_git
|
22
|
-
version = `git describe --dirty --always`&.strip
|
23
|
-
return "0.#{version}" unless !version || version.empty?
|
24
|
-
end
|
25
|
-
|
26
20
|
# No VERSION file, so version is unknown.
|
27
21
|
return "0.unknown"
|
28
22
|
end
|
data/lib/rest_framework.rb
CHANGED
@@ -20,6 +20,10 @@ module RESTFramework
|
|
20
20
|
destroy_all: :delete,
|
21
21
|
}.freeze
|
22
22
|
|
23
|
+
# We put most vendored external assets into these files to make precompilation and serving faster.
|
24
|
+
EXTERNAL_CSS_NAME = "rest_framework/external.min.css"
|
25
|
+
EXTERNAL_JS_NAME = "rest_framework/external.min.js"
|
26
|
+
|
23
27
|
# We should always add the `.min` extension prefix even if the assets are not minified, to avoid
|
24
28
|
# sprockets minifying the assets. We target propshaft, so we want these assets to just be passed
|
25
29
|
# through.
|
@@ -81,7 +85,8 @@ module RESTFramework
|
|
81
85
|
exclude_from_docs: true,
|
82
86
|
},
|
83
87
|
}.map { |name, cfg|
|
84
|
-
|
88
|
+
ext = File.extname(name)
|
89
|
+
if ext == ".js"
|
85
90
|
cfg[:place] = "javascripts"
|
86
91
|
cfg[:extra_tag_attrs] ||= {}
|
87
92
|
cfg[:tag_attrs] = {
|
@@ -93,7 +98,7 @@ module RESTFramework
|
|
93
98
|
**cfg[:extra_tag_attrs],
|
94
99
|
}
|
95
100
|
cfg[:tag] = ActionController::Base.helpers.tag.script(**cfg[:tag_attrs])
|
96
|
-
|
101
|
+
elsif ext == ".css"
|
97
102
|
cfg[:place] = "stylesheets"
|
98
103
|
cfg[:extra_tag_attrs] ||= {}
|
99
104
|
cfg[:tag_attrs] = {
|
@@ -104,12 +109,16 @@ module RESTFramework
|
|
104
109
|
**cfg[:extra_tag_attrs],
|
105
110
|
}
|
106
111
|
cfg[:tag] = ActionController::Base.helpers.tag.link(**cfg[:tag_attrs])
|
112
|
+
else
|
113
|
+
raise "Unknown asset extension: #{ext}."
|
107
114
|
end
|
108
115
|
|
109
116
|
[name, cfg]
|
110
117
|
}.to_h.freeze
|
111
118
|
# rubocop:enable Layout/LineLength
|
112
119
|
|
120
|
+
EXTERNAL_UNSUMMARIZED_ASSETS = EXTERNAL_ASSETS.select { |_, cfg| cfg[:extra_tag_attrs].present? }
|
121
|
+
|
113
122
|
# Global configuration should be kept minimal, as controller-level configurations allows multiple
|
114
123
|
# APIs to be defined to behave differently.
|
115
124
|
class Config
|