restful_json 4.1.0 → 4.2.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 +8 -8
- data/README.md +38 -20
- data/lib/restful_json/config.rb +24 -20
- data/lib/restful_json/controller.rb +32 -8
- data/lib/restful_json/version.rb +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
OTZiNzMzYTllNTRkNGQ1N2I1ZjYyOWM4ZDJlZjI3MWQ4ZDMzMTg4Yg==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
NTRiMGMwZjRmZjllYTJhNTUxZDdhYWQ0ZTIzM2U2OTY0MmJkZTkzZA==
|
7
7
|
!binary "U0hBNTEy":
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ODZmNGI1MDljOGM4YTRhZmY1OTU5MjAyYzRmZGY5ZGNhZjdmMGJkZTE3OTE0
|
10
|
+
M2M5M2FjMzAxYTMwNDJhMzhlMDY0YWMyNDZmMDk0N2JmNjI5MTg5NDUwMmM5
|
11
|
+
NDU0YWZmOTA0NjMyNTE1MmY3MWU1NGNiNzlkZTk2YjUyNWU1MDk=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
ZmMwNjgxMDI1ZDhhNjc0YzA3YzUyNDJlZjI0NDZiYTZhYzg0MjJhYTIwNTIx
|
14
|
+
YTEwZWNiYzcwOGVmNTcxYWY1ODc1ODc5NDQ3NzY5YTY0YTAxYmQ5Y2UxZjNk
|
15
|
+
ZjM5OWEwZjIzODk4MDc1MmExM2RjMDQ1NzdiNzZjMzNmNmRlMmY=
|
data/README.md
CHANGED
@@ -252,40 +252,40 @@ or in bulk, like:
|
|
252
252
|
|
253
253
|
```ruby
|
254
254
|
RestfulJson.configure do
|
255
|
-
|
255
|
+
|
256
256
|
# default for :using in can_filter_by
|
257
257
|
self.can_filter_by_default_using = [:eq]
|
258
|
-
|
258
|
+
|
259
259
|
# to log debug info during request handling
|
260
260
|
self.debug = false
|
261
|
-
|
261
|
+
|
262
262
|
# delimiter for values in request parameter values
|
263
263
|
self.filter_split = ','.freeze
|
264
|
-
|
264
|
+
|
265
265
|
# equivalent to specifying respond_to :json, :html in the controller, and can be overriden in the controller. Note that by default responders gem sets respond_to :html in application_controller.rb.
|
266
266
|
self.formats = :json, :html
|
267
|
-
|
267
|
+
|
268
268
|
# default number of records to return if using the page request function
|
269
269
|
self.number_of_records_in_a_page = 15
|
270
|
-
|
270
|
+
|
271
271
|
# delimiter for ARel predicate in the request parameter name
|
272
272
|
self.predicate_prefix = '!'.freeze
|
273
|
-
|
273
|
+
|
274
274
|
# if true, will render resource and HTTP 201 for post/create or resource and HTTP 200 for put/update. ignored if render_enabled is false.
|
275
275
|
self.return_resource = false
|
276
|
-
|
276
|
+
|
277
277
|
# if false, controller actions will just set instance variable and return it instead of calling setting instance variable and then calling render/respond_with
|
278
278
|
self.render_enabled = true
|
279
|
-
|
279
|
+
|
280
280
|
# use Permitters
|
281
281
|
self.use_permitters = true
|
282
|
-
|
282
|
+
|
283
283
|
# instead of using Rails default respond_with, explicitly define render in respond_with block
|
284
284
|
self.avoid_respond_with = true
|
285
|
-
|
285
|
+
|
286
286
|
# use the permitter_class for create and update, if use_permitters = true
|
287
287
|
self.action_to_permitter = {create: nil, update: nil}
|
288
|
-
|
288
|
+
|
289
289
|
# the methods that call authorize! action_sym, @model_class
|
290
290
|
self.actions_that_authorize = [:create, :update]
|
291
291
|
|
@@ -294,36 +294,39 @@ RestfulJson.configure do
|
|
294
294
|
|
295
295
|
# if not using permitters, will check respond_to?("(singular_model_name)_params".to_sym) and if true will __send__(method)
|
296
296
|
self.actions_that_permit = [:create, :update]
|
297
|
-
|
297
|
+
|
298
|
+
# will call .includes(...) for including and/or including_for_action when action was generated by query_for
|
299
|
+
self.apply_includes_to_custom_queries = true
|
300
|
+
|
298
301
|
# in error JSON, break out the exception info into fields for debugging
|
299
302
|
self.return_error_data = true
|
300
|
-
|
303
|
+
|
301
304
|
# the class that is rescued in each action method, but if nil will always reraise and not handle
|
302
305
|
self.rescue_class = StandardError
|
303
306
|
|
304
307
|
# will define order of errors handled and what status and/or i18n message key to use
|
305
308
|
self.rescue_handlers = []
|
306
|
-
|
309
|
+
|
307
310
|
# rescue_handlers are an ordered array of handlers to handle rescue of self.rescue_class or sub types.
|
308
311
|
# can use optional i18n_key for message, but will default to e.message if i18n_key not found.
|
309
|
-
|
312
|
+
|
310
313
|
# support 404 error for ActiveRecord::RecordNotFound if using ActiveRecord.
|
311
314
|
begin
|
312
315
|
require 'active_record/errors'
|
313
316
|
self.rescue_handlers << {exception_classes: [ActiveRecord::RecordNotFound], status: :not_found, i18n_key: 'api.not_found'.freeze}
|
314
317
|
rescue LoadError, NameError
|
315
318
|
end
|
316
|
-
|
319
|
+
|
317
320
|
# support 403 error for CanCan::AccessDenied if using CanCan
|
318
321
|
begin
|
319
322
|
require 'cancan/exceptions'
|
320
323
|
self.rescue_handlers << {exception_classes: [CanCan::AccessDenied], status: :forbidden, i18n_key: 'api.not_found'.freeze}
|
321
324
|
rescue LoadError, NameError
|
322
325
|
end
|
323
|
-
|
326
|
+
|
324
327
|
# support 500 error for everything else that is a self.rescue_class (in action)
|
325
328
|
self.rescue_handlers << {status: :internal_server_error, i18n_key: 'api.internal_server_error'.freeze}
|
326
|
-
|
329
|
+
|
327
330
|
end
|
328
331
|
```
|
329
332
|
|
@@ -706,7 +709,7 @@ self.allow_action_specific_params_methods = true
|
|
706
709
|
|
707
710
|
##### Avoid n+1 Queries
|
708
711
|
|
709
|
-
|
712
|
+
Call `include(...) to eager load and avoid n+1 queries:
|
710
713
|
|
711
714
|
```ruby
|
712
715
|
class PostsController < ApplicationController
|
@@ -730,6 +733,21 @@ end
|
|
730
733
|
|
731
734
|
Be careful- Rails doesn't raise an error if it includes associations that don't exist (at least in Rails 3.1-4.0).
|
732
735
|
|
736
|
+
A relevant config option is:
|
737
|
+
|
738
|
+
```ruby
|
739
|
+
self.apply_includes_to_custom_queries = true
|
740
|
+
```
|
741
|
+
|
742
|
+
If that is instead set to true as it is by default, it will also try to call `.includes` on the relation returned from your custom `query_for` query, e.g. if you called index and in the controller defined `including ...` or `including_for_action index: ...`, it will execute your custom query and then take the resuling relation and call `.includes(...)` on it. If `self.apply_includes_to_custom_queries = false`, it won't do that.
|
743
|
+
|
744
|
+
If you have action-specific ActiveModel::Serializers or JBuilder views that require different includes (such as an index action that only includes abbreviated info and a show action that includes more associations), you can handle that with `including_for_action`. Some examples:
|
745
|
+
|
746
|
+
```ruby
|
747
|
+
includes_for :create, are: [:category, :comments]
|
748
|
+
includes_for :index, :a_custom_action, are: [posts: [{comments: :guest}, :tags]]
|
749
|
+
```
|
750
|
+
|
733
751
|
### With Rails-api
|
734
752
|
|
735
753
|
If you want to try out [rails-api][rails-api]:
|
data/lib/restful_json/config.rb
CHANGED
@@ -17,7 +17,8 @@ module RestfulJson
|
|
17
17
|
:avoid_respond_with,
|
18
18
|
:return_error_data,
|
19
19
|
:rescue_class,
|
20
|
-
:rescue_handlers
|
20
|
+
:rescue_handlers,
|
21
|
+
:apply_includes_to_custom_queries
|
21
22
|
]
|
22
23
|
|
23
24
|
class << self
|
@@ -28,40 +29,40 @@ module RestfulJson
|
|
28
29
|
end
|
29
30
|
|
30
31
|
RestfulJson.configure do
|
31
|
-
|
32
|
+
|
32
33
|
# default for :using in can_filter_by
|
33
34
|
self.can_filter_by_default_using = [:eq]
|
34
|
-
|
35
|
+
|
35
36
|
# to log debug info during request handling
|
36
37
|
self.debug = false
|
37
|
-
|
38
|
+
|
38
39
|
# delimiter for values in request parameter values
|
39
40
|
self.filter_split = ','.freeze
|
40
|
-
|
41
|
+
|
41
42
|
# equivalent to specifying respond_to :json, :html in the controller, and can be overriden in the controller. Note that by default responders gem sets respond_to :html in application_controller.rb.
|
42
43
|
self.formats = :json, :html
|
43
|
-
|
44
|
+
|
44
45
|
# default number of records to return if using the page request function
|
45
46
|
self.number_of_records_in_a_page = 15
|
46
|
-
|
47
|
+
|
47
48
|
# delimiter for ARel predicate in the request parameter name
|
48
49
|
self.predicate_prefix = '!'.freeze
|
49
|
-
|
50
|
+
|
50
51
|
# if true, will render resource and HTTP 201 for post/create or resource and HTTP 200 for put/update. ignored if render_enabled is false.
|
51
52
|
self.return_resource = false
|
52
|
-
|
53
|
+
|
53
54
|
# if false, controller actions will just set instance variable and return it instead of calling setting instance variable and then calling render/respond_with
|
54
55
|
self.render_enabled = true
|
55
|
-
|
56
|
+
|
56
57
|
# use Permitters
|
57
58
|
self.use_permitters = true
|
58
|
-
|
59
|
+
|
59
60
|
# instead of using Rails default respond_with, explicitly define render in respond_with block
|
60
61
|
self.avoid_respond_with = true
|
61
|
-
|
62
|
+
|
62
63
|
# use the permitter_class for create and update, if use_permitters = true
|
63
64
|
self.action_to_permitter = {create: nil, update: nil}
|
64
|
-
|
65
|
+
|
65
66
|
# the methods that call authorize! action_sym, @model_class
|
66
67
|
self.actions_that_authorize = [:create, :update]
|
67
68
|
|
@@ -70,34 +71,37 @@ RestfulJson.configure do
|
|
70
71
|
|
71
72
|
# if not using permitters, will check respond_to?("(singular_model_name)_params".to_sym) and if true will __send__(method)
|
72
73
|
self.actions_that_permit = [:create, :update]
|
73
|
-
|
74
|
+
|
75
|
+
# will call .includes(...) for including and/or including_for_action when action was generated by query_for
|
76
|
+
self.apply_includes_to_custom_queries = true
|
77
|
+
|
74
78
|
# in error JSON, break out the exception info into fields for debugging
|
75
79
|
self.return_error_data = true
|
76
|
-
|
80
|
+
|
77
81
|
# the class that is rescued in each action method, but if nil will always reraise and not handle
|
78
82
|
self.rescue_class = StandardError
|
79
83
|
|
80
84
|
# will define order of errors handled and what status and/or i18n message key to use
|
81
85
|
self.rescue_handlers = []
|
82
|
-
|
86
|
+
|
83
87
|
# rescue_handlers are an ordered array of handlers to handle rescue of self.rescue_class or sub types.
|
84
88
|
# can use optional i18n_key for message, but will default to e.message if i18n_key not found.
|
85
|
-
|
89
|
+
|
86
90
|
# support 404 error for ActiveRecord::RecordNotFound if using ActiveRecord.
|
87
91
|
begin
|
88
92
|
require 'active_record/errors'
|
89
93
|
self.rescue_handlers << {exception_classes: [ActiveRecord::RecordNotFound], status: :not_found, i18n_key: 'api.not_found'.freeze}
|
90
94
|
rescue LoadError, NameError
|
91
95
|
end
|
92
|
-
|
96
|
+
|
93
97
|
# support 403 error for CanCan::AccessDenied if using CanCan
|
94
98
|
begin
|
95
99
|
require 'cancan/exceptions'
|
96
100
|
self.rescue_handlers << {exception_classes: [CanCan::AccessDenied], status: :forbidden, i18n_key: 'api.not_found'.freeze}
|
97
101
|
rescue LoadError, NameError
|
98
102
|
end
|
99
|
-
|
103
|
+
|
100
104
|
# support 500 error for everything else that is a self.rescue_class (in action)
|
101
105
|
self.rescue_handlers << {status: :internal_server_error, i18n_key: 'api.internal_server_error'.freeze}
|
102
|
-
|
106
|
+
|
103
107
|
end
|
@@ -37,6 +37,7 @@ module RestfulJson
|
|
37
37
|
class_attribute :action_to_serializer, instance_writer: true
|
38
38
|
class_attribute :action_to_serializer_for, instance_writer: true
|
39
39
|
class_attribute :query_includes, instance_writer: true
|
40
|
+
class_attribute :action_to_query_includes, instance_writer: true
|
40
41
|
|
41
42
|
# use values from config
|
42
43
|
RestfulJson::CONTROLLER_OPTIONS.each do |key|
|
@@ -52,6 +53,7 @@ module RestfulJson
|
|
52
53
|
self.param_to_through ||= {}
|
53
54
|
self.action_to_serializer ||= {}
|
54
55
|
self.action_to_serializer_for ||= {}
|
56
|
+
self.action_to_query_includes ||= {}
|
55
57
|
end
|
56
58
|
|
57
59
|
module ClassMethods
|
@@ -105,9 +107,27 @@ module RestfulJson
|
|
105
107
|
self.supported_functions += args
|
106
108
|
end
|
107
109
|
|
110
|
+
# Calls .includes(...) on queries. Take a hash of action as symbol to the includes, e.g. to include(:category, :comments):
|
111
|
+
# including :category, :comments
|
112
|
+
# or includes({posts: [{comments: :guest}, :tags]}):
|
113
|
+
# including posts: [{comments: :guest}, :tags]
|
108
114
|
def including(*args)
|
109
115
|
self.query_includes = args
|
110
116
|
end
|
117
|
+
|
118
|
+
# Calls .includes(...) only on specified action queries. Take a hash of action as symbol to the includes, e.g.:
|
119
|
+
# includes_for :create, are: [:category, :comments]
|
120
|
+
# includes_for :index, :a_custom_action, are: [posts: [{comments: :guest}, :tags]]
|
121
|
+
def includes_for(*args)
|
122
|
+
options = args.extract_options!
|
123
|
+
args.each do |an_action|
|
124
|
+
if options[:are]
|
125
|
+
self.action_to_query_includes.merge!({an_action.to_sym => options[:are]})
|
126
|
+
else
|
127
|
+
raise "#{self.class.name} must supply an :are option with includes_for #{an_action.inspect}"
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
111
131
|
|
112
132
|
# Specify a custom query. If action specified does not have a method, it will alias_method index to create a new action method with that query.
|
113
133
|
#
|
@@ -274,10 +294,8 @@ module RestfulJson
|
|
274
294
|
# primary_key array support for composite_primary_keys.
|
275
295
|
if @model_class.primary_key.is_a? Array
|
276
296
|
c = @model_class
|
297
|
+
apply_includes params[:action].to_sym, value
|
277
298
|
c.primary_key.each {|pkey|c.where(pkey.to_sym => params[pkey].to_s)}
|
278
|
-
if self.query_includes
|
279
|
-
value.includes(*(self.query_includes))
|
280
|
-
end
|
281
299
|
# raise exception if not found
|
282
300
|
@value = c.first!
|
283
301
|
else
|
@@ -285,6 +303,13 @@ module RestfulJson
|
|
285
303
|
end
|
286
304
|
end
|
287
305
|
|
306
|
+
def apply_includes(action_sym, value)
|
307
|
+
this_includes = self.action_to_query_includes[action_sym] || self.query_includes
|
308
|
+
if this_includes
|
309
|
+
value.includes(*this_includes)
|
310
|
+
end
|
311
|
+
end
|
312
|
+
|
288
313
|
def allowed_params
|
289
314
|
action_sym = params[:action].to_sym
|
290
315
|
singular = single_value_response?
|
@@ -383,14 +408,17 @@ module RestfulJson
|
|
383
408
|
def index
|
384
409
|
# could be index or another action if alias_method'd by query_for
|
385
410
|
logger.debug "#{params[:action]} called in #{self.class}: model=#{@model_class}, request.format=#{request.format}, request.content_type=#{request.content_type}, params=#{params.inspect}" if self.debug
|
411
|
+
action_sym = params[:action].to_sym
|
386
412
|
p_params = allowed_params
|
387
413
|
t = @model_class.arel_table
|
388
414
|
value = @model_class.scoped # returns ActiveRecord::Relation equivalent to select with no where clause
|
389
|
-
custom_query = self.action_to_query[
|
415
|
+
custom_query = self.action_to_query[action_sym]
|
390
416
|
if custom_query
|
391
417
|
value = custom_query.call(t, value)
|
392
418
|
end
|
393
419
|
|
420
|
+
apply_includes action_sym, value
|
421
|
+
|
394
422
|
self.param_to_query.each do |param_name, param_query|
|
395
423
|
if params[param_name]
|
396
424
|
# to_s as safety measure for vulnerabilities similar to CVE-2013-1854
|
@@ -445,10 +473,6 @@ module RestfulJson
|
|
445
473
|
end
|
446
474
|
end
|
447
475
|
|
448
|
-
if self.query_includes
|
449
|
-
value.includes(*(self.query_includes))
|
450
|
-
end
|
451
|
-
|
452
476
|
if p_params[:page] && self.supported_functions.include?(:page)
|
453
477
|
page = p_params[:page].to_i
|
454
478
|
page = 1 if page < 1 # to avoid people using this as a way to get all records unpaged, as that probably isn't the intent?
|
data/lib/restful_json/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: restful_json
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 4.
|
4
|
+
version: 4.2.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Gary S. Weaver
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-05-
|
12
|
+
date: 2013-05-02 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|