standardapi 1.0.2 → 1.0.3
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 +4 -4
- data/README.md +52 -6
- data/lib/standard_api/includes.rb +64 -0
- data/lib/standard_api/test_case/index_tests.rb +2 -3
- data/lib/standard_api/views/application/_model.json.jbuilder +9 -4
- data/lib/standard_api.rb +3 -2
- metadata +16 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 69566409eb2d53c206772fd1bba289eb016269a4
|
4
|
+
data.tar.gz: bdbbb1c63b34d2eea506cfe63ef1d87a467074cd
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 602ead9fee5724eabfefa6b61510a71f0bf0e0a8b6f2a669561be5d18e44a5ae942bfdca5c1448221336b033dc0f559b687b18ed4449e422726cf9d0bf8852b5
|
7
|
+
data.tar.gz: 441e7a6b71b9f1bf7aa1d018a3c1c5d3c30753aab585e5fea15afab536b1e82bc26595dbe8e0c3410e356e0015bb7d51d430df549b67d4d158d46ec798ea4471
|
data/README.md
CHANGED
@@ -1,10 +1,56 @@
|
|
1
|
-
#
|
1
|
+
# StandardAPI
|
2
|
+
|
2
3
|
StandardAPI makes it easy to expose a query interface for your Rails models
|
3
4
|
|
5
|
+
# Installation
|
6
|
+
|
7
|
+
gem install standardapi
|
8
|
+
|
9
|
+
In your Gemfile
|
10
|
+
|
11
|
+
gem 'standardapi', require: 'standard_api'
|
12
|
+
|
13
|
+
StandardAPI is a module you can include into any controllers you want to have
|
14
|
+
API access to, or in the ApplicationController, giving all inherited controller
|
15
|
+
access.
|
16
|
+
|
17
|
+
class ApplicationController < ActiveController::Base
|
18
|
+
include StandardAPI
|
19
|
+
|
20
|
+
end
|
21
|
+
|
22
|
+
And example contoller and it's tests.
|
23
|
+
|
24
|
+
class PhotosController < ApplicationController
|
25
|
+
include StandardAPI
|
26
|
+
|
27
|
+
# If you have actions you don't want include be sure to hide them,
|
28
|
+
# otherwise if you include StandardAPI::TestCase and you don't have the
|
29
|
+
# action setup, the test will fail.
|
30
|
+
hide_action :destroy
|
31
|
+
|
32
|
+
# Allowed params
|
33
|
+
def photo_params
|
34
|
+
[:id, :file, :caption]
|
35
|
+
end
|
36
|
+
|
37
|
+
# Allowed orderings
|
38
|
+
def photo_orders
|
39
|
+
[:id, :created_at, :updated_at, :caption]
|
40
|
+
end
|
41
|
+
|
42
|
+
# Allowed includes
|
43
|
+
# You can include the author and the authors photos in the JSON response
|
44
|
+
def photo_includes
|
45
|
+
{ :author => [:photos] }
|
46
|
+
end
|
4
47
|
|
5
|
-
|
6
|
-
|
7
|
-
|
48
|
+
# Mask for Photo. Provide this method if you want to mask some records
|
49
|
+
# The mask is then applyed to all actions when querring ActiveRecord
|
50
|
+
# Will only allow photos that have id one. For more on the syntax see
|
51
|
+
# the activerecord-filter gem.
|
52
|
+
def current_mask
|
53
|
+
{ id: 1 }
|
54
|
+
end
|
8
55
|
|
9
|
-
|
10
|
-
- current_mask
|
56
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'active_support/core_ext/hash/indifferent_access'
|
2
|
+
# require 'active_support/core_ext/hash'
|
3
|
+
module StandardAPI
|
4
|
+
module Includes
|
5
|
+
|
6
|
+
# :x => { x: {} }
|
7
|
+
# [:x, :y] => { x: {}, y: {} }
|
8
|
+
# [ { x: true }, { y: true } ] => { x: {}, y: {} }
|
9
|
+
# { x: true, y: true } => { x: {}, y: {} }
|
10
|
+
# { x: { y: true } } => { x: { y: {} } }
|
11
|
+
# { x: [:y] } => { x: { y: {} } }
|
12
|
+
def self.normalize(includes)
|
13
|
+
normalized = ActiveSupport::HashWithIndifferentAccess.new
|
14
|
+
|
15
|
+
case includes
|
16
|
+
when Array
|
17
|
+
includes.flatten.compact.each { |v| normalized.merge!(normalize(v)) }
|
18
|
+
when Hash
|
19
|
+
includes.each_pair { |k, v| normalized[k] = normalize(v) }
|
20
|
+
else
|
21
|
+
if ![true, 'true'].include?(includes)
|
22
|
+
normalized[includes] = {}
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
normalized
|
27
|
+
end
|
28
|
+
|
29
|
+
# sanitize({:key => {}}, [:key]) # => {:key => {}}
|
30
|
+
# sanitize({:key => {}}, {:key => true}) # => {:key => {}}
|
31
|
+
# sanitize({:key => {}}, :value => {}}, [:key]) => # Raises ParseError
|
32
|
+
# sanitize({:key => {}}, :value => {}}, {:key => true}) => # Raises ParseError
|
33
|
+
# sanitize({:key => {:value => {}}}, {:key => [:value]}) # => {:key => {:value => {}}}
|
34
|
+
# sanitize({:key => {:value => {}}}, {:key => {:value => true}}) # => {:key => {:value => {}}}
|
35
|
+
# sanitize({:key => {:value => {}}}, [:key]) => # Raises ParseError
|
36
|
+
def self.sanitize(includes, permit)
|
37
|
+
includes = normalize(includes)
|
38
|
+
permitted = ActiveSupport::HashWithIndifferentAccess.new
|
39
|
+
|
40
|
+
if permit.is_a?(Array)
|
41
|
+
permit = permit.inject({}) { |acc, v| acc[v] = true; acc }
|
42
|
+
end
|
43
|
+
|
44
|
+
permit = normalize(permit.with_indifferent_access)
|
45
|
+
includes.each do |k, v|
|
46
|
+
if permit.has_key?(k) || ['where', 'order'].include?(k.to_s)
|
47
|
+
permitted[k] = sanitize(v, permit[k] || {})
|
48
|
+
else
|
49
|
+
if [:raise, nil].include?(Rails.configuration.try(:action_on_unpermitted_includes))
|
50
|
+
raise(ActionDispatch::ParamsParser::ParseError.new(<<-ERR.squish, nil))
|
51
|
+
Invalid Include: #{k}"
|
52
|
+
Set config.action_on_unpermitted_includes = :warm to log instead of raise
|
53
|
+
ERR
|
54
|
+
else
|
55
|
+
Rails.logger.try(:warn, "Invalid Include: #{k}")
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
permitted
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
64
|
+
end
|
@@ -42,10 +42,9 @@ module StandardAPI
|
|
42
42
|
end
|
43
43
|
|
44
44
|
test '#index.json params[:include]' do
|
45
|
-
create_model
|
46
|
-
|
45
|
+
create_model(:nested)
|
46
|
+
get :index, include: includes, format: 'json'
|
47
47
|
includes.each do |included|
|
48
|
-
get :index, include: [included], format: 'json'
|
49
48
|
assert JSON.parse(response.body)[0].key?(included.to_s), "#{included.inspect} not included in response"
|
50
49
|
end
|
51
50
|
end
|
@@ -2,16 +2,21 @@ model.attributes.each do |name, value|
|
|
2
2
|
json.set! name, value
|
3
3
|
end
|
4
4
|
|
5
|
-
includes.each do |inc|
|
6
|
-
if model.class.reflect_on_association(inc).klass
|
5
|
+
includes.each do |inc, subinc|
|
6
|
+
if model.class.reflect_on_association(inc).klass < ActiveRecord::Base
|
7
7
|
json.set! inc do
|
8
|
-
|
8
|
+
collection = [:has_many, :has_and_belongs_to_many].include?(model.class.reflect_on_association(inc).macro)
|
9
|
+
if collection
|
10
|
+
json.array! model.send(inc), partial: 'application/model', as: :model, locals: { includes: subinc }
|
11
|
+
else
|
12
|
+
json.partial! 'application/model', model: model.send(inc), includes: subinc
|
13
|
+
end
|
9
14
|
end
|
10
15
|
else
|
11
16
|
json.set! inc, model.send(inc)
|
12
17
|
end
|
13
18
|
end
|
14
19
|
|
15
|
-
if model.errors
|
20
|
+
if !model.errors.blank?
|
16
21
|
json.set! 'errors', model.errors.to_h
|
17
22
|
end
|
data/lib/standard_api.rb
CHANGED
@@ -11,6 +11,8 @@ if !ActionView::Template.registered_template_handler(:jbuilder)
|
|
11
11
|
ActionView::Template.register_template_handler :jbuilder, JbuilderHandler
|
12
12
|
end
|
13
13
|
|
14
|
+
require 'standard_api/includes'
|
15
|
+
|
14
16
|
module StandardAPI
|
15
17
|
|
16
18
|
def self.included(klass)
|
@@ -85,9 +87,8 @@ module StandardAPI
|
|
85
87
|
model.filter(params[:where]).where(current_mask[model.table_name])
|
86
88
|
end
|
87
89
|
|
88
|
-
# TODO: sanitize includes
|
89
90
|
def includes
|
90
|
-
params[:include] || []
|
91
|
+
@includes ||= StandardAPI::Includes.normalize(params[:include] || [])
|
91
92
|
end
|
92
93
|
|
93
94
|
# TODO: sanitize orders
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standardapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.0.
|
4
|
+
version: 1.0.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Bracy
|
@@ -52,6 +52,20 @@ dependencies:
|
|
52
52
|
- - "~>"
|
53
53
|
- !ruby/object:Gem::Version
|
54
54
|
version: '4.2'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: activesupport
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - "~>"
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '4.2'
|
62
|
+
type: :runtime
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - "~>"
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '4.2'
|
55
69
|
- !ruby/object:Gem::Dependency
|
56
70
|
name: jbuilder
|
57
71
|
requirement: !ruby/object:Gem::Requirement
|
@@ -175,6 +189,7 @@ extra_rdoc_files:
|
|
175
189
|
files:
|
176
190
|
- README.md
|
177
191
|
- lib/standard_api.rb
|
192
|
+
- lib/standard_api/includes.rb
|
178
193
|
- lib/standard_api/test_case.rb
|
179
194
|
- lib/standard_api/test_case/calculate_tests.rb
|
180
195
|
- lib/standard_api/test_case/create_tests.rb
|