standardapi 5.0.0.16 → 5.2.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/README.md +25 -1
- data/lib/standard_api/controller.rb +30 -24
- data/lib/standard_api/helpers.rb +3 -3
- data/lib/standard_api/includes.rb +5 -2
- data/lib/standard_api/test_case/create_tests.rb +21 -4
- data/lib/standard_api/test_case/index_tests.rb +9 -21
- data/lib/standard_api/test_case/schema_tests.rb +1 -1
- data/lib/standard_api/test_case/update_tests.rb +2 -1
- data/lib/standard_api/test_case.rb +16 -7
- data/lib/standard_api/version.rb +1 -1
- data/lib/standard_api/views/application/_record.streamer +63 -0
- data/lib/standard_api/views/application/index.streamer +12 -0
- data/lib/standard_api/views/application/new.streamer +1 -0
- data/lib/standard_api/views/application/schema.json.jbuilder +3 -1
- data/lib/standard_api/views/application/schema.streamer +39 -0
- data/lib/standard_api/views/application/show.streamer +1 -0
- data/lib/standard_api.rb +1 -2
- metadata +41 -43
- data/lib/standard_api/views/application/settings.json.jbuilder +0 -0
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 07e04cf1267208519f3837a0b7881786d55a053f3e3304e5e7599d01fb72102d
|
4
|
+
data.tar.gz: 7bf8e046a0ef987a912001df5075537961651d9ddcc6cccab31fb2a690b1e1cc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 949c1c8abf9098956e5ceca14978b725b157fa604eeb8e4c60213e0eb84e841fd551088097bcedc8e39106442cd5ea4fd9f779f41fb05b41531556b7007bc3f5
|
7
|
+
data.tar.gz: 6c381c38daca817c906d11eda4f67c77d8bb2353f3c454f783da7a6d1fde3938335e4159e50f8c358ae46b33fd4492c2cfd6b1127cdfefd4ff8d2f1de9ab7697
|
data/README.md
CHANGED
@@ -7,10 +7,34 @@ interface to your Rails models.
|
|
7
7
|
|
8
8
|
gem install standardapi
|
9
9
|
|
10
|
-
In your Gemfile
|
10
|
+
In your Gemfile:
|
11
11
|
|
12
12
|
gem 'standardapi', require: 'standard_api'
|
13
13
|
|
14
|
+
In `config/application.rb:
|
15
|
+
|
16
|
+
require_relative 'boot'
|
17
|
+
|
18
|
+
require 'rails/all'
|
19
|
+
require 'standard_api/middleware/query_encoding'
|
20
|
+
|
21
|
+
# Require the gems listed in Gemfile, including any gems
|
22
|
+
# you've limited to :test, :development, or :production.
|
23
|
+
Bundler.require(*Rails.groups)
|
24
|
+
|
25
|
+
module Tester
|
26
|
+
class Application < Rails::Application
|
27
|
+
# Initialize configuration defaults for originally generated Rails version.
|
28
|
+
config.load_defaults 5.2
|
29
|
+
|
30
|
+
# Settings in config/environments/* take precedence over those specified here.
|
31
|
+
# Application configuration can go into files in config/initializers
|
32
|
+
# -- all .rb files in that directory are automatically loaded after loading
|
33
|
+
# the framework and any gems in your application.
|
34
|
+
config.middleware.insert_after Rack::MethodOverride, StandardAPI::Middleware::QueryEncoding
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
14
38
|
# Usage
|
15
39
|
|
16
40
|
StandardAPI is a module that can be included into any controller to expose a API
|
@@ -42,10 +42,15 @@ module StandardAPI
|
|
42
42
|
def create
|
43
43
|
record = model.new(model_params)
|
44
44
|
instance_variable_set("@#{model.model_name.singular}", record)
|
45
|
-
|
45
|
+
|
46
46
|
if record.save
|
47
47
|
if request.format == :html
|
48
|
-
redirect_to
|
48
|
+
redirect_to url_for(
|
49
|
+
controller: record.class.base_class.model_name.collection,
|
50
|
+
action: 'show',
|
51
|
+
id: record.id,
|
52
|
+
only_path: true
|
53
|
+
)
|
49
54
|
else
|
50
55
|
render :show, status: :created
|
51
56
|
end
|
@@ -64,7 +69,12 @@ module StandardAPI
|
|
64
69
|
|
65
70
|
if record.update_attributes(model_params)
|
66
71
|
if request.format == :html
|
67
|
-
redirect_to
|
72
|
+
redirect_to url_for(
|
73
|
+
controller: record.class.base_class.model_name.collection,
|
74
|
+
action: 'show',
|
75
|
+
id: record.id,
|
76
|
+
only_path: true
|
77
|
+
)
|
68
78
|
else
|
69
79
|
render :show, status: :ok
|
70
80
|
end
|
@@ -90,22 +100,6 @@ module StandardAPI
|
|
90
100
|
@model = name.sub(/Controller\z/, '').singularize.camelize.safe_constantize
|
91
101
|
end
|
92
102
|
|
93
|
-
def model_includes
|
94
|
-
if self.respond_to?("#{model.model_name.singular}_includes", true)
|
95
|
-
self.send "#{model.model_name.singular}_includes"
|
96
|
-
else
|
97
|
-
[]
|
98
|
-
end
|
99
|
-
end
|
100
|
-
|
101
|
-
def model_orders
|
102
|
-
if self.respond_to?("#{model.model_name.singular}_orders", true)
|
103
|
-
self.send "#{model.model_name.singular}_orders"
|
104
|
-
else
|
105
|
-
[]
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
103
|
end
|
110
104
|
|
111
105
|
private
|
@@ -119,11 +113,19 @@ module StandardAPI
|
|
119
113
|
end
|
120
114
|
|
121
115
|
def model_includes
|
122
|
-
self.
|
116
|
+
if self.respond_to?("#{model.model_name.singular}_includes", true)
|
117
|
+
self.send("#{model.model_name.singular}_includes")
|
118
|
+
else
|
119
|
+
[]
|
120
|
+
end
|
123
121
|
end
|
124
122
|
|
125
123
|
def model_orders
|
126
|
-
self.
|
124
|
+
if self.respond_to?("#{model.model_name.singular}_orders", true)
|
125
|
+
self.send("#{model.model_name.singular}_orders")
|
126
|
+
else
|
127
|
+
[]
|
128
|
+
end
|
127
129
|
end
|
128
130
|
|
129
131
|
def model_params
|
@@ -166,6 +168,10 @@ module StandardAPI
|
|
166
168
|
def required_orders
|
167
169
|
[]
|
168
170
|
end
|
171
|
+
|
172
|
+
def default_orders
|
173
|
+
nil
|
174
|
+
end
|
169
175
|
|
170
176
|
def orders
|
171
177
|
exluded_required_orders = required_orders.map(&:to_s)
|
@@ -189,8 +195,8 @@ module StandardAPI
|
|
189
195
|
if !exluded_required_orders.empty?
|
190
196
|
params[:order] = exluded_required_orders.unshift(params[:order])
|
191
197
|
end
|
192
|
-
|
193
|
-
@orders ||= StandardAPI::Orders.sanitize(params[:order], model_orders | required_orders)
|
198
|
+
|
199
|
+
@orders ||= StandardAPI::Orders.sanitize(params[:order] || default_orders, model_orders | required_orders)
|
194
200
|
end
|
195
201
|
|
196
202
|
def excludes
|
@@ -231,7 +237,7 @@ module StandardAPI
|
|
231
237
|
select.each do |func, column|
|
232
238
|
column = column == '*' ? Arel.star : column.to_sym
|
233
239
|
if functions.include?(func.to_s.downcase)
|
234
|
-
@selects << (model.arel_table[column].send(func)
|
240
|
+
@selects << (model.arel_table[column].send(func))
|
235
241
|
end
|
236
242
|
end
|
237
243
|
end
|
data/lib/standard_api/helpers.rb
CHANGED
@@ -19,7 +19,7 @@ module StandardAPI
|
|
19
19
|
end
|
20
20
|
|
21
21
|
def cache_key(record, includes)
|
22
|
-
timestamp_keys = ['cached_at'] +
|
22
|
+
timestamp_keys = ['cached_at'] + record.class.column_names.select{|x| x.ends_with? "_cached_at"}
|
23
23
|
if includes.empty?
|
24
24
|
record.cache_key(*timestamp_keys)
|
25
25
|
else
|
@@ -58,9 +58,9 @@ module StandardAPI
|
|
58
58
|
end
|
59
59
|
|
60
60
|
def cached_at_columns_for_includes(includes)
|
61
|
-
includes.select{|k,v| ![:where, :limit, :order].include?(k.to_sym) }.map
|
61
|
+
includes.select { |k,v| ![:where, :limit, :order].include?(k.to_sym) }.map do |k, v|
|
62
62
|
["#{k}_cached_at"] + cached_at_columns_for_includes(v).map { |v2| "#{k}_#{v2}" }
|
63
|
-
|
63
|
+
end.flatten
|
64
64
|
end
|
65
65
|
|
66
66
|
def includes_to_cache_key(relation, subincludes)
|
@@ -17,8 +17,11 @@ module StandardAPI
|
|
17
17
|
includes.flatten.compact.each { |v| normalized.merge!(normalize(v)) }
|
18
18
|
when Hash, ActionController::Parameters
|
19
19
|
includes.each_pair do |k, v|
|
20
|
-
if ['where', 'order'].include?(k.to_s) # Where and order are not normalized
|
21
|
-
normalized[k] = v
|
20
|
+
if ['where', 'order'].include?(k.to_s) # Where and order are not normalized (sanitation happens in activerecord-filter)
|
21
|
+
normalized[k] = case v
|
22
|
+
when Hash then v.to_h
|
23
|
+
when ActionController::Parameters then v.to_unsafe_h
|
24
|
+
end
|
22
25
|
else
|
23
26
|
normalized[k] = normalize(v)
|
24
27
|
end
|
@@ -4,7 +4,8 @@ module StandardAPI
|
|
4
4
|
extend ActiveSupport::Testing::Declarative
|
5
5
|
|
6
6
|
test '#create.json' do
|
7
|
-
attrs = attributes_for(singular_name, :nested).select{|k,v| !model.readonly_attributes.include?(k.to_s) }
|
7
|
+
attrs = attributes_for(singular_name, :nested).select{ |k,v| !model.readonly_attributes.include?(k.to_s) }
|
8
|
+
mask.each { |k, v| attrs[k] = v }
|
8
9
|
create_webmocks(attrs)
|
9
10
|
|
10
11
|
file_upload = attrs.any? { |k, v| v.is_a?(Rack::Test::UploadedFile) }
|
@@ -34,6 +35,7 @@ module StandardAPI
|
|
34
35
|
|
35
36
|
test '#create.json with nested attributes' do
|
36
37
|
attrs = attributes_for(singular_name, :nested).select{|k,v| !model.readonly_attributes.include?(k.to_s) }
|
38
|
+
mask.each { |k, v| attrs[k] = v }
|
37
39
|
create_webmocks(attrs)
|
38
40
|
|
39
41
|
file_upload = attrs.any? { |k, v| v.is_a?(Rack::Test::UploadedFile) }
|
@@ -59,7 +61,7 @@ module StandardAPI
|
|
59
61
|
end
|
60
62
|
|
61
63
|
test '#create.json with invalid attributes' do
|
62
|
-
trait =
|
64
|
+
trait = FactoryBot.factories[singular_name].definition.defined_traits.any? { |x| x.name.to_s == 'invalid' }
|
63
65
|
|
64
66
|
if !trait
|
65
67
|
Rails.logger.try(:warn, "No invalid trait for #{model.name}. Skipping invalid tests")
|
@@ -82,10 +84,26 @@ module StandardAPI
|
|
82
84
|
end
|
83
85
|
end
|
84
86
|
|
87
|
+
test '#create.html' do
|
88
|
+
return unless supports_format(:html)
|
89
|
+
|
90
|
+
attrs = attributes_for(singular_name, :nested).select{ |k,v| !model.readonly_attributes.include?(k.to_s) }
|
91
|
+
mask.each { |k, v| attrs[k] = v }
|
92
|
+
create_webmocks(attrs)
|
93
|
+
|
94
|
+
file_upload = attrs.any? { |k, v| v.is_a?(Rack::Test::UploadedFile) }
|
95
|
+
as = file_upload ? nil : :json
|
96
|
+
|
97
|
+
assert_difference("#{model.name}.count") do
|
98
|
+
post resource_path(:create), params: { singular_name => attrs }, as: :html
|
99
|
+
assert_response :redirect
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
85
103
|
test '#create.html with invalid attributes renders edit action' do
|
86
104
|
return unless supports_format(:html)
|
87
105
|
|
88
|
-
trait =
|
106
|
+
trait = FactoryBot.factories[singular_name].definition.defined_traits.any? { |x| x.name.to_s == 'invalid' }
|
89
107
|
|
90
108
|
if !trait
|
91
109
|
Rails.logger.try(:warn, "No invalid trait for #{model.name}. Skipping invalid tests")
|
@@ -99,7 +117,6 @@ module StandardAPI
|
|
99
117
|
assert_difference("#{model.name}.count", 0) do
|
100
118
|
post resource_path(:create), params: { singular_name => attrs }, as: :html
|
101
119
|
assert_response :bad_request
|
102
|
-
assert_equal response.body, 'properties#edit.html'
|
103
120
|
end
|
104
121
|
end
|
105
122
|
|
@@ -12,37 +12,26 @@ module StandardAPI
|
|
12
12
|
end
|
13
13
|
|
14
14
|
test '#index.json requires limit' do
|
15
|
-
|
16
|
-
|
17
|
-
return if !limit || limit == Float::INFINITY
|
15
|
+
return if !resource_limit || resource_limit == Float::INFINITY
|
18
16
|
|
19
17
|
begin
|
20
18
|
get resource_path(:index, format: :json)
|
21
19
|
assert_response :bad_request
|
22
20
|
rescue ActionController::ParameterMissing
|
23
21
|
end
|
24
|
-
|
25
|
-
# return if !controller_class.new.send(:resource_limit)
|
26
|
-
# if app.config.action_dispatch.show_exceptions
|
27
|
-
# assert_raises ActionController::ParameterMissing do
|
28
|
-
# get resource_path(:index, format: 'json')
|
29
|
-
# assert_response :bad_request
|
30
|
-
# end
|
31
|
-
# else
|
32
|
-
# get resource_path(:index, format: :json)
|
33
|
-
# assert_response :bad_request
|
34
|
-
# end
|
35
22
|
end
|
36
23
|
|
37
24
|
test '#index.json params[:limit]' do
|
38
25
|
get resource_path(:index, format: :json), params: { limit: 1 }
|
39
26
|
models = @controller.instance_variable_get("@#{plural_name}")
|
40
|
-
assert_equal model.limit(1).sort(
|
27
|
+
assert_equal model.filter(mask).limit(1).sort(default_orders).to_sql, models.to_sql
|
41
28
|
end
|
42
29
|
|
43
30
|
test '#index.json params[:limit] does not exceed maximum limit' do
|
31
|
+
return if !resource_limit || resource_limit == Float::INFINITY
|
32
|
+
|
44
33
|
assert_raises ActionController::UnpermittedParameters do
|
45
|
-
get resource_path(:index, format: :json), params: { limit:
|
34
|
+
get resource_path(:index, format: :json), params: { limit: resource_limit + 1 }
|
46
35
|
end
|
47
36
|
end
|
48
37
|
|
@@ -59,24 +48,23 @@ module StandardAPI
|
|
59
48
|
get resource_path(:index, format: :json), params: { limit: 1 }
|
60
49
|
|
61
50
|
orders.each do |order|
|
62
|
-
@controller.instance_variable_set('@orders', nil) # Hack for dealing with caching / multiple request per controller life
|
63
51
|
get resource_path(:index, format: :json), params: { limit: 10, order: order }
|
64
52
|
models = @controller.instance_variable_get("@#{plural_name}")
|
65
|
-
assert_equal model.sort(order).limit(10).sort(
|
66
|
-
|
53
|
+
assert_equal model.filter(mask).sort(order).limit(10).sort(order).to_sql, models.to_sql
|
54
|
+
end
|
67
55
|
end
|
68
56
|
|
69
57
|
test '#index.json params[:offset]' do
|
70
58
|
get resource_path(:index, format: :json), params: { limit: 10, offset: 13 }
|
71
59
|
models = @controller.instance_variable_get("@#{plural_name}")
|
72
|
-
assert_equal model.offset(13).limit(10).sort(
|
60
|
+
assert_equal model.filter(mask).offset(13).limit(10).sort(default_orders).to_sql, models.to_sql
|
73
61
|
end
|
74
62
|
|
75
63
|
test '#index.json params[:include]' do
|
76
64
|
travel_to Time.now do
|
77
65
|
create_model
|
78
66
|
get resource_path(:index, format: :json), params: { limit: 100, include: includes }
|
79
|
-
|
67
|
+
|
80
68
|
json = JSON.parse(response.body)[0]
|
81
69
|
assert json.is_a?(Hash)
|
82
70
|
includes.each do |included|
|
@@ -11,7 +11,7 @@ module StandardAPI
|
|
11
11
|
json = JSON(@response.body)
|
12
12
|
assert json['columns']
|
13
13
|
model.columns.map do |column|
|
14
|
-
assert json['columns'][column.name]['type']
|
14
|
+
assert json['columns'][column.name]['type'], "Missing `type` for \"#{model}\" attribute \"#{column.name}\""
|
15
15
|
end
|
16
16
|
assert json['limit']
|
17
17
|
end
|
@@ -46,6 +46,7 @@ module StandardAPI
|
|
46
46
|
test '#update.json with nested attributes' do
|
47
47
|
m = create_model
|
48
48
|
attrs = attributes_for(singular_name, :nested).select{|k,v| !model.readonly_attributes.include?(k.to_s) }
|
49
|
+
mask.each { |k, v| attrs[k] = v }
|
49
50
|
create_webmocks(attrs)
|
50
51
|
|
51
52
|
file_upload = attrs.any? { |k, v| v.is_a?(Rack::Test::UploadedFile) }
|
@@ -64,7 +65,7 @@ module StandardAPI
|
|
64
65
|
end
|
65
66
|
|
66
67
|
test '#update.json with invalid attributes' do
|
67
|
-
trait =
|
68
|
+
trait = FactoryBot.factories[singular_name].definition.defined_traits.any? { |x| x.name.to_s == 'invalid' }
|
68
69
|
|
69
70
|
if !trait
|
70
71
|
Rails.logger.try(:warn, "No invalid trait for #{model.name}. Skipping invalid tests")
|
@@ -1,6 +1,4 @@
|
|
1
1
|
require 'active_support/test_case'
|
2
|
-
require 'rails-controller-testing'
|
3
|
-
Rails::Controller::Testing.install
|
4
2
|
|
5
3
|
require File.expand_path(File.join(__FILE__, '../test_case/calculate_tests'))
|
6
4
|
require File.expand_path(File.join(__FILE__, '../test_case/create_tests'))
|
@@ -45,7 +43,10 @@ module StandardAPI::TestCase
|
|
45
43
|
acc
|
46
44
|
end
|
47
45
|
|
48
|
-
|
46
|
+
test_cases = Dir.entries(File.expand_path(File.join(__FILE__, '..', 'test_case')))
|
47
|
+
test_cases.select! {|fn| fn.ends_with?('_tests.rb') }
|
48
|
+
test_cases.map! {|fn| fn.sub('_tests.rb', '') }
|
49
|
+
(klass.controller_class.action_methods & test_cases).each do |action|
|
49
50
|
if const_defined?("StandardAPI::TestCase::#{action.capitalize}Tests") && routes[klass.controller_class.controller_path][action]
|
50
51
|
klass.include("StandardAPI::TestCase::#{action.capitalize}Tests".constantize)
|
51
52
|
end
|
@@ -60,13 +61,21 @@ module StandardAPI::TestCase
|
|
60
61
|
count > 0
|
61
62
|
end
|
62
63
|
|
63
|
-
def
|
64
|
-
controller_class.new.send(:
|
64
|
+
def default_orders
|
65
|
+
controller_class.new.send(:default_orders)
|
66
|
+
end
|
67
|
+
|
68
|
+
def resource_limit
|
69
|
+
controller_class.new.send(:resource_limit)
|
65
70
|
end
|
66
71
|
|
67
72
|
def model
|
68
73
|
self.class.model
|
69
74
|
end
|
75
|
+
|
76
|
+
def mask
|
77
|
+
{}
|
78
|
+
end
|
70
79
|
|
71
80
|
def resource_path(action, options={})
|
72
81
|
url_for({
|
@@ -90,8 +99,8 @@ module StandardAPI::TestCase
|
|
90
99
|
self.class.controller_class
|
91
100
|
end
|
92
101
|
|
93
|
-
def create_model(
|
94
|
-
create(model.name.underscore,
|
102
|
+
def create_model(attrs={})
|
103
|
+
create(model.name.underscore, attrs.merge(mask))
|
95
104
|
end
|
96
105
|
|
97
106
|
def singular_name
|
data/lib/standard_api/version.rb
CHANGED
@@ -0,0 +1,63 @@
|
|
1
|
+
json.object! do
|
2
|
+
|
3
|
+
record.attributes.each do |name, value|
|
4
|
+
# Skip if attribute is included in excludes
|
5
|
+
next if defined?(excludes) && excludes[record.model_name.singular.to_sym].try(:find) { |x| x.to_s == name.to_s }
|
6
|
+
json.set! name, value
|
7
|
+
end
|
8
|
+
|
9
|
+
includes.each do |inc, subinc|
|
10
|
+
next if [:where, :order, :limit].include?(inc.to_sym)
|
11
|
+
|
12
|
+
case association = record.class.reflect_on_association(inc)
|
13
|
+
when ActiveRecord::Reflection::HasManyReflection, ActiveRecord::Reflection::HasAndBelongsToManyReflection, ActiveRecord::Reflection::ThroughReflection
|
14
|
+
can_cache = can_cache_relation?(record.class, inc, subinc)
|
15
|
+
json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
|
16
|
+
partial = model_partial(association.klass)
|
17
|
+
json.set! inc do
|
18
|
+
json.array! record.send(inc).filter(subinc[:where]).limit(subinc[:limit]).sort(subinc[:order]), partial: partial, as: partial.split('/').last, locals: { includes: subinc }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
when ActiveRecord::Reflection::BelongsToReflection, ActiveRecord::Reflection::HasOneReflection
|
23
|
+
can_cache = can_cache_relation?(record.class, inc, subinc)
|
24
|
+
if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
25
|
+
can_cache = can_cache && !record.send(association.foreign_key).nil?
|
26
|
+
end
|
27
|
+
json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
|
28
|
+
value = record.send(inc)
|
29
|
+
if value.nil?
|
30
|
+
json.set! inc, nil
|
31
|
+
else
|
32
|
+
partial = model_partial(value)
|
33
|
+
json.set! inc do
|
34
|
+
json.partial! partial, partial.split('/').last.to_sym => value, includes: subinc
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
else
|
40
|
+
if record.respond_to?(inc)
|
41
|
+
value = record.send(inc)
|
42
|
+
if value.nil?
|
43
|
+
json.set! inc, nil
|
44
|
+
elsif value.is_a?(ActiveModel::Model)
|
45
|
+
json.set! inc do
|
46
|
+
partial = model_partial(value)
|
47
|
+
json.partial! partial, partial.split('/').last.to_sym => value, includes: subinc
|
48
|
+
end
|
49
|
+
else
|
50
|
+
json.set! inc, value.as_json
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
|
57
|
+
if !record.errors.blank?
|
58
|
+
errs = record.errors.to_hash
|
59
|
+
errs.default_proc = nil
|
60
|
+
json.set! 'errors', errs
|
61
|
+
end
|
62
|
+
|
63
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
if !includes.empty? && can_cache?(model, includes)
|
2
|
+
partial = model_partial(model)
|
3
|
+
record_name = partial.split('/').last.to_sym
|
4
|
+
locals = { record_name => nil, :includes => includes}
|
5
|
+
|
6
|
+
json.cache_collection! instance_variable_get("@#{model.model_name.plural}"), key: proc {|record| cache_key(record, includes) } do |record|
|
7
|
+
locals[record_name] = record
|
8
|
+
json.partial! partial, locals
|
9
|
+
end
|
10
|
+
else
|
11
|
+
json.array! instance_variable_get("@#{model.model_name.plural}"), partial: model_partial(model), as: model_partial(model).split('/').last, includes: includes
|
12
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
|
@@ -3,6 +3,7 @@ mapping = {
|
|
3
3
|
'time without time zone' => 'datetime',
|
4
4
|
'text' => 'string',
|
5
5
|
'json' => 'hash',
|
6
|
+
'bigint' => 'integer',
|
6
7
|
'integer' => 'integer',
|
7
8
|
'character varying(255)' => 'string',
|
8
9
|
'character varying(128)' => 'string',
|
@@ -17,7 +18,8 @@ mapping = {
|
|
17
18
|
'double precision' => 'decimal',
|
18
19
|
'ltree' => 'string',
|
19
20
|
'boolean' => 'boolean',
|
20
|
-
'geometry' => 'ewkb'
|
21
|
+
'geometry' => 'ewkb',
|
22
|
+
'uuid' => 'string'
|
21
23
|
}
|
22
24
|
|
23
25
|
json.set! 'columns' do
|
@@ -0,0 +1,39 @@
|
|
1
|
+
mapping = {
|
2
|
+
'timestamp without time zone' => 'datetime',
|
3
|
+
'time without time zone' => 'datetime',
|
4
|
+
'text' => 'string',
|
5
|
+
'json' => 'hash',
|
6
|
+
'integer' => 'integer',
|
7
|
+
'character varying(255)' => 'string',
|
8
|
+
'character varying(128)' => 'string',
|
9
|
+
'character varying(50)' => 'string',
|
10
|
+
'character varying' => 'string',
|
11
|
+
'jsonb' => 'hash',
|
12
|
+
'inet' => 'string', #TODO: should be inet
|
13
|
+
'hstore' => 'hash',
|
14
|
+
'date' => 'datetime',
|
15
|
+
'numeric(16,2)' => 'decimal',
|
16
|
+
'numeric' => 'decimal',
|
17
|
+
'double precision' => 'decimal',
|
18
|
+
'ltree' => 'string',
|
19
|
+
'boolean' => 'boolean',
|
20
|
+
'geometry' => 'ewkb',
|
21
|
+
'uuid' => 'string'
|
22
|
+
}
|
23
|
+
|
24
|
+
json.object! do
|
25
|
+
json.set! 'columns' do
|
26
|
+
json.object! do
|
27
|
+
model.columns.each do |column|
|
28
|
+
json.set! column.name, {
|
29
|
+
type: mapping[column.sql_type],
|
30
|
+
primary_key: column.name == model.primary_key,
|
31
|
+
null: column.null,
|
32
|
+
array: column.array
|
33
|
+
}
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
json.set! 'limit', resource_limit
|
39
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
|
data/lib/standard_api.rb
CHANGED
@@ -2,8 +2,7 @@ require 'rails'
|
|
2
2
|
require 'action_view'
|
3
3
|
require 'action_pack'
|
4
4
|
require 'action_controller'
|
5
|
-
|
6
|
-
require 'jbuilder/railtie'
|
5
|
+
|
7
6
|
require 'active_record/filter'
|
8
7
|
require 'active_record/sort'
|
9
8
|
require 'active_support/core_ext/hash/indifferent_access'
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: standardapi
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 5.
|
4
|
+
version: 5.2.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- James Bracy
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-10-05 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -16,120 +16,114 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - "~>"
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: '5.
|
19
|
+
version: '5.2'
|
20
20
|
- - ">="
|
21
21
|
- !ruby/object:Gem::Version
|
22
|
-
version: 5.
|
22
|
+
version: 5.2.0
|
23
23
|
type: :runtime
|
24
24
|
prerelease: false
|
25
25
|
version_requirements: !ruby/object:Gem::Requirement
|
26
26
|
requirements:
|
27
27
|
- - "~>"
|
28
28
|
- !ruby/object:Gem::Version
|
29
|
-
version: '5.
|
29
|
+
version: '5.2'
|
30
30
|
- - ">="
|
31
31
|
- !ruby/object:Gem::Version
|
32
|
-
version: 5.
|
32
|
+
version: 5.2.0
|
33
33
|
- !ruby/object:Gem::Dependency
|
34
34
|
name: activesupport
|
35
35
|
requirement: !ruby/object:Gem::Requirement
|
36
36
|
requirements:
|
37
37
|
- - "~>"
|
38
38
|
- !ruby/object:Gem::Version
|
39
|
-
version: '5.
|
39
|
+
version: '5.2'
|
40
40
|
- - ">="
|
41
41
|
- !ruby/object:Gem::Version
|
42
|
-
version: 5.
|
42
|
+
version: 5.2.0
|
43
43
|
type: :runtime
|
44
44
|
prerelease: false
|
45
45
|
version_requirements: !ruby/object:Gem::Requirement
|
46
46
|
requirements:
|
47
47
|
- - "~>"
|
48
48
|
- !ruby/object:Gem::Version
|
49
|
-
version: '5.
|
49
|
+
version: '5.2'
|
50
50
|
- - ">="
|
51
51
|
- !ruby/object:Gem::Version
|
52
|
-
version: 5.
|
52
|
+
version: 5.2.0
|
53
53
|
- !ruby/object:Gem::Dependency
|
54
54
|
name: actionpack
|
55
55
|
requirement: !ruby/object:Gem::Requirement
|
56
56
|
requirements:
|
57
57
|
- - "~>"
|
58
58
|
- !ruby/object:Gem::Version
|
59
|
-
version: '5.
|
59
|
+
version: '5.2'
|
60
60
|
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
|
-
version: 5.
|
62
|
+
version: 5.2.0
|
63
63
|
type: :runtime
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
67
|
- - "~>"
|
68
68
|
- !ruby/object:Gem::Version
|
69
|
-
version: '5.
|
69
|
+
version: '5.2'
|
70
70
|
- - ">="
|
71
71
|
- !ruby/object:Gem::Version
|
72
|
-
version: 5.
|
72
|
+
version: 5.2.0
|
73
73
|
- !ruby/object:Gem::Dependency
|
74
74
|
name: activerecord-sort
|
75
75
|
requirement: !ruby/object:Gem::Requirement
|
76
76
|
requirements:
|
77
77
|
- - "~>"
|
78
78
|
- !ruby/object:Gem::Version
|
79
|
-
version: '5.
|
79
|
+
version: '5.2'
|
80
80
|
- - ">="
|
81
81
|
- !ruby/object:Gem::Version
|
82
|
-
version: 5.
|
82
|
+
version: 5.2.0
|
83
83
|
type: :runtime
|
84
84
|
prerelease: false
|
85
85
|
version_requirements: !ruby/object:Gem::Requirement
|
86
86
|
requirements:
|
87
87
|
- - "~>"
|
88
88
|
- !ruby/object:Gem::Version
|
89
|
-
version: '5.
|
89
|
+
version: '5.2'
|
90
90
|
- - ">="
|
91
91
|
- !ruby/object:Gem::Version
|
92
|
-
version: 5.
|
92
|
+
version: 5.2.0
|
93
93
|
- !ruby/object:Gem::Dependency
|
94
94
|
name: activerecord-filter
|
95
95
|
requirement: !ruby/object:Gem::Requirement
|
96
96
|
requirements:
|
97
97
|
- - "~>"
|
98
98
|
- !ruby/object:Gem::Version
|
99
|
-
version: '5.
|
99
|
+
version: '5.2'
|
100
100
|
- - ">="
|
101
101
|
- !ruby/object:Gem::Version
|
102
|
-
version: 5.
|
102
|
+
version: 5.2.0
|
103
103
|
type: :runtime
|
104
104
|
prerelease: false
|
105
105
|
version_requirements: !ruby/object:Gem::Requirement
|
106
106
|
requirements:
|
107
107
|
- - "~>"
|
108
108
|
- !ruby/object:Gem::Version
|
109
|
-
version: '5.
|
109
|
+
version: '5.2'
|
110
110
|
- - ">="
|
111
111
|
- !ruby/object:Gem::Version
|
112
|
-
version: 5.
|
112
|
+
version: 5.2.0
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
|
-
name:
|
114
|
+
name: pg
|
115
115
|
requirement: !ruby/object:Gem::Requirement
|
116
116
|
requirements:
|
117
|
-
- - "~>"
|
118
|
-
- !ruby/object:Gem::Version
|
119
|
-
version: '2.6'
|
120
117
|
- - ">="
|
121
118
|
- !ruby/object:Gem::Version
|
122
|
-
version:
|
123
|
-
type: :
|
119
|
+
version: '0'
|
120
|
+
type: :development
|
124
121
|
prerelease: false
|
125
122
|
version_requirements: !ruby/object:Gem::Requirement
|
126
123
|
requirements:
|
127
|
-
- - "~>"
|
128
|
-
- !ruby/object:Gem::Version
|
129
|
-
version: '2.6'
|
130
124
|
- - ">="
|
131
125
|
- !ruby/object:Gem::Version
|
132
|
-
version:
|
126
|
+
version: '0'
|
133
127
|
- !ruby/object:Gem::Dependency
|
134
128
|
name: bundler
|
135
129
|
requirement: !ruby/object:Gem::Requirement
|
@@ -145,7 +139,7 @@ dependencies:
|
|
145
139
|
- !ruby/object:Gem::Version
|
146
140
|
version: '0'
|
147
141
|
- !ruby/object:Gem::Dependency
|
148
|
-
name:
|
142
|
+
name: jbuilder
|
149
143
|
requirement: !ruby/object:Gem::Requirement
|
150
144
|
requirements:
|
151
145
|
- - ">="
|
@@ -159,7 +153,7 @@ dependencies:
|
|
159
153
|
- !ruby/object:Gem::Version
|
160
154
|
version: '0'
|
161
155
|
- !ruby/object:Gem::Dependency
|
162
|
-
name:
|
156
|
+
name: rake
|
163
157
|
requirement: !ruby/object:Gem::Requirement
|
164
158
|
requirements:
|
165
159
|
- - ">="
|
@@ -173,7 +167,7 @@ dependencies:
|
|
173
167
|
- !ruby/object:Gem::Version
|
174
168
|
version: '0'
|
175
169
|
- !ruby/object:Gem::Dependency
|
176
|
-
name: minitest
|
170
|
+
name: minitest
|
177
171
|
requirement: !ruby/object:Gem::Requirement
|
178
172
|
requirements:
|
179
173
|
- - ">="
|
@@ -187,7 +181,7 @@ dependencies:
|
|
187
181
|
- !ruby/object:Gem::Version
|
188
182
|
version: '0'
|
189
183
|
- !ruby/object:Gem::Dependency
|
190
|
-
name:
|
184
|
+
name: minitest-reporters
|
191
185
|
requirement: !ruby/object:Gem::Requirement
|
192
186
|
requirements:
|
193
187
|
- - ">="
|
@@ -201,7 +195,7 @@ dependencies:
|
|
201
195
|
- !ruby/object:Gem::Version
|
202
196
|
version: '0'
|
203
197
|
- !ruby/object:Gem::Dependency
|
204
|
-
name:
|
198
|
+
name: simplecov
|
205
199
|
requirement: !ruby/object:Gem::Requirement
|
206
200
|
requirements:
|
207
201
|
- - ">="
|
@@ -215,7 +209,7 @@ dependencies:
|
|
215
209
|
- !ruby/object:Gem::Version
|
216
210
|
version: '0'
|
217
211
|
- !ruby/object:Gem::Dependency
|
218
|
-
name:
|
212
|
+
name: factory_bot_rails
|
219
213
|
requirement: !ruby/object:Gem::Requirement
|
220
214
|
requirements:
|
221
215
|
- - ">="
|
@@ -229,7 +223,7 @@ dependencies:
|
|
229
223
|
- !ruby/object:Gem::Version
|
230
224
|
version: '0'
|
231
225
|
- !ruby/object:Gem::Dependency
|
232
|
-
name:
|
226
|
+
name: faker
|
233
227
|
requirement: !ruby/object:Gem::Requirement
|
234
228
|
requirements:
|
235
229
|
- - ">="
|
@@ -243,7 +237,7 @@ dependencies:
|
|
243
237
|
- !ruby/object:Gem::Version
|
244
238
|
version: '0'
|
245
239
|
- !ruby/object:Gem::Dependency
|
246
|
-
name:
|
240
|
+
name: byebug
|
247
241
|
requirement: !ruby/object:Gem::Requirement
|
248
242
|
requirements:
|
249
243
|
- - ">="
|
@@ -257,7 +251,7 @@ dependencies:
|
|
257
251
|
- !ruby/object:Gem::Version
|
258
252
|
version: '0'
|
259
253
|
- !ruby/object:Gem::Dependency
|
260
|
-
name:
|
254
|
+
name: mocha
|
261
255
|
requirement: !ruby/object:Gem::Requirement
|
262
256
|
requirements:
|
263
257
|
- - ">="
|
@@ -299,11 +293,15 @@ files:
|
|
299
293
|
- lib/standard_api/test_case/update_tests.rb
|
300
294
|
- lib/standard_api/version.rb
|
301
295
|
- lib/standard_api/views/application/_record.json.jbuilder
|
296
|
+
- lib/standard_api/views/application/_record.streamer
|
302
297
|
- lib/standard_api/views/application/index.json.jbuilder
|
298
|
+
- lib/standard_api/views/application/index.streamer
|
303
299
|
- lib/standard_api/views/application/new.json.jbuilder
|
300
|
+
- lib/standard_api/views/application/new.streamer
|
304
301
|
- lib/standard_api/views/application/schema.json.jbuilder
|
305
|
-
- lib/standard_api/views/application/
|
302
|
+
- lib/standard_api/views/application/schema.streamer
|
306
303
|
- lib/standard_api/views/application/show.json.jbuilder
|
304
|
+
- lib/standard_api/views/application/show.streamer
|
307
305
|
homepage: https://github.com/waratuman/standardapi
|
308
306
|
licenses:
|
309
307
|
- MIT
|
@@ -326,7 +324,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
326
324
|
version: '0'
|
327
325
|
requirements: []
|
328
326
|
rubyforge_project:
|
329
|
-
rubygems_version: 2.
|
327
|
+
rubygems_version: 2.7.6
|
330
328
|
signing_key:
|
331
329
|
specification_version: 4
|
332
330
|
summary: StandardAPI makes it easy to expose a query interface for your Rails models
|
File without changes
|