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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 00a4ca4a08d5ea94b8ac4bd32a3594e788df0ff8
4
- data.tar.gz: 1e7475c8c767003c8772799c15e2c024b972caed
3
+ metadata.gz: 69566409eb2d53c206772fd1bba289eb016269a4
4
+ data.tar.gz: bdbbb1c63b34d2eea506cfe63ef1d87a467074cd
5
5
  SHA512:
6
- metadata.gz: 512d98d1856c2652f27556e76077163a8b74fd40979fe1d544e8ee7a8014d92ddf00ebd8a5b7b7957e32e727516f265b624e1ee85f29c3ee71d10ca3d5ab5c4d
7
- data.tar.gz: b6df1f38fbc139cfd9fa9cfd07dbd50436134fecac245853177ffe5af45cc7a8fc3588b0203f80910afa36fc571d29f82ddb0f9cb9dabe65c6b6dd2425a83490
6
+ metadata.gz: 602ead9fee5724eabfefa6b61510a71f0bf0e0a8b6f2a669561be5d18e44a5ae942bfdca5c1448221336b033dc0f559b687b18ed4449e422726cf9d0bf8852b5
7
+ data.tar.gz: 441e7a6b71b9f1bf7aa1d018a3c1c5d3c30753aab585e5fea15afab536b1e82bc26595dbe8e0c3410e356e0015bb7d51d430df549b67d4d158d46ec798ea4471
data/README.md CHANGED
@@ -1,10 +1,56 @@
1
- # standardapi
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
- required models
6
- - account { mask }
7
- - api_keys
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
- # TODO
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.is_a?(ActiveModel)
5
+ includes.each do |inc, subinc|
6
+ if model.class.reflect_on_association(inc).klass < ActiveRecord::Base
7
7
  json.set! inc do
8
- json.partial! 'action_controller/standard_api/_model', locals: { model: model.send(inc) }
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.2
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