standardapi 6.0.0.26 → 6.1.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 +4 -4
- data/README.md +15 -6
- data/lib/standard_api.rb +5 -0
- data/lib/standard_api/access_control_list.rb +114 -0
- data/lib/standard_api/active_record/connection_adapters/postgresql/schema_statements.rb +21 -0
- data/lib/standard_api/controller.rb +75 -78
- data/lib/standard_api/errors.rb +9 -0
- data/lib/standard_api/helpers.rb +66 -13
- data/lib/standard_api/includes.rb +9 -0
- data/lib/standard_api/middleware/query_encoding.rb +3 -3
- data/lib/standard_api/railtie.rb +13 -2
- data/lib/standard_api/route_helpers.rb +5 -5
- data/lib/standard_api/test_case.rb +24 -14
- data/lib/standard_api/test_case/calculate_tests.rb +10 -4
- data/lib/standard_api/test_case/create_tests.rb +13 -15
- data/lib/standard_api/test_case/index_tests.rb +14 -4
- data/lib/standard_api/test_case/schema_tests.rb +25 -3
- data/lib/standard_api/test_case/show_tests.rb +1 -0
- data/lib/standard_api/test_case/update_tests.rb +8 -9
- data/lib/standard_api/version.rb +1 -1
- data/lib/standard_api/views/application/_record.json.jbuilder +33 -30
- data/lib/standard_api/views/application/_record.streamer +36 -34
- data/lib/standard_api/views/application/_schema.json.jbuilder +68 -0
- data/lib/standard_api/views/application/_schema.streamer +78 -0
- data/lib/standard_api/views/application/new.streamer +1 -1
- data/lib/standard_api/views/application/schema.json.jbuilder +1 -12
- data/lib/standard_api/views/application/schema.streamer +1 -16
- data/test/standard_api/caching_test.rb +43 -0
- data/test/standard_api/helpers_test.rb +172 -0
- data/test/standard_api/performance.rb +39 -0
- data/test/standard_api/route_helpers_test.rb +33 -0
- data/test/standard_api/standard_api_test.rb +699 -0
- data/test/standard_api/test_app.rb +1 -0
- data/test/standard_api/test_app/app/controllers/acl/account_acl.rb +15 -0
- data/test/standard_api/test_app/app/controllers/acl/property_acl.rb +27 -0
- data/test/standard_api/test_app/app/controllers/acl/reference_acl.rb +7 -0
- data/test/standard_api/test_app/controllers.rb +13 -45
- data/test/standard_api/test_app/models.rb +38 -4
- data/test/standard_api/test_app/test/factories.rb +4 -3
- data/test/standard_api/test_app/views/photos/_photo.json.jbuilder +1 -0
- data/test/standard_api/test_app/views/photos/_photo.streamer +18 -0
- data/test/standard_api/test_app/views/photos/_schema.json.jbuilder +1 -0
- data/test/standard_api/test_app/views/photos/_schema.streamer +3 -0
- data/test/standard_api/test_app/views/photos/schema.json.jbuilder +1 -1
- data/test/standard_api/test_app/views/photos/schema.streamer +1 -0
- data/test/standard_api/test_helper.rb +238 -0
- metadata +33 -17
- data/test/standard_api/test_app/log/test.log +0 -129516
@@ -37,10 +37,10 @@ module StandardAPI
|
|
37
37
|
|
38
38
|
test '#index.json params[:limit] does not exceed maximum limit' do
|
39
39
|
return if !resource_limit || resource_limit == Float::INFINITY
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
|
41
|
+
get resource_path(:index, format: :json), params: { limit: resource_limit + 1 }
|
42
|
+
assert_response :bad_request
|
43
|
+
assert_equal 'found unpermitted parameters: :limit, 1001', response.body
|
44
44
|
end
|
45
45
|
|
46
46
|
test '#index.json params[:where]' do
|
@@ -69,9 +69,12 @@ module StandardAPI
|
|
69
69
|
end
|
70
70
|
|
71
71
|
test '#index.json params[:include]' do
|
72
|
+
next if includes.empty?
|
73
|
+
|
72
74
|
travel_to Time.now do
|
73
75
|
create_model
|
74
76
|
get resource_path(:index, format: :json), params: { limit: 100, include: includes }
|
77
|
+
assert_response :ok
|
75
78
|
|
76
79
|
json = JSON.parse(response.body)[0]
|
77
80
|
assert json.is_a?(Hash)
|
@@ -128,6 +131,13 @@ module StandardAPI
|
|
128
131
|
models = @controller.instance_variable_get("@#{plural_name}")
|
129
132
|
assert_equal model.where(id: m.id).sort(required_orders).to_sql, models.to_sql
|
130
133
|
@controller.current_mask.delete(plural_name)
|
134
|
+
|
135
|
+
@controller.current_mask[plural_name.to_sym] = { id: m.id }
|
136
|
+
get :index, format: :json
|
137
|
+
models = @controller.instance_variable_get("@#{plural_name}")
|
138
|
+
assert_equal model.where(id: m.id).sort(required_orders).to_sql, models.to_sql
|
139
|
+
@controller.current_mask.delete(plural_name.to_sym)
|
140
|
+
|
131
141
|
end
|
132
142
|
end
|
133
143
|
end
|
@@ -9,13 +9,35 @@ module StandardAPI
|
|
9
9
|
get resource_path(:schema, format: :json)
|
10
10
|
assert_response :ok
|
11
11
|
json = JSON(@response.body)
|
12
|
-
assert json['
|
12
|
+
assert json['attributes']
|
13
|
+
|
13
14
|
model.columns.map do |column|
|
14
|
-
|
15
|
+
actual_column = json['attributes'][column.name]
|
16
|
+
assert_not_nil actual_column['type'], "Missing `type` for \"#{model}\" attribute \"#{column.name}\""
|
17
|
+
assert_equal_or_nil model.primary_key == column.name, actual_column['primary_key']
|
18
|
+
assert_equal_or_nil column.null, actual_column['null']
|
19
|
+
assert_equal_or_nil column.array, actual_column['array']
|
20
|
+
assert_equal_or_nil column.comment, actual_column['comment']
|
21
|
+
|
22
|
+
if column.default
|
23
|
+
default = model.connection.lookup_cast_type_from_column(column).deserialize(column.default)
|
24
|
+
assert_equal default, actual_column['default']
|
25
|
+
else
|
26
|
+
assert_nil column.default
|
27
|
+
end
|
15
28
|
end
|
29
|
+
|
16
30
|
assert json['limit']
|
31
|
+
assert_equal_or_nil model.connection.table_comment(model.table_name), json['comment']
|
17
32
|
end
|
18
33
|
|
34
|
+
def assert_equal_or_nil(expected, actual, msg=nil)
|
35
|
+
if expected.nil?
|
36
|
+
assert_nil actual, msg
|
37
|
+
else
|
38
|
+
assert_equal expected, actual, msg
|
39
|
+
end
|
40
|
+
end
|
19
41
|
end
|
20
42
|
end
|
21
|
-
end
|
43
|
+
end
|
@@ -16,7 +16,7 @@ module StandardAPI
|
|
16
16
|
put resource_path(:update, :id => m.id, format: format), params: { singular_name => attrs }, as: as
|
17
17
|
assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
|
18
18
|
|
19
|
-
|
19
|
+
update_attributes(m.reload).select { |x| attrs.keys.map(&:to_s).include?(x) }.each do |key, value|
|
20
20
|
message = "Model / Attribute: #{m.class.name}##{key}"
|
21
21
|
if value.is_a?(BigDecimal)
|
22
22
|
assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]).to_s.to_f, value.to_s.to_f, message
|
@@ -34,7 +34,7 @@ module StandardAPI
|
|
34
34
|
get resource_path(:show, id: m.id), as: :json
|
35
35
|
|
36
36
|
return if @controller.method(:update).owner != StandardAPI
|
37
|
-
|
37
|
+
|
38
38
|
attrs = attributes_for(singular_name).select{|k,v| !model.readonly_attributes.include?(k.to_s) }
|
39
39
|
create_webmocks(attrs)
|
40
40
|
|
@@ -57,9 +57,9 @@ module StandardAPI
|
|
57
57
|
assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
|
58
58
|
|
59
59
|
# (m.attribute_names & attrs.keys.map(&:to_s)).each do |test_key|
|
60
|
-
|
60
|
+
update_attributes(m.reload).select { |x| attrs.keys.map(&:to_s).include?(x) }.each do |key, value|
|
61
61
|
message = "Model / Attribute: #{m.class.name}##{key}"
|
62
|
-
assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]), value, message
|
62
|
+
assert_equal_or_nil normalize_attribute(m, key, attrs[key.to_sym]), normalize_attribute(m, key, value), message
|
63
63
|
end
|
64
64
|
assert JSON.parse(@response.body).is_a?(Hash)
|
65
65
|
end
|
@@ -68,8 +68,7 @@ module StandardAPI
|
|
68
68
|
trait = FactoryBot.factories[singular_name].definition.defined_traits.any? { |x| x.name.to_s == 'invalid' }
|
69
69
|
|
70
70
|
if !trait
|
71
|
-
|
72
|
-
warn("No invalid trait for #{model.name}. Skipping invalid tests")
|
71
|
+
skip("No invalid trait for #{model.name}. Skipping invalid tests")
|
73
72
|
return
|
74
73
|
end
|
75
74
|
|
@@ -94,7 +93,7 @@ module StandardAPI
|
|
94
93
|
|
95
94
|
put resource_path(:update, :id => m.id, format: format), params: { include: includes, singular_name => attrs }, as: as
|
96
95
|
assert_response :ok, "Updating #{m.class.name} with #{attrs.inspect}"
|
97
|
-
|
96
|
+
|
98
97
|
controller_model = @controller.instance_variable_get("@#{singular_name}")
|
99
98
|
json = JSON.parse(response.body)
|
100
99
|
includes.each do |included|
|
@@ -104,7 +103,7 @@ module StandardAPI
|
|
104
103
|
next if !association
|
105
104
|
|
106
105
|
if ['belongs_to', 'has_one'].include?(association.macro.to_s)
|
107
|
-
|
106
|
+
update_attributes(controller_model.send(included)) do |key, value|
|
108
107
|
message = "Model / Attribute: #{controller_model.send(included).class.name}##{key}"
|
109
108
|
assert_equal json[included.to_s][key.to_s], value, message
|
110
109
|
end
|
@@ -118,7 +117,7 @@ module StandardAPI
|
|
118
117
|
nil
|
119
118
|
end
|
120
119
|
|
121
|
-
|
120
|
+
update_attributes(m).each do |key, value|
|
122
121
|
message = "Model / Attribute: #{m.class.name}##{key}"
|
123
122
|
if m_json[key.to_s].nil?
|
124
123
|
assert_nil normalize_to_json(m, key, value), message
|
data/lib/standard_api/version.rb
CHANGED
@@ -6,39 +6,42 @@ end
|
|
6
6
|
|
7
7
|
includes.each do |inc, subinc|
|
8
8
|
next if ["limit", "offset", "order", "when", "where", "distinct", "distinct_on"].include?(inc)
|
9
|
-
|
9
|
+
|
10
10
|
case association = record.class.reflect_on_association(inc)
|
11
|
-
when ActiveRecord::Reflection::
|
12
|
-
|
13
|
-
|
14
|
-
partial = model_partial(association.klass)
|
11
|
+
when ActiveRecord::Reflection::AbstractReflection
|
12
|
+
if association.collection?
|
13
|
+
can_cache = can_cache_relation?(record, inc, subinc)
|
15
14
|
json.set! inc do
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
sub_records = sub_records.order(subinc['order']) if subinc['order']
|
22
|
-
sub_records = sub_records.filter(subinc['where']) if subinc['where']
|
23
|
-
sub_records = sub_records.distinct if subinc['distinct']
|
24
|
-
sub_records = sub_records.distinct_on(subinc['distinct_on']) if subinc['distinct_on']
|
15
|
+
json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
|
16
|
+
partial = model_partial(association.klass)
|
17
|
+
|
18
|
+
# TODO limit causes preloaded assocations to reload
|
19
|
+
sub_records = record.send(inc)
|
25
20
|
|
26
|
-
|
21
|
+
sub_records = sub_records.limit(subinc['limit']) if subinc['limit']
|
22
|
+
sub_records = sub_records.offset(subinc['offset']) if subinc['offset']
|
23
|
+
sub_records = sub_records.reorder(subinc['order']) if subinc['order']
|
24
|
+
sub_records = sub_records.filter(subinc['where']) if subinc['where']
|
25
|
+
sub_records = sub_records.distinct if subinc['distinct']
|
26
|
+
sub_records = sub_records.distinct_on(subinc['distinct_on']) if subinc['distinct_on']
|
27
|
+
|
28
|
+
json.array! sub_records, partial: partial, as: partial.split('/').last, locals: { includes: subinc }
|
29
|
+
end
|
27
30
|
end
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
31
|
+
else
|
32
|
+
can_cache = can_cache_relation?(record, inc, subinc)
|
33
|
+
if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
34
|
+
can_cache = can_cache && !record.send(association.foreign_key).nil?
|
35
|
+
end
|
36
|
+
json.set! inc do
|
37
|
+
json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
|
38
|
+
value = record.send(inc)
|
39
|
+
if value.nil?
|
40
|
+
json.null!
|
41
|
+
else
|
42
|
+
partial = model_partial(value)
|
43
|
+
json.partial! partial, partial.split('/').last.to_sym => value, includes: subinc
|
44
|
+
end
|
42
45
|
end
|
43
46
|
end
|
44
47
|
end
|
@@ -57,7 +60,7 @@ includes.each do |inc, subinc|
|
|
57
60
|
end
|
58
61
|
end
|
59
62
|
end
|
60
|
-
|
63
|
+
|
61
64
|
end
|
62
65
|
|
63
66
|
if !record.errors.blank?
|
@@ -1,5 +1,5 @@
|
|
1
1
|
json.object! do
|
2
|
-
|
2
|
+
|
3
3
|
record.attributes.each do |name, value|
|
4
4
|
# Skip if attribute is included in excludes
|
5
5
|
next if defined?(excludes) && excludes[record.model_name.singular.to_sym].try(:find) { |x| x.to_s == name.to_s }
|
@@ -8,39 +8,41 @@ json.object! do
|
|
8
8
|
|
9
9
|
includes.each do |inc, subinc|
|
10
10
|
next if ["limit", "offset", "order", "when", "where", "distinct", "distinct_on"].include?(inc)
|
11
|
-
|
11
|
+
|
12
12
|
case association = record.class.reflect_on_association(inc)
|
13
|
-
when ActiveRecord::Reflection::
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
13
|
+
when ActiveRecord::Reflection::AbstractReflection
|
14
|
+
if association.collection?
|
15
|
+
can_cache = can_cache_relation?(record, inc, subinc)
|
16
|
+
json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
|
17
|
+
json.set! inc do
|
18
|
+
partial = model_partial(association.klass)
|
19
|
+
# TODO limit causes preloaded assocations to reload
|
20
|
+
sub_records = record.send(inc)
|
20
21
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
22
|
+
sub_records = sub_records.limit(subinc["limit"]) if subinc["limit"]
|
23
|
+
sub_records = sub_records.offset(subinc["offset"]) if subinc["offset"]
|
24
|
+
sub_records = sub_records.reorder(subinc["order"]) if subinc["order"]
|
25
|
+
sub_records = sub_records.filter(subinc["where"]) if subinc["where"]
|
26
|
+
sub_records = sub_records.distinct if subinc["distinct"]
|
27
|
+
sub_records = sub_records.distinct_on(subinc["distinct_on"]) if subinc["distinct_on"]
|
27
28
|
|
28
|
-
|
29
|
+
json.array! sub_records, partial: partial, as: partial.split("/").last, locals: { includes: subinc }
|
30
|
+
end
|
29
31
|
end
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
json.cache_if!(can_cache, can_cache ? association_cache_key(record, inc, subinc) : nil) do
|
37
|
-
value = record.send(inc)
|
38
|
-
if value.nil?
|
39
|
-
json.set! inc, nil
|
40
|
-
else
|
41
|
-
partial = model_partial(value)
|
32
|
+
else
|
33
|
+
can_cache = can_cache_relation?(record, inc, subinc)
|
34
|
+
if association.is_a?(ActiveRecord::Reflection::BelongsToReflection)
|
35
|
+
can_cache = can_cache && !record.send(association.foreign_key).nil?
|
36
|
+
end
|
37
|
+
json.cache_if!(can_cache, can_cache ? [inc, association_cache_key(record, inc, subinc)] : nil) do
|
42
38
|
json.set! inc do
|
43
|
-
|
39
|
+
value = record.send(inc)
|
40
|
+
if value.nil?
|
41
|
+
json.value! nil
|
42
|
+
else
|
43
|
+
partial = model_partial(value)
|
44
|
+
json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
|
45
|
+
end
|
44
46
|
end
|
45
47
|
end
|
46
48
|
end
|
@@ -52,20 +54,20 @@ json.object! do
|
|
52
54
|
elsif value.is_a?(ActiveModel::Model)
|
53
55
|
json.set! inc do
|
54
56
|
partial = model_partial(value)
|
55
|
-
json.partial! partial, partial.split(
|
57
|
+
json.partial! partial, partial.split("/").last.to_sym => value, includes: subinc
|
56
58
|
end
|
57
59
|
else
|
58
60
|
json.set! inc, value.as_json
|
59
61
|
end
|
60
62
|
end
|
61
63
|
end
|
62
|
-
|
64
|
+
|
63
65
|
end
|
64
|
-
|
66
|
+
|
65
67
|
if !record.errors.blank?
|
66
68
|
errs = record.errors.to_hash
|
67
69
|
errs.default_proc = nil
|
68
|
-
json.set!
|
70
|
+
json.set! "errors", errs
|
69
71
|
end
|
70
|
-
|
72
|
+
|
71
73
|
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
if model.nil? && controller_name == "application"
|
2
|
+
routes = Rails.application.routes.routes.reject(&:internal).collect do |route|
|
3
|
+
{ name: route.name,
|
4
|
+
verb: route.verb,
|
5
|
+
path: route.path.spec.to_s.gsub(/\(\.format\)\Z/, ''),
|
6
|
+
controller: route.requirements[:controller],
|
7
|
+
action: route.requirements[:action],
|
8
|
+
array: ['index'].include?(route.requirements[:action]) }
|
9
|
+
end
|
10
|
+
|
11
|
+
json.set! 'comment', ActiveRecord::Base.connection.database_comment
|
12
|
+
|
13
|
+
json.set! 'routes' do
|
14
|
+
json.array!(routes) do |route|
|
15
|
+
controller = if controller_name = route[:controller]
|
16
|
+
begin
|
17
|
+
controller_param = controller_name.underscore
|
18
|
+
const_name = "#{controller_param.camelize}Controller"
|
19
|
+
const = ActiveSupport::Dependencies.constantize(const_name)
|
20
|
+
if const.ancestors.include?(StandardAPI::Controller)
|
21
|
+
const
|
22
|
+
else
|
23
|
+
nil
|
24
|
+
end
|
25
|
+
rescue NameError
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
next if controller.nil?
|
30
|
+
|
31
|
+
resource_limit = controller.resource_limit if controller.respond_to?(:resource_limit)
|
32
|
+
|
33
|
+
json.set! 'path', route[:path]
|
34
|
+
json.set! 'method', route[:verb]
|
35
|
+
json.set! 'model', controller.model&.name
|
36
|
+
json.set! 'array', route[:array]
|
37
|
+
json.set! 'limit', resource_limit
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
json.set! 'models' do
|
42
|
+
models.each do |model|
|
43
|
+
json.set! model.name do
|
44
|
+
json.partial! partial: schema_partial(model), model: model
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
else
|
50
|
+
|
51
|
+
json.set! 'attributes' do
|
52
|
+
model.columns.each do |column|
|
53
|
+
json.set! column.name, {
|
54
|
+
type: json_column_type(column.sql_type),
|
55
|
+
default: column.default ? model.connection.lookup_cast_type_from_column(column).deserialize(column.default) : nil,
|
56
|
+
primary_key: column.name == model.primary_key,
|
57
|
+
null: column.null,
|
58
|
+
array: column.array,
|
59
|
+
comment: column.comment
|
60
|
+
}
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
json.set! 'limit', resource_limit # This should be removed?
|
65
|
+
json.set! 'comment', model.connection.table_comment(model.table_name)
|
66
|
+
|
67
|
+
end
|
68
|
+
|
@@ -0,0 +1,78 @@
|
|
1
|
+
if model.nil? && controller_name == "application"
|
2
|
+
routes = Rails.application.routes.routes.reject(&:internal).collect do |route|
|
3
|
+
{ name: route.name,
|
4
|
+
verb: route.verb,
|
5
|
+
path: route.path.spec.to_s.gsub(/\(\.:format\)\Z/, ''),
|
6
|
+
controller: route.requirements[:controller],
|
7
|
+
action: route.requirements[:action],
|
8
|
+
array: ['index'].include?(route.requirements[:action]) }
|
9
|
+
end
|
10
|
+
|
11
|
+
json.object! do
|
12
|
+
json.set! 'comment', ActiveRecord::Base.connection.database_comment
|
13
|
+
|
14
|
+
json.set! 'routes' do
|
15
|
+
json.array!(routes) do |route|
|
16
|
+
controller = if controller_name = route[:controller]
|
17
|
+
begin
|
18
|
+
controller_param = controller_name.underscore
|
19
|
+
const_name = "#{controller_param.camelize}Controller"
|
20
|
+
const = ActiveSupport::Dependencies.constantize(const_name)
|
21
|
+
if const.ancestors.include?(StandardAPI::Controller)
|
22
|
+
const
|
23
|
+
else
|
24
|
+
nil
|
25
|
+
end
|
26
|
+
rescue NameError
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
next if controller.nil?
|
31
|
+
|
32
|
+
resource_limit = controller.resource_limit if controller.respond_to?(:resource_limit)
|
33
|
+
|
34
|
+
json.object! do
|
35
|
+
json.set! 'path', route[:path]
|
36
|
+
json.set! 'method', route[:verb]
|
37
|
+
json.set! 'model', controller.model&.name
|
38
|
+
json.set! 'array', route[:array]
|
39
|
+
json.set! 'limit', resource_limit
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
|
45
|
+
json.set! 'models' do
|
46
|
+
json.object! do
|
47
|
+
models.each do |model|
|
48
|
+
json.set! model.name do
|
49
|
+
json.partial!(schema_partial(model), model: model)
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
else
|
57
|
+
|
58
|
+
json.object! do
|
59
|
+
json.set! 'attributes' do
|
60
|
+
json.object! do
|
61
|
+
model.columns.each do |column|
|
62
|
+
json.set! column.name, {
|
63
|
+
type: json_column_type(column.sql_type),
|
64
|
+
default: column.default ? model.connection.lookup_cast_type_from_column(column).deserialize(column.default) : nil,
|
65
|
+
primary_key: column.name == model.primary_key,
|
66
|
+
null: column.null,
|
67
|
+
array: column.array,
|
68
|
+
comment: column.comment
|
69
|
+
}
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
json.set! 'limit', resource_limit
|
75
|
+
json.set! 'comment', model.connection.table_comment(model.table_name)
|
76
|
+
end
|
77
|
+
|
78
|
+
end
|