rest_framework 0.0.8 → 0.0.14

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: f0a9ae17435876f34d868d88ea187ae8844593a498f6d2d560c3ab2cfe1fa37a
4
- data.tar.gz: ea04580ad618ed1e15f28cb29ed079e64beead85d77479a52896c10aed226bc8
3
+ metadata.gz: ab8e500690ee54da42755e6243047dcc2cd78706c96dae29e18510aef2f9829a
4
+ data.tar.gz: 9e8c0990b2bf175effea734f306a806de6094984b6dca7cf2899c9c6e77bcc5a
5
5
  SHA512:
6
- metadata.gz: 3b596fb77e6bf656ce0fd7613ed2498019670b8576b022f6bda349d4f945d1502a2704bffb3d82a8cf2910ee0779f8fbcf2abae69bbd90e7734d59af1f2a8323
7
- data.tar.gz: 9c11d18a0805d17adb55b15d2e5b75e563c7e065bf0734e330c2584991ba0301a542466d9ee5d87387ecd97848451656c0740fa5488d77cd3f187b1f8988aacb
6
+ metadata.gz: 730b8dcf9e9febb6d6adee7672a3bb1d8458498b6c17b1ec483878a5b8d28638a11f15c71745d9ba06d2eb41e64834a7e591390da3d5d64e1daa30b5244046b3
7
+ data.tar.gz: 544814fbe3bc83bdd6661346bae020ce8f74a0ea8edab9180d88654e09d51b458f5eed5732916c58aff9961da6b6224776d9bc6aff9d01b6519ab0cfe5e2641c
@@ -19,7 +19,7 @@
19
19
  <div class="container py-3">
20
20
  <div class="container">
21
21
  <div class="row">
22
- <h1><%= @title %></h1>
22
+ <h1><%= (@header_text if defined? @header_text) || @title %></h1>
23
23
  </div>
24
24
  <hr/>
25
25
  <% if @json_payload || @xml_payload %>
@@ -46,7 +46,7 @@
46
46
  <div class="tab-content w-100 pt-3">
47
47
  <div class="tab-pane fade show active" id="tab-json" role="tab">
48
48
  <% if @json_payload %>
49
- <div><pre><code class="language-json"><%= JSON.pretty_generate(JSON.parse(@json_payload)) %></code></pre></div>
49
+ <div><pre><code class="language-json"><%= JSON.pretty_generate(JSON.parse(@json_payload)) unless @json_payload == '' %></code></pre></div>
50
50
  <% end %>
51
51
  </div>
52
52
  <div class="tab-pane fade" id="tab-xml" role="tab">
@@ -1 +1 @@
1
- 0.0.8
1
+ 0.0.14
@@ -34,8 +34,15 @@ module RESTFramework
34
34
  :skip_actions,
35
35
  :paginator_class,
36
36
  ])
37
+
38
+ # skip csrf since this is an API
39
+ base.skip_before_action(:verify_authenticity_token) rescue nil
40
+
41
+ # handle some common exceptions
37
42
  base.rescue_from(ActiveRecord::RecordNotFound, with: :record_not_found)
38
43
  base.rescue_from(ActiveRecord::RecordInvalid, with: :record_invalid)
44
+ base.rescue_from(ActiveRecord::RecordNotSaved, with: :record_not_saved)
45
+ base.rescue_from(ActiveRecord::RecordNotDestroyed, with: :record_not_destroyed)
39
46
  end
40
47
  end
41
48
 
@@ -51,6 +58,14 @@ module RESTFramework
51
58
  return api_response({message: "Record not found.", exception: e}, status: 404)
52
59
  end
53
60
 
61
+ def record_not_saved(e)
62
+ return api_response({message: "Record not saved.", exception: e}, status: 406)
63
+ end
64
+
65
+ def record_not_destroyed(e)
66
+ return api_response({message: "Record not destroyed.", exception: e}, status: 406)
67
+ end
68
+
54
69
  def _get_routes
55
70
  begin
56
71
  formatter = ActionDispatch::Routing::ConsoleFormatter::Sheet
@@ -59,42 +74,55 @@ module RESTFramework
59
74
  end
60
75
  return ActionDispatch::Routing::RoutesInspector.new(Rails.application.routes.routes).format(
61
76
  formatter.new
62
- ).lines[1..].map { |r| r.split.last(3) }.map { |r|
77
+ ).lines.drop(1).map { |r| r.split.last(3) }.map { |r|
63
78
  {verb: r[0], path: r[1], action: r[2]}
64
79
  }.select { |r| r[:path].start_with?(request.path) }
65
80
  end
66
81
 
67
- # Helper alias for `respond_to`/`render`, and replace nil responses with blank ones. `payload`
68
- # must be already serialized to Ruby primitives.
82
+ # Helper alias for `respond_to`/`render`. `payload` should be already serialized to Ruby
83
+ # primitives.
69
84
  def api_response(payload, html_kwargs: nil, json_kwargs: nil, xml_kwargs: nil, **kwargs)
70
85
  html_kwargs ||= {}
71
86
  json_kwargs ||= {}
72
87
  xml_kwargs ||= {}
73
88
 
89
+ # allow blank (no-content) responses
90
+ @blank = kwargs[:blank]
91
+
74
92
  respond_to do |format|
75
- if payload.respond_to?(:to_json)
76
- format.json {
77
- kwargs = kwargs.merge(json_kwargs)
78
- render(json: payload || '', **kwargs)
79
- }
80
- end
81
- if payload.respond_to?(:to_xml)
82
- format.xml {
83
- kwargs = kwargs.merge(xml_kwargs)
84
- render(xml: payload || '', **kwargs)
85
- }
93
+ if @blank
94
+ format.json {head :no_content}
95
+ format.xml {head :no_content}
96
+ else
97
+ if payload.respond_to?(:to_json)
98
+ format.json {
99
+ kwargs = kwargs.merge(json_kwargs)
100
+ render(json: payload, layout: false, **kwargs)
101
+ }
102
+ end
103
+ if payload.respond_to?(:to_xml)
104
+ format.xml {
105
+ kwargs = kwargs.merge(xml_kwargs)
106
+ render(xml: payload, layout: false, **kwargs)
107
+ }
108
+ end
86
109
  end
87
110
  format.html {
88
111
  @payload = payload
89
- @json_payload = payload.to_json
90
- @xml_payload = payload.to_xml
112
+ @json_payload = ''
113
+ @xml_payload = ''
114
+ unless @blank
115
+ @json_payload = payload.to_json if payload.respond_to?(:to_json)
116
+ @xml_payload = payload.to_xml if payload.respond_to?(:to_xml)
117
+ end
91
118
  @template_logo_text ||= "Rails REST Framework"
92
119
  @title ||= self.controller_name.camelize
93
120
  @routes ||= self._get_routes
94
121
  kwargs = kwargs.merge(html_kwargs)
95
122
  begin
96
123
  render(**kwargs)
97
- rescue ActionView::MissingTemplate # fallback to rest_framework default view
124
+ rescue ActionView::MissingTemplate # fallback to rest_framework layout/view
125
+ kwargs[:layout] = "rest_framework"
98
126
  kwargs[:template] = "rest_framework/default"
99
127
  end
100
128
  render(**kwargs)
@@ -13,6 +13,8 @@ module RESTFramework
13
13
  :recordset,
14
14
  :fields,
15
15
  :action_fields,
16
+ :native_serializer_config,
17
+ :native_serializer_action_config,
16
18
  :filterset_fields,
17
19
  :allowed_parameters,
18
20
  :allowed_action_parameters,
@@ -29,36 +31,43 @@ module RESTFramework
29
31
  return self.class.serializer_class || NativeModelSerializer
30
32
  end
31
33
 
32
- # Get a list of fields for an action (or the current action if none given).
33
- def get_fields(action: nil)
34
+ # Get a list of fields for the current action.
35
+ def get_fields
34
36
  action_fields = self.class.action_fields || {}
35
-
36
- # action will, by default, be the current action name
37
- action = action_name.to_sym unless action
37
+ action = self.action_name.to_sym
38
38
 
39
39
  # index action should use :list fields if :index is not provided
40
40
  action = :list if action == :index && !action_fields.key?(:index)
41
41
 
42
- return action_fields[action] || self.class.fields || []
42
+ return (action_fields[action] if action) || self.class.fields || []
43
43
  end
44
44
 
45
- # Get a list of parameters allowed for an action (or the current action if none given).
46
- def get_allowed_parameters(action: nil)
47
- allowed_action_parameters = self.class.allowed_action_parameters || {}
45
+ # Get a native serializer config for the current action.
46
+ def get_native_serializer_config
47
+ action_serializer_config = self.class.native_serializer_action_config || {}
48
+ action = self.action_name.to_sym
48
49
 
49
- # action will, by default, be the current action name
50
- action = action_name.to_sym unless action
50
+ # index action should use :list serializer config if :index is not provided
51
+ action = :list if action == :index && !action_serializer_config.key?(:index)
52
+
53
+ return (action_serializer_config[action] if action) || self.class.native_serializer_config
54
+ end
55
+
56
+ # Get a list of parameters allowed for the current action.
57
+ def get_allowed_parameters
58
+ allowed_action_parameters = self.class.allowed_action_parameters || {}
59
+ action = self.action_name.to_sym
51
60
 
52
61
  # index action should use :list allowed parameters if :index is not provided
53
62
  action = :list if action == :index && !allowed_action_parameters.key?(:index)
54
63
 
55
- return allowed_action_parameters[action] || self.class.allowed_parameters
64
+ return (allowed_action_parameters[action] if action) || self.class.allowed_parameters
56
65
  end
57
66
 
58
67
  # Filter the request body for keys in current action's allowed_parameters/fields config.
59
68
  def _get_parameter_values_from_request_body
60
69
  fields = self.get_allowed_parameters || self.get_fields
61
- return @_get_field_values_from_request_body ||= (request.request_parameters.select { |p|
70
+ return @_get_parameter_values_from_request_body ||= (request.request_parameters.select { |p|
62
71
  fields.include?(p.to_sym) || fields.include?(p.to_s)
63
72
  })
64
73
  end
@@ -68,7 +77,7 @@ module RESTFramework
68
77
  # Filter params for keys allowed by the current action's filterset_fields/fields config.
69
78
  def _get_filterset_values_from_params
70
79
  fields = self.filterset_fields || self.get_fields
71
- return @_get_field_values_from_params ||= request.query_parameters.select { |p|
80
+ return @_get_filterset_values_from_params ||= request.query_parameters.select { |p|
72
81
  fields.include?(p.to_sym) || fields.include?(p.to_s)
73
82
  }
74
83
  end
@@ -178,12 +187,8 @@ module RESTFramework
178
187
  module DestroyModelMixin
179
188
  def destroy
180
189
  @record = self.get_record
181
- if @record
182
- @record.destroy!
183
- api_response('')
184
- else
185
- api_response({detail: "Method 'DELETE' not allowed."}, status: 405)
186
- end
190
+ @record.destroy!
191
+ api_response(nil)
187
192
  end
188
193
  end
189
194
 
@@ -7,34 +7,102 @@ module RESTFramework
7
7
  @data = data
8
8
  @controller = controller
9
9
  end
10
-
11
- def is_valid
12
- return true
13
- end
14
10
  end
15
11
 
16
12
  # This serializer uses `.as_json` to serialize objects. Despite the name, `.as_json` is a Rails
17
13
  # method which converts objects to Ruby primitives (with the top-level being either an array or a
18
14
  # hash).
19
15
  class NativeModelSerializer < BaseSerializer
20
- def initialize(model: nil, **kwargs)
16
+ class_attribute :config
17
+ class_attribute :singular_config
18
+ class_attribute :plural_config
19
+ class_attribute :action_config
20
+
21
+ def initialize(model: nil, many: nil, **kwargs)
21
22
  super(**kwargs)
22
- @model = model || @controller.send(:get_model)
23
+ @many = many
24
+ @model = model || (@controller ? @controller.send(:get_model) : nil)
25
+ end
26
+
27
+ # Get controller action, if possible.
28
+ def get_action
29
+ return @controller&.action_name&.to_sym
30
+ end
31
+
32
+ # Get a locally defined configuration, if one is defined.
33
+ def get_local_serializer_config
34
+ action = self.get_action
35
+
36
+ if action && self.action_config
37
+ # index action should use :list serializer config if :index is not provided
38
+ action = :list if action == :index && !self.action_config.key?(:index)
39
+
40
+ return self.action_config[action] if self.action_config[action]
41
+ end
42
+
43
+ # no action_config, so try singular/plural config
44
+ return self.plural_config if @many && self.plural_config
45
+ return self.singular_config if !@many && self.singular_config
46
+
47
+ # lastly, try the default config
48
+ return self.config
23
49
  end
24
50
 
25
51
  # Get a configuration passable to `as_json` for the model.
26
- def get_native_serializer_config
27
- fields = @controller.send(:get_fields)
52
+ def get_serializer_config
53
+ # return a locally defined serializer config if one is defined
54
+ local_config = self.get_local_serializer_config
55
+ return local_config if local_config
56
+
57
+ # return a serializer config if one is defined
58
+ serializer_config = @controller.send(:get_native_serializer_config)
59
+ return serializer_config if serializer_config
60
+
61
+ # otherwise, build a serializer config from fields
62
+ fields = @controller.send(:get_fields) if @controller
28
63
  unless fields.blank?
29
64
  columns, methods = fields.partition { |f| f.to_s.in?(@model.column_names) }
30
65
  return {only: columns, methods: methods}
31
66
  end
67
+
32
68
  return {}
33
69
  end
34
70
 
35
71
  # Convert the object(s) to Ruby primitives.
36
72
  def serialize
37
- return @object.as_json(self.get_native_serializer_config)
73
+ if @object
74
+ @many = @object.respond_to?(:each) if @many.nil?
75
+ return @object.as_json(self.get_serializer_config)
76
+ end
77
+ return nil
78
+ end
79
+
80
+ # Allow a serializer instance to be used as a hash directly in a nested serializer config.
81
+ def [](key)
82
+ unless instance_variable_defined?(:@_nested_config)
83
+ @_nested_config = self.get_serializer_config
84
+ end
85
+ return @_nested_config[key]
86
+ end
87
+ def []=(key, value)
88
+ unless instance_variable_defined?(:@_nested_config)
89
+ @_nested_config = self.get_serializer_config
90
+ end
91
+ return @_nested_config[key] = value
92
+ end
93
+
94
+ # Allow a serializer class to be used as a hash directly in a nested serializer config.
95
+ def self.[](key)
96
+ unless instance_variable_defined?(:@_nested_config)
97
+ @_nested_config = self.new.get_serializer_config
98
+ end
99
+ return @_nested_config[key]
100
+ end
101
+ def self.[]=(key, value)
102
+ unless instance_variable_defined?(:@_nested_config)
103
+ @_nested_config = self.new.get_serializer_config
104
+ end
105
+ return @_nested_config[key] = value
38
106
  end
39
107
  end
40
108
  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.0.8
4
+ version: 0.0.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Gregory N. Schmit
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-10-06 00:00:00.000000000 Z
11
+ date: 2020-10-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails