rest_framework 0.0.16 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 825e7e7ac0e9c8ae57250288a54dc3ef6510665ce3d4fee23245c559aa8e8233
4
- data.tar.gz: 2211c303d14708ef94a4cb35d6e3b25bf78b3b08645f2990ca5448354d8dd64e
3
+ metadata.gz: 46db4e7aa05600caaa4c1f9f645f417b4d3cd9e5bcde7da0b54d3c5fa84e872e
4
+ data.tar.gz: 95c9d018b687795f80c38b43289f19ffd44eb1b170d883c164b590ab6b1c20d0
5
5
  SHA512:
6
- metadata.gz: 0ee2cf406f2b8d77d9ea63650b080d037a759143e0a3e19846585d493a386a4647db0fe59188aa0fd887257a18087aaca82b80d99dee962af1dfdb7eca66a07c
7
- data.tar.gz: 6248caea5ad7f5a37a55f7da6aae55c70dc284b9f04d046fc6149a13dff4ae34410106c97f54274f59a8353c79fe97073b7dcba51d65d9c94eb0f9cff1a205ac
6
+ metadata.gz: 2c376d191ffa5ae9de932dceb8411362a00be789ff9aa3733f038608da890fc5437d981576e3b17d402b857f7966cb15e437d7cbe2c8447191088a9a2249134f
7
+ data.tar.gz: 72e31acb2e66c6d8d2af2dd7375e7732a93b5e66b1c1fedf4c1d781421422c582958d32c6022305cd9cc2ca9dda51e2c2f6c540b1737e11eb3506501ef91b618
data/README.md CHANGED
@@ -117,4 +117,5 @@ $ rake test
117
117
  ```
118
118
 
119
119
  To interact with the test app, `cd test` and operate it via the normal Rails interfaces. Ensure you
120
- run `rake db:schema:load` before running `rails server` or `rails console`.
120
+ run `rake db:schema:load` before running `rails server` or `rails console`. You can also load the
121
+ test fixtures with `rake db:fixtures:load`.
@@ -1 +1 @@
1
- 0.0.16
1
+ 0.1.0
@@ -36,8 +36,6 @@ module RESTFramework
36
36
  extra_actions: nil,
37
37
  extra_member_actions: nil,
38
38
  filter_backends: nil,
39
- native_serializer_config: nil,
40
- native_serializer_action_config: nil,
41
39
  paginator_class: nil,
42
40
  page_size: nil,
43
41
  page_query_param: 'page',
@@ -77,17 +75,12 @@ module RESTFramework
77
75
 
78
76
  # Helper to get filtering backends with a sane default.
79
77
  def get_filter_backends
80
- if self.class.filter_backends
81
- return self.class.filter_backends
82
- end
83
-
84
- # By default, return nil.
85
- return nil
78
+ return self.class.filter_backends || []
86
79
  end
87
80
 
88
81
  # Filter the recordset over all configured filter backends.
89
82
  def get_filtered_data(data)
90
- (self.get_filter_backends || []).each do |filter_class|
83
+ self.get_filter_backends.each do |filter_class|
91
84
  filter = filter_class.new(controller: self)
92
85
  data = filter.get_filtered_data(data)
93
86
  end
@@ -95,9 +88,9 @@ module RESTFramework
95
88
  return data
96
89
  end
97
90
 
98
- # Helper to get the configured serializer class, or `NativeModelSerializer` as a default.
91
+ # Helper to get the configured serializer class.
99
92
  def get_serializer_class
100
- return self.class.serializer_class || NativeModelSerializer
93
+ return self.class.serializer_class
101
94
  end
102
95
 
103
96
  # Get a native serializer config for the current action.
@@ -23,6 +23,10 @@ module RESTFramework
23
23
  fields: nil,
24
24
  action_fields: nil,
25
25
 
26
+ # Attributes for the default native serializer.
27
+ native_serializer_config: nil,
28
+ native_serializer_action_config: nil,
29
+
26
30
  # Attributes for default model filtering (and ordering).
27
31
  filterset_fields: nil,
28
32
  ordering_fields: nil,
@@ -44,6 +48,11 @@ module RESTFramework
44
48
 
45
49
  protected
46
50
 
51
+ # Helper to get the configured serializer class, or `NativeModelSerializer` as a default.
52
+ def get_serializer_class
53
+ return self.class.serializer_class || RESTFramework::NativeModelSerializer
54
+ end
55
+
47
56
  # Get a list of parameters allowed for the current action.
48
57
  def get_allowed_parameters
49
58
  allowed_action_parameters = self.class.allowed_action_parameters || {}
@@ -57,11 +66,9 @@ module RESTFramework
57
66
 
58
67
  # Get the list of filtering backends to use.
59
68
  def get_filter_backends
60
- backends = super
61
- return backends if backends
62
-
63
- # By default, return the standard model filter backend.
64
- return [RESTFramework::ModelFilter, RESTFramework::ModelOrderingFilter]
69
+ return self.class.filter_backends || [
70
+ RESTFramework::ModelFilter, RESTFramework::ModelOrderingFilter
71
+ ]
65
72
  end
66
73
 
67
74
  # Get a list of fields for the current action.
@@ -76,14 +83,14 @@ module RESTFramework
76
83
  end
77
84
 
78
85
  # Filter the request body for keys in current action's allowed_parameters/fields config.
79
- def _get_parameter_values_from_request_body
86
+ def get_body_params
80
87
  fields = self.get_allowed_parameters || self.get_fields
81
- return @_get_parameter_values_from_request_body ||= (request.request_parameters.select { |p|
88
+ return @get_body_params ||= (request.request_parameters.select { |p|
82
89
  fields.include?(p.to_sym) || fields.include?(p.to_s)
83
90
  })
84
91
  end
85
- alias :get_create_params :_get_parameter_values_from_request_body
86
- alias :get_update_params :_get_parameter_values_from_request_body
92
+ alias :get_create_params :get_body_params
93
+ alias :get_update_params :get_body_params
87
94
 
88
95
  # Get a record by `id` or return a single record if recordset is filtered down to a single
89
96
  # record.
@@ -11,7 +11,7 @@ module RESTFramework
11
11
  @page_size = self._page_size
12
12
 
13
13
  @total_pages = @count / @page_size
14
- @total_pages += 1 if @count % @page_size
14
+ @total_pages += 1 if (@count % @page_size != 0)
15
15
  end
16
16
 
17
17
  def _page_size
@@ -2,6 +2,41 @@ require 'action_dispatch/routing/mapper'
2
2
 
3
3
  module ActionDispatch::Routing
4
4
  class Mapper
5
+ # Helper to take extra_actions hash and convert to a consistent format.
6
+ protected def _parse_extra_actions(extra_actions)
7
+ return (extra_actions || {}).map do |k,v|
8
+ kwargs = {}
9
+ path = k
10
+
11
+ # Convert structure to path/methods/kwargs.
12
+ if v.is_a?(Hash) # allow kwargs
13
+ v = v.symbolize_keys
14
+
15
+ # Ensure methods is an array.
16
+ if v[:methods].is_a?(String) || v[:methods].is_a?(Symbol)
17
+ methods = [v.delete(:methods)]
18
+ else
19
+ methods = v.delete(:methods)
20
+ end
21
+
22
+ # Override path if it's provided.
23
+ if v.key?(:path)
24
+ path = v.delete(:path)
25
+ end
26
+
27
+ # Pass any further kwargs to the underlying Rails interface.
28
+ kwargs = kwargs.merge(v)
29
+ elsif v.is_a?(Symbol) || v.is_a?(String)
30
+ methods = [v]
31
+ else
32
+ methods = v
33
+ end
34
+
35
+ # Return a hash with keys: :path, :methods, :kwargs.
36
+ {path: path, methods: methods, kwargs: kwargs}
37
+ end
38
+ end
39
+
5
40
  # Private interface to get the controller class from the name and current scope.
6
41
  protected def _get_controller_class(name, pluralize: true, fallback_reverse_pluralization: true)
7
42
  # get class name
@@ -40,16 +75,16 @@ module ActionDispatch::Routing
40
75
  # @param default_singular [Boolean] the default plurality of the resource if the plurality is
41
76
  # not otherwise defined by the controller
42
77
  # @param name [Symbol] the resource name, from which path and controller are deduced by default
43
- # @param skip_undefined [Boolean] whether we should skip routing undefined actions
78
+ # @param skip_undefined [Boolean] whether we should skip routing undefined resourceful actions
44
79
  protected def _rest_resources(default_singular, name, skip_undefined: true, **kwargs, &block)
45
- controller = kwargs[:controller] || name
80
+ controller = kwargs.delete(:controller) || name
46
81
  if controller.is_a?(Class)
47
82
  controller_class = controller
48
83
  else
49
84
  controller_class = _get_controller_class(controller, pluralize: !default_singular)
50
85
  end
51
86
 
52
- # set controller if it's not explicitly set
87
+ # Set controller if it's not explicitly set.
53
88
  kwargs[:controller] = name unless kwargs[:controller]
54
89
 
55
90
  # determine plural/singular resource
@@ -70,25 +105,20 @@ module ActionDispatch::Routing
70
105
  public_send(resource_method, name, except: skip, **kwargs) do
71
106
  if controller_class.respond_to?(:extra_member_actions)
72
107
  member do
73
- actions = controller_class.extra_member_actions || {}
74
- actions = actions.select { |k,v| controller_class.method_defined?(k) } if skip_undefined
75
- actions.each do |action, methods|
76
- methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
77
- methods.each do |m|
78
- public_send(m, action)
108
+ actions = self._parse_extra_actions(controller_class.extra_member_actions)
109
+ actions.each do |action_config|
110
+ action_config[:methods].each do |m|
111
+ public_send(m, action_config[:path], **action_config[:kwargs])
79
112
  end
80
113
  end
81
114
  end
82
115
  end
83
116
 
84
117
  collection do
85
- actions = controller_class.extra_actions || {}
86
- actions = actions.select { |k,v| controller_class.method_defined?(k) } if skip_undefined
87
- actions.reject! { |k,v| skip.include? k }
88
- actions.each do |action, methods|
89
- methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
90
- methods.each do |m|
91
- public_send(m, action)
118
+ actions = self._parse_extra_actions(controller_class.extra_actions)
119
+ actions.each do |action_config|
120
+ action_config[:methods].each do |m|
121
+ public_send(m, action_config[:path], **action_config[:kwargs])
92
122
  end
93
123
  end
94
124
  end
@@ -112,42 +142,55 @@ module ActionDispatch::Routing
112
142
  end
113
143
 
114
144
  # Route a controller without the default resourceful paths.
115
- def rest_route(path=nil, skip_undefined: true, **kwargs, &block)
116
- controller = kwargs.delete(:controller) || path
117
- path = path.to_s
145
+ def rest_route(name=nil, **kwargs, &block)
146
+ controller = kwargs.delete(:controller) || name
147
+ if controller.is_a?(Class)
148
+ controller_class = controller
149
+ else
150
+ controller_class = self._get_controller_class(controller, pluralize: false)
151
+ end
118
152
 
119
- # route actions
120
- controller_class = self._get_controller_class(controller, pluralize: false)
121
- skip = controller_class.get_skip_actions(skip_undefined: skip_undefined)
122
- actions = controller_class.extra_actions || {}
123
- actions = actions.select { |k,v| controller_class.method_defined?(k) } if skip_undefined
124
- actions.reject! { |k,v| skip.include? k }
125
- actions.each do |action, methods|
126
- methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
127
- methods.each do |m|
128
- public_send(m, File.join(path, action.to_s), controller: controller, action: action)
153
+ # Set controller if it's not explicitly set.
154
+ kwargs[:controller] = name unless kwargs[:controller]
155
+
156
+ # Route actions using the resourceful router, but skip all builtin actions.
157
+ actions = self._parse_extra_actions(controller_class.extra_actions)
158
+ public_send(:resource, name, only: [], **kwargs) do
159
+ actions.each do |action_config|
160
+ action_config[:methods].each do |m|
161
+ public_send(m, action_config[:path], **action_config[:kwargs])
162
+ end
163
+ yield if block_given?
129
164
  end
130
- yield if block_given?
131
165
  end
132
166
  end
133
167
 
134
168
  # Route a controller's `#root` to '/' in the current scope/namespace, along with other actions.
135
169
  # @param label [Symbol] the snake_case name of the controller
136
- def rest_root(path=nil, **kwargs, &block)
137
- # by default, use RootController#root
170
+ def rest_root(name=nil, **kwargs, &block)
171
+ # By default, use RootController#root.
138
172
  root_action = kwargs.delete(:action) || :root
139
- controller = kwargs.delete(:controller) || path || :root
140
- path = path.to_s
173
+ controller = kwargs.delete(:controller) || name || :root
141
174
 
142
- # route the root
143
- get path, controller: controller, action: root_action
175
+ # Route the root.
176
+ get name.to_s, controller: controller, action: root_action
144
177
 
145
- # route any additional actions
178
+ # Route any additional actions.
146
179
  controller_class = self._get_controller_class(controller, pluralize: false)
147
- (controller_class.extra_actions || {}).each do |action, methods|
148
- methods = [methods] if methods.is_a?(Symbol) || methods.is_a?(String)
149
- methods.each do |m|
150
- public_send(m, File.join(path, action.to_s), controller: controller, action: action)
180
+ actions = self._parse_extra_actions(controller_class.extra_actions)
181
+ actions.each do |action_config|
182
+ # Add :action unless kwargs defines it.
183
+ unless action_config[:kwargs].key?(:action)
184
+ action_config[:kwargs][:action] = action_config[:path]
185
+ end
186
+
187
+ action_config[:methods].each do |m|
188
+ public_send(
189
+ m,
190
+ File.join(name.to_s, action_config[:path].to_s),
191
+ controller: controller,
192
+ **action_config[:kwargs],
193
+ )
151
194
  end
152
195
  yield if block_given?
153
196
  end
@@ -8,18 +8,25 @@ module RESTFramework
8
8
  end
9
9
  end
10
10
 
11
- # This serializer uses `.as_json` to serialize objects. Despite the name, `.as_json` is a Rails
12
- # method which converts objects to Ruby primitives (with the top-level being either an array or a
13
- # hash).
14
- class NativeSerializer < BaseSerializer
11
+ # This serializer uses `.as_json` to serialize objects. Despite the name, `.as_json` is an
12
+ # `ActiveModel` method which converts objects to Ruby primitives (with the top-level being either
13
+ # an array or a hash).
14
+ class NativeModelSerializer < BaseSerializer
15
15
  class_attribute :config
16
16
  class_attribute :singular_config
17
17
  class_attribute :plural_config
18
18
  class_attribute :action_config
19
19
 
20
- def initialize(many: nil, **kwargs)
20
+ def initialize(many: nil, model: nil, **kwargs)
21
21
  super(**kwargs)
22
- @many = many
22
+
23
+ if many.nil?
24
+ @many = @object.respond_to?(:count) ? @object.count : nil
25
+ else
26
+ @many = many
27
+ end
28
+
29
+ @model = model || (@controller ? @controller.send(:get_model) : nil)
23
30
  end
24
31
 
25
32
  # Get controller action, if possible.
@@ -58,6 +65,13 @@ module RESTFramework
58
65
  return serializer_config
59
66
  end
60
67
 
68
+ # If the config wasn't determined, build a serializer config from model fields.
69
+ fields = @controller.try(:get_fields) if @controller
70
+ unless fields.blank?
71
+ columns, methods = fields.partition { |f| f.to_s.in?(@model.column_names) }
72
+ return {only: columns, methods: methods}
73
+ end
74
+
61
75
  return {}
62
76
  end
63
77
 
@@ -99,27 +113,4 @@ module RESTFramework
99
113
  end
100
114
  end
101
115
 
102
- # `NativeModelSerializer` is similar to `NativeSerializer` but with some customizations to work
103
- # with `ActiveModel`.
104
- class NativeModelSerializer < NativeSerializer
105
- def initialize(model: nil, **kwargs)
106
- super(**kwargs)
107
- @model = model || (@controller ? @controller.send(:get_model) : nil)
108
- end
109
-
110
- # Get a configuration passable to `as_json` for the object.
111
- def get_serializer_config
112
- config = super
113
- return config unless config.blank?
114
-
115
- # If the config wasn't determined, build a serializer config from model fields.
116
- fields = @controller.try(:get_fields) if @controller
117
- unless fields.blank?
118
- columns, methods = fields.partition { |f| f.to_s.in?(@model.column_names) }
119
- return {only: columns, methods: methods}
120
- end
121
-
122
- return {}
123
- end
124
- end
125
116
  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.16
4
+ version: 0.1.0
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: 2021-02-07 00:00:00.000000000 Z
11
+ date: 2021-02-28 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -48,11 +48,11 @@ files:
48
48
  - lib/rest_framework/routers.rb
49
49
  - lib/rest_framework/serializers.rb
50
50
  - lib/rest_framework/version.rb
51
- homepage: https://github.com/gregschmit/rails-rest-framework
51
+ homepage: https://rails-rest-framework.com
52
52
  licenses:
53
53
  - MIT
54
54
  metadata:
55
- homepage_uri: https://github.com/gregschmit/rails-rest-framework
55
+ homepage_uri: https://rails-rest-framework.com
56
56
  source_code_uri: https://github.com/gregschmit/rails-rest-framework
57
57
  post_install_message:
58
58
  rdoc_options: []
@@ -70,7 +70,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
70
70
  - !ruby/object:Gem::Version
71
71
  version: '0'
72
72
  requirements: []
73
- rubygems_version: 3.0.8
73
+ rubygems_version: 3.0.9
74
74
  signing_key:
75
75
  specification_version: 4
76
76
  summary: A framework for DRY RESTful APIs in Ruby on Rails.