rest_framework 0.3.5 → 0.4.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: dc5065eb969e4616e6a0e22717a4398940b3696a43182d6e8b526e225f6c81f3
4
- data.tar.gz: 3efcfdfa6abfe7343770c8241e83d34bc1e02bcbd145826bc8a9709514b8b5f7
3
+ metadata.gz: 1e654cef83c3cf4505697e0417d637489a248b691ca157100b6a12dc3e0f3f9e
4
+ data.tar.gz: b656446d2fd724e2b91708e4df6248cd5e6676a311e8cd23d76f07951758bffd
5
5
  SHA512:
6
- metadata.gz: 170b7b9ebb18b9527d1e9216a0456af154284ab8935d1ddcc367815bf73c86379ae83340f6a259f6b4324d5c4cf32eae740a28210a1ce963427ef96a870ae016
7
- data.tar.gz: a6148d463fa2eda9dc6f19dc89646a78b922a93bdcf6f147707343d218a9501e8bebe67d8182d75a946968d59b27a0f030d08349268297799bc4886b780f6aa4
6
+ metadata.gz: 3a9ee1d172c5e33813352b2190f2f38540226d93d84bf77cca34fab326231f6215a702c66e3965f5239d652e35eeb36a7286210826608e11ab9a35c8edf65704
7
+ data.tar.gz: e132e15651e2c9fd0cd9d1338ec2c5a795d369a6a001c2e4a957c7912dfd5539ea940945ea48c011e1c4be6e3b1feaf55b63934fdff5608135c2ac089fd83486
data/LICENSE CHANGED
@@ -1,6 +1,6 @@
1
1
  The MIT License (MIT)
2
2
 
3
- Copyright (c) 2020 Gregory N. Schmit
3
+ Copyright (c) 2021 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 CHANGED
@@ -1,7 +1,7 @@
1
1
  # Rails REST Framework
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/rest_framework.svg)](https://badge.fury.io/rb/rest_framework)
4
- [![Build Status](https://travis-ci.org/gregschmit/rails-rest-framework.svg?branch=master)](https://travis-ci.org/gregschmit/rails-rest-framework)
4
+ [![Build Status](https://travis-ci.com/gregschmit/rails-rest-framework.svg?branch=master)](https://travis-ci.com/gregschmit/rails-rest-framework)
5
5
  [![Coverage Status](https://coveralls.io/repos/github/gregschmit/rails-rest-framework/badge.svg?branch=master)](https://coveralls.io/github/gregschmit/rails-rest-framework?branch=master)
6
6
  [![Maintainability](https://api.codeclimate.com/v1/badges/ba5df7706cb544d78555/maintainability)](https://codeclimate.com/github/gregschmit/rails-rest-framework/maintainability)
7
7
 
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.5
1
+ 0.4.1
@@ -29,14 +29,14 @@
29
29
  <ul class="nav nav-tabs">
30
30
  <% if @json_payload %>
31
31
  <li class="nav-item">
32
- <a class="nav-link active" href="#tab-json" data-toggle="tab" role="tab">
32
+ <a class="nav-link active" href="#tab-json" data-bs-toggle="tab" role="tab">
33
33
  .json
34
34
  </a>
35
35
  </li>
36
36
  <% end %>
37
37
  <% if @xml_payload %>
38
38
  <li class="nav-item">
39
- <a class="nav-link" href="#tab-xml" data-toggle="tab" role="tab">
39
+ <a class="nav-link" href="#tab-xml" data-bs-toggle="tab" role="tab">
40
40
  .xml
41
41
  </a>
42
42
  </li>
@@ -57,7 +57,7 @@
57
57
  </div>
58
58
  </div>
59
59
  <% end %>
60
- <% unless @routes.blank? %>
60
+ <% unless @route_groups.blank? %>
61
61
  <div class="row">
62
62
  <h2>Routes</h2>
63
63
  <%= render partial: 'rest_framework/routes' %>
@@ -1,11 +1,12 @@
1
1
  <meta charset="utf-8">
2
- <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
2
+ <meta name="viewport" content="width=device-width, initial-scale=1">
3
3
  <%= csrf_meta_tags %>
4
4
  <%= csp_meta_tag rescue nil %>
5
5
 
6
- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
7
- <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/styles/vs.min.css" integrity="sha512-aWjgJTbdG4imzxTxistV5TVNffcYGtIQQm2NBNahV6LmX14Xq9WwZTL1wPjaSglUuVzYgwrq+0EuI4+vKvQHHw==" crossorigin="anonymous" />
6
+ <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/css/bootstrap.min.css" integrity="sha384-F3w7mX95PdgyTmZZMECAngseQB83DfGTowi0iMjiWaeVhAn4FJkqJByhZMI3AhiU" crossorigin="anonymous">
7
+ <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/styles/vs.min.css" integrity="sha512-aWjgJTbdG4imzxTxistV5TVNffcYGtIQQm2NBNahV6LmX14Xq9WwZTL1wPjaSglUuVzYgwrq+0EuI4+vKvQHHw==" crossorigin="anonymous">
8
8
  <style>
9
+ /* Adjust headers to always take up their entire row, and tweak the sizing. */
9
10
  h1,h2,h3,h4,h5,h6 { width: 100%; font-weight: normal; }
10
11
  h1 { font-size: 2rem; }
11
12
  h2 { font-size: 1.7rem; }
@@ -13,11 +14,27 @@
13
14
  h4 { font-size: 1.3rem; }
14
15
  h5 { font-size: 1.1rem; }
15
16
  h6 { font-size: 1rem; }
17
+
18
+ /* Make route group expansion obvious to the user. */
19
+ .rrf-routes .rrf-route-group-header {
20
+ background-color: #f8f8f8;
21
+ }
22
+ .rrf-routes .rrf-route-group-header:hover {
23
+ background-color: #f0f0f0;
24
+ }
25
+ .rrf-routes .rrf-route-group-header td {
26
+ cursor: pointer;
27
+ }
28
+
29
+ /* Disable bootstrap's collapsing animation because in tables it causes delayed jerkiness. */
30
+ .rrf-routes .collapsing {
31
+ -webkit-transition: none;
32
+ transition: none;
33
+ display: none;
34
+ }
16
35
  </style>
17
36
 
18
- <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
19
- <script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
20
- <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
37
+ <script src="https://cdn.jsdelivr.net/npm/bootstrap@5.1.1/dist/js/bootstrap.bundle.min.js" integrity="sha384-/bQdsTh/da6pkI1MST/rWKFNjaCP5gBSY4sEBT38Q/9RBh9AH40zEOg7Hlq2THRZ" crossorigin="anonymous"></script>
21
38
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/highlight.min.js" integrity="sha512-TDKKr+IvoqZnPzc3l35hdjpHD0m+b2EC2SrLEgKDRWpxf2rFCxemkgvJ5kfU48ip+Y+m2XVKyOCD85ybtlZDmw==" crossorigin="anonymous"></script>
22
39
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/languages/json.min.js" integrity="sha512-FoN8JE+WWCdIGXAIT8KQXwpiavz0Mvjtfk7Rku3MDUNO0BDCiRMXAsSX+e+COFyZTcDb9HDgP+pM2RX12d4j+A==" crossorigin="anonymous"></script>
23
40
  <script src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/10.2.0/languages/xml.min.js" integrity="sha512-dICltIgnUP+QSJrnYGCV8943p3qSDgvcg2NU4W8IcOZP4tdrvxlXjbhIznhtVQEcXow0mOjLM0Q6/NvZsmUH4g==" crossorigin="anonymous"></script>
@@ -0,0 +1,9 @@
1
+ <tr>
2
+ <td><%= route[:path] %></td>
3
+ <td><%= route[:verb] %></td>
4
+ <% if route[:controller] && route[:action] %>
5
+ <td><%= route[:controller] %>#<%= route[:action] %></td>
6
+ <% else %>
7
+ <td><%= route[:route_app] %></td>
8
+ <% end %>
9
+ </tr>
@@ -1,18 +1,28 @@
1
- <table class="table">
2
- <thead>
3
- <tr>
4
- <th scope="col">Verb</th>
5
- <th scope="col">Path</th>
6
- <th scope="col">Action</th>
7
- </tr>
8
- </thead>
9
- <tbody>
10
- <% @routes.each do |r| %>
11
- <tr>
12
- <td><%= r[:verb] %></td>
13
- <td><%= r[:path] %></td>
14
- <td><%= r[:action] %></td>
15
- </tr>
1
+ <div class="table-responsive">
2
+ <table class="table table-responsive rrf-routes">
3
+ <thead>
4
+ <tr>
5
+ <th scope="col">Path</th>
6
+ <th scope="col">Verb</th>
7
+ <th scope="col">Controller#Action</th>
8
+ </tr>
9
+ </thead>
10
+ <%# Render first group of routes directly. %>
11
+ <tbody>
12
+ <% @route_groups.values[0].each do |route| %>
13
+ <%= render partial: "rest_framework/route", locals: {route: route} %>
14
+ <% end %>
15
+ </tbody>
16
+ <%# Render any other groups under dropdowns. %>
17
+ <% @route_groups.drop(1).each_with_index do |(name, route_group), index| %>
18
+ <tr data-bs-toggle="collapse" data-bs-target="#route-group-<%= index %>" class="rrf-route-group-header">
19
+ <td colspan="3" class="text-center user-select-none"><%= name %></td>
20
+ </tr>
21
+ <tbody id="route-group-<%= index %>" class="collapse">
22
+ <% route_group.each do |route| %>
23
+ <%= render partial: "rest_framework/route", locals: {route: route} %>
24
+ <% end %>
25
+ </tbody>
16
26
  <% end %>
17
- </tbody>
18
- </table>
27
+ </table>
28
+ </div>
@@ -1,5 +1,6 @@
1
1
  require_relative '../errors'
2
2
  require_relative '../serializers'
3
+ require_relative '../utils'
3
4
 
4
5
 
5
6
  # This module provides the common functionality for any controller mixins, a `root` action, and
@@ -121,22 +122,6 @@ module RESTFramework::BaseControllerMixin
121
122
  }, status: 406)
122
123
  end
123
124
 
124
- # Helper for showing routes under a controller action, used for the browsable API.
125
- def _get_routes
126
- begin
127
- formatter = ActionDispatch::Routing::ConsoleFormatter::Sheet
128
- rescue NameError
129
- # :nocov:
130
- formatter = ActionDispatch::Routing::ConsoleFormatter
131
- # :nocov:
132
- end
133
- return ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes).format(
134
- formatter.new
135
- ).lines.drop(1).map { |r| r.split.last(3) }.map { |r|
136
- {verb: r[0], path: r[1], action: r[2]}
137
- }.select { |r| r[:path].start_with?(request.path) }
138
- end
139
-
140
125
  # Helper to render a browsable API for `html` format, along with basic `json`/`xml` formats, and
141
126
  # with support or passing custom `kwargs` to the underlying `render` calls.
142
127
  def api_response(payload, html_kwargs: nil, **kwargs)
@@ -178,7 +163,7 @@ module RESTFramework::BaseControllerMixin
178
163
  end
179
164
  @template_logo_text ||= "Rails REST Framework"
180
165
  @title ||= self.controller_name.camelize
181
- @routes ||= self._get_routes
166
+ @route_groups ||= RESTFramework::Utils::get_routes(Rails.application.routes, request)
182
167
  hkwargs = kwargs.merge(html_kwargs)
183
168
  begin
184
169
  render(**hkwargs)
@@ -14,15 +14,3 @@ class RESTFramework::NilPassedToAPIResponseError < RESTFramework::Error
14
14
  MSG
15
15
  end
16
16
  end
17
-
18
-
19
- class RESTFramework::UnserializableError < RESTFramework::Error
20
- def initialize(object)
21
- @object = object
22
- return super
23
- end
24
-
25
- def message
26
- return "Unable to serialize `#{@object.inspect}` (of type `#{@object.class}`)."
27
- end
28
- end
@@ -1,43 +1,8 @@
1
1
  require 'action_dispatch/routing/mapper'
2
-
2
+ require_relative 'utils'
3
3
 
4
4
  module ActionDispatch::Routing
5
5
  class Mapper
6
- # Internal helper to take extra_actions hash and convert to a consistent format.
7
- protected def _parse_extra_actions(extra_actions)
8
- return (extra_actions || {}).map do |k,v|
9
- kwargs = {action: k}
10
- path = k
11
-
12
- # Convert structure to path/methods/kwargs.
13
- if v.is_a?(Hash) # allow kwargs
14
- v = v.symbolize_keys
15
-
16
- # Ensure methods is an array.
17
- if v[:methods].is_a?(String) || v[:methods].is_a?(Symbol)
18
- methods = [v.delete(:methods)]
19
- else
20
- methods = v.delete(:methods)
21
- end
22
-
23
- # Override path if it's provided.
24
- if v.key?(:path)
25
- path = v.delete(:path)
26
- end
27
-
28
- # Pass any further kwargs to the underlying Rails interface.
29
- kwargs = kwargs.merge(v)
30
- elsif v.is_a?(Symbol) || v.is_a?(String)
31
- methods = [v]
32
- else
33
- methods = v
34
- end
35
-
36
- # Return a hash with keys: :path, :methods, :kwargs.
37
- {path: path, methods: methods, kwargs: kwargs}
38
- end
39
- end
40
-
41
6
  # Internal interface to get the controller class from the name and current scope.
42
7
  protected def _get_controller_class(name, pluralize: true, fallback_reverse_pluralization: true)
43
8
  # get class name
@@ -92,13 +57,13 @@ module ActionDispatch::Routing
92
57
  if controller.is_a?(Class)
93
58
  controller_class = controller
94
59
  else
95
- controller_class = _get_controller_class(controller, pluralize: !default_singular)
60
+ controller_class = self._get_controller_class(controller, pluralize: !default_singular)
96
61
  end
97
62
 
98
63
  # Set controller if it's not explicitly set.
99
64
  kwargs[:controller] = name unless kwargs[:controller]
100
65
 
101
- # determine plural/singular resource
66
+ # Determine plural/singular resource.
102
67
  force_singular = kwargs.delete(:force_singular)
103
68
  force_plural = kwargs.delete(:force_plural)
104
69
  if force_singular
@@ -118,14 +83,16 @@ module ActionDispatch::Routing
118
83
  public_send(resource_method, name, except: skip, **kwargs) do
119
84
  if controller_class.respond_to?(:extra_member_actions)
120
85
  member do
121
- actions = self._parse_extra_actions(controller_class.extra_member_actions)
122
- _route_extra_actions(actions)
86
+ actions = RESTFramework::Utils::parse_extra_actions(
87
+ controller_class.extra_member_actions
88
+ )
89
+ self._route_extra_actions(actions)
123
90
  end
124
91
  end
125
92
 
126
93
  collection do
127
- actions = self._parse_extra_actions(controller_class.extra_actions)
128
- _route_extra_actions(actions)
94
+ actions = RESTFramework::Utils::parse_extra_actions(controller_class.extra_actions)
95
+ self._route_extra_actions(actions)
129
96
  end
130
97
 
131
98
  yield if block_given?
@@ -160,14 +127,14 @@ module ActionDispatch::Routing
160
127
  kwargs[:controller] = name unless kwargs[:controller]
161
128
 
162
129
  # Route actions using the resourceful router, but skip all builtin actions.
163
- actions = self._parse_extra_actions(controller_class.extra_actions)
130
+ actions = RESTFramework::Utils::parse_extra_actions(controller_class.extra_actions)
164
131
  public_send(:resource, name, only: [], **kwargs) do
165
132
  # Route a root for this resource.
166
133
  if route_root_to
167
134
  get '', action: route_root_to
168
135
  end
169
136
 
170
- _route_extra_actions(actions, &block)
137
+ self._route_extra_actions(actions, &block)
171
138
  end
172
139
  end
173
140
 
@@ -105,18 +105,12 @@ class RESTFramework::NativeSerializer < RESTFramework::BaseSerializer
105
105
 
106
106
  # Convert the object (record or recordset) to Ruby primitives.
107
107
  def serialize
108
- if @object
109
- begin
110
- if @object.is_a?(Enumerable)
111
- return @object.map { |r| r.serializable_hash(self.get_serializer_config) }
112
- end
113
- return @object.serializable_hash(self.get_serializer_config)
114
- rescue NoMethodError
115
- end
116
- end
108
+ raise "No object available to serialize!" unless @object
117
109
 
118
- # Raise an error if we cannot serialize the object.
119
- raise RESTFramework::UnserializableError.new(@object)
110
+ if @object.is_a?(Enumerable)
111
+ return @object.map { |r| r.serializable_hash(self.get_serializer_config) }
112
+ end
113
+ return @object.serializable_hash(self.get_serializer_config)
120
114
  end
121
115
 
122
116
  # Allow a serializer instance to be used as a hash directly in a nested serializer config.
@@ -0,0 +1,64 @@
1
+ module RESTFramework::Utils
2
+ # Helper to take extra_actions hash and convert to a consistent format:
3
+ # `{paths:, methods:, kwargs:}`.
4
+ def self.parse_extra_actions(extra_actions)
5
+ return (extra_actions || {}).map do |k,v|
6
+ kwargs = {action: k}
7
+ path = k
8
+
9
+ # Convert structure to path/methods/kwargs.
10
+ if v.is_a?(Hash) # allow kwargs
11
+ v = v.symbolize_keys
12
+
13
+ # Ensure methods is an array.
14
+ if v[:methods].is_a?(String) || v[:methods].is_a?(Symbol)
15
+ methods = [v.delete(:methods)]
16
+ else
17
+ methods = v.delete(:methods)
18
+ end
19
+
20
+ # Override path if it's provided.
21
+ if v.key?(:path)
22
+ path = v.delete(:path)
23
+ end
24
+
25
+ # Pass any further kwargs to the underlying Rails interface.
26
+ kwargs = kwargs.merge(v)
27
+ elsif v.is_a?(Symbol) || v.is_a?(String)
28
+ methods = [v]
29
+ else
30
+ methods = v
31
+ end
32
+
33
+ # Return a hash with keys: :path, :methods, :kwargs.
34
+ {path: path, methods: methods, kwargs: kwargs}
35
+ end
36
+ end
37
+
38
+ # Helper to get the current route pattern, stripped of the `(:format)` segment.
39
+ def self.get_route_pattern(application_routes, request)
40
+ application_routes.router.recognize(request) do |route, _, _|
41
+ return route.path.spec.to_s.gsub(/\(\.:format\)$/, '')
42
+ end
43
+ end
44
+
45
+ # Helper for showing routes under a controller action, used for the browsable API.
46
+ def self.get_routes(application_routes, request)
47
+ current_pattern = self.get_route_pattern(application_routes, request)
48
+ current_subdomain = request.subdomain.presence
49
+
50
+ # Return routes that match our current route subdomain/pattern, grouped by controller.
51
+ return application_routes.routes.map { |r|
52
+ {
53
+ verb: r.verb,
54
+ path: r.path.spec.to_s,
55
+ action: r.defaults[:action].presence,
56
+ controller: r.defaults[:controller].presence,
57
+ subdomain: r.defaults[:subdomain].presence,
58
+ route_app: r.app&.app&.inspect&.presence,
59
+ }
60
+ }.select { |r|
61
+ r[:subdomain] == current_subdomain && r[:path].start_with?(current_pattern)
62
+ }.group_by { |r| r[:controller] }
63
+ end
64
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rest_framework
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.3.5
4
+ version: 0.4.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregory N. Schmit
8
- autorequire:
8
+ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2021-05-07 00:00:00.000000000 Z
11
+ date: 2021-09-10 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -36,6 +36,7 @@ files:
36
36
  - VERSION
37
37
  - app/views/layouts/rest_framework.html.erb
38
38
  - app/views/rest_framework/_head.html.erb
39
+ - app/views/rest_framework/_route.html.erb
39
40
  - app/views/rest_framework/_routes.html.erb
40
41
  - lib/rest_framework.rb
41
42
  - lib/rest_framework/controller_mixins.rb
@@ -49,6 +50,7 @@ files:
49
50
  - lib/rest_framework/paginators.rb
50
51
  - lib/rest_framework/routers.rb
51
52
  - lib/rest_framework/serializers.rb
53
+ - lib/rest_framework/utils.rb
52
54
  - lib/rest_framework/version.rb
53
55
  homepage: https://rails-rest-framework.com
54
56
  licenses:
@@ -56,7 +58,7 @@ licenses:
56
58
  metadata:
57
59
  homepage_uri: https://rails-rest-framework.com
58
60
  source_code_uri: https://github.com/gregschmit/rails-rest-framework
59
- post_install_message:
61
+ post_install_message:
60
62
  rdoc_options: []
61
63
  require_paths:
62
64
  - lib
@@ -73,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
73
75
  version: '0'
74
76
  requirements: []
75
77
  rubygems_version: 3.1.4
76
- signing_key:
78
+ signing_key:
77
79
  specification_version: 4
78
80
  summary: A framework for DRY RESTful APIs in Ruby on Rails.
79
81
  test_files: []