standardapi 1.0.2 → 1.0.3

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
  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