standardapi 6.0.0.15 → 6.0.0.29

Sign up to get free protection for your applications and to get access to all the features.
Files changed (40) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +15 -6
  3. data/lib/standard_api.rb +2 -0
  4. data/lib/standard_api/active_record/connection_adapters/postgresql/schema_statements.rb +21 -0
  5. data/lib/standard_api/controller.rb +77 -66
  6. data/lib/standard_api/errors.rb +13 -0
  7. data/lib/standard_api/helpers.rb +67 -15
  8. data/lib/standard_api/includes.rb +22 -12
  9. data/lib/standard_api/orders.rb +4 -6
  10. data/lib/standard_api/railtie.rb +1 -1
  11. data/lib/standard_api/route_helpers.rb +4 -0
  12. data/lib/standard_api/test_case/calculate_tests.rb +5 -3
  13. data/lib/standard_api/test_case/create_tests.rb +0 -3
  14. data/lib/standard_api/test_case/schema_tests.rb +19 -3
  15. data/lib/standard_api/version.rb +1 -1
  16. data/lib/standard_api/views/application/_record.json.jbuilder +11 -10
  17. data/lib/standard_api/views/application/_record.streamer +11 -10
  18. data/lib/standard_api/views/application/_schema.json.jbuilder +68 -0
  19. data/lib/standard_api/views/application/_schema.streamer +78 -0
  20. data/lib/standard_api/views/application/index.json.jbuilder +9 -16
  21. data/lib/standard_api/views/application/index.streamer +9 -16
  22. data/lib/standard_api/views/application/schema.json.jbuilder +1 -12
  23. data/lib/standard_api/views/application/schema.streamer +1 -16
  24. data/lib/standard_api/views/application/show.json.jbuilder +8 -1
  25. data/lib/standard_api/views/application/show.streamer +8 -1
  26. data/test/standard_api/test_app.rb +55 -0
  27. data/test/standard_api/test_app/config/database.yml +4 -0
  28. data/test/standard_api/test_app/controllers.rb +107 -0
  29. data/test/standard_api/test_app/models.rb +94 -0
  30. data/test/standard_api/test_app/test/factories.rb +50 -0
  31. data/test/standard_api/test_app/test/fixtures/photo.png +0 -0
  32. data/test/standard_api/test_app/views/photos/_photo.json.jbuilder +15 -0
  33. data/test/standard_api/test_app/views/photos/_photo.streamer +17 -0
  34. data/test/standard_api/test_app/views/photos/_schema.json.jbuilder +1 -0
  35. data/test/standard_api/test_app/views/photos/_schema.streamer +3 -0
  36. data/test/standard_api/test_app/views/photos/schema.json.jbuilder +1 -0
  37. data/test/standard_api/test_app/views/photos/schema.streamer +1 -0
  38. data/test/standard_api/test_app/views/properties/edit.html.erb +1 -0
  39. data/test/standard_api/test_app/views/sessions/new.html.erb +0 -0
  40. metadata +27 -8
@@ -1,20 +1,17 @@
1
- if !includes.empty?
2
- instance_variable_set("@#{model.model_name.plural}", preloadables(instance_variable_get("@#{model.model_name.plural}"), includes))
1
+ if !defined?(records)
2
+ records = instance_variable_get("@#{model.model_name.plural}")
3
3
  end
4
4
 
5
+ partial = model_partial(model)
6
+ partial_record_name = partial.split('/').last.to_sym
7
+
5
8
  if !includes.empty? && can_cache?(model, includes)
6
- partial = model_partial(model)
7
- record_name = partial.split('/').last.to_sym
8
-
9
- json.cache_collection! instance_variable_get("@#{model.model_name.plural}"), key: proc {|record| cache_key(record, includes) } do |record|
10
- locals = { record: record, record_name => record, :includes => includes }
11
- json.partial! partial, locals
9
+ json.cache_collection! records, key: proc { |record| cache_key(record, includes) } do |record|
10
+ json.partial!(partial, includes: includes, partial_record_name => record)
12
11
  end
13
12
  else
14
- partial = model_partial(model)
15
- record_name = partial.split('/').last.to_sym
16
13
  json.array! do
17
- instance_variable_get("@#{model.model_name.plural}").each do |record|
14
+ records.each do |record|
18
15
  sub_includes = includes.select do |key, value|
19
16
  case value
20
17
  when Hash, ActionController::Parameters
@@ -28,11 +25,7 @@ else
28
25
  end
29
26
  end
30
27
 
31
- json.partial! partial, {
32
- record: record,
33
- record_name => record,
34
- includes: sub_includes
35
- }
28
+ json.partial!(partial, includes: sub_includes, partial_record_name => record)
36
29
  end
37
30
  end
38
31
  end
@@ -1,12 +1 @@
1
- json.set! 'columns' do
2
- model.columns.each do |column|
3
- json.set! column.name, {
4
- type: json_column_type(column.sql_type),
5
- primary_key: column.name == model.primary_key,
6
- null: column.null,
7
- array: column.array
8
- }
9
- end
10
- end
11
-
12
- json.set! 'limit', resource_limit
1
+ json.partial!('schema', model: model)
@@ -1,16 +1 @@
1
- json.object! do
2
- json.set! 'columns' do
3
- json.object! do
4
- model.columns.each do |column|
5
- json.set! column.name, {
6
- type: json_column_type(column.sql_type),
7
- primary_key: column.name == model.primary_key,
8
- null: column.null,
9
- array: column.array
10
- }
11
- end
12
- end
13
- end
14
-
15
- json.set! 'limit', resource_limit
16
- end
1
+ json.partial!('schema', model: model)
@@ -1 +1,8 @@
1
- json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
1
+ if !defined?(record)
2
+ record = instance_variable_get("@#{model.model_name.singular}")
3
+ end
4
+
5
+ partial = model_partial(model)
6
+ partial_record_name = partial.split('/').last.to_sym
7
+
8
+ json.partial!(partial, partial_record_name => record, includes: includes)
@@ -1 +1,8 @@
1
- json.partial! model_partial(model), model_partial(model).split('/').last.to_sym => instance_variable_get("@#{model.model_name.singular}"), includes: includes
1
+ if !defined?(record)
2
+ record = instance_variable_get("@#{model.model_name.singular}")
3
+ end
4
+
5
+ partial = model_partial(model)
6
+ partial_record_name = partial.split('/').last.to_sym
7
+
8
+ json.partial!(partial, partial_record_name => record, includes: includes)
@@ -0,0 +1,55 @@
1
+ require "rails"
2
+ require "active_model/railtie"
3
+ require "active_record/railtie"
4
+ require "action_controller/railtie"
5
+ require "action_view/railtie"
6
+ require "rails/test_unit/railtie"
7
+ Bundler.require(*Rails.groups)
8
+
9
+ require 'standard_api'
10
+
11
+ # Test Application Config
12
+ Rails.env = 'test'
13
+
14
+ class TestApplication < Rails::Application
15
+ config.root = File.join(File.dirname(__FILE__), 'test_app')
16
+ config.secret_key_base = 'test key base'
17
+ config.eager_load = true
18
+ config.cache_classes = true
19
+ config.action_controller.perform_caching = true
20
+ config.cache_store = :memory_store, { size: 8.megabytes }
21
+ config.action_dispatch.show_exceptions = false
22
+
23
+ # if defined?(FactoryBotRails)
24
+ # config.factory_bot.definition_file_paths += [ '../factories' ]
25
+ # end
26
+ end
27
+
28
+ # Test Application initialization
29
+ TestApplication.initialize!
30
+
31
+ # Test Application Models
32
+ require 'standard_api/test_app/models'
33
+
34
+ # Test Application Controllers
35
+ require 'standard_api/test_app/controllers'
36
+
37
+ # Test Application Routes
38
+ Rails.application.routes.draw do
39
+ get :tables, to: 'application#tables', as: :tables
40
+ get :schema, to: 'application#schema', as: :schema
41
+
42
+ [:properties, :photos, :documents, :references, :sessions, :unlimited, :default_limit].each do |r|
43
+ standard_resources r
44
+ end
45
+
46
+ standard_resource :account
47
+ end
48
+
49
+ # Test Application Helpers
50
+ Object.const_set(:ApplicationHelper, Module.new)
51
+
52
+ # require 'turbostreamer'
53
+ # require 'wankel'
54
+ # ActionView::Template.unregister_template_handler :jbuilder
55
+ # ActionView::Template.register_template_handler :streamer, TurboStreamer::Handler
@@ -0,0 +1,4 @@
1
+ test:
2
+ adapter: postgresql
3
+ database: standardapi-test
4
+ encoding: utf8
@@ -0,0 +1,107 @@
1
+ class ApplicationController < ActionController::Base
2
+ include StandardAPI::Controller
3
+ prepend_view_path File.join(File.dirname(__FILE__), 'views')
4
+
5
+ private
6
+
7
+ def account_params
8
+ [ "property_id", "name" ]
9
+ end
10
+
11
+ def account_orders
12
+ [ "id" ]
13
+ end
14
+
15
+ def account_includes
16
+ [ "photos" ]
17
+ end
18
+
19
+ def property_params
20
+ [ :name,
21
+ :aliases,
22
+ :description,
23
+ :constructed,
24
+ :size,
25
+ :active,
26
+ :photos_attributes,
27
+ { photos_attributes: [ :id, :account_id, :property_id, :format] }
28
+ ]
29
+ end
30
+
31
+ def property_orders
32
+ ["id", "name", "aliases", "description", "constructed", "size", "created_at", "active"]
33
+ end
34
+
35
+ def property_includes
36
+ [:photos, :landlord, :english_name]
37
+ end
38
+
39
+ def reference_includes
40
+ { subject: [ :landlord, :photos ] }
41
+ end
42
+
43
+ end
44
+
45
+ class PropertiesController < ApplicationController
46
+ end
47
+
48
+ class AccountsController < ApplicationController
49
+ end
50
+
51
+ class DocumentsController < ApplicationController
52
+
53
+ def document_params
54
+ [ :file, :type ]
55
+ end
56
+
57
+ def document_orders
58
+ [:id]
59
+ end
60
+
61
+ end
62
+
63
+ class PhotosController < ApplicationController
64
+
65
+ def photo_params
66
+ [ :id, :account_id, :property_id, :format ]
67
+ end
68
+
69
+ def photo_orders
70
+ [:id]
71
+ end
72
+
73
+ def photo_includes
74
+ [:account]
75
+ end
76
+
77
+ end
78
+
79
+ class ReferencesController < ApplicationController
80
+ end
81
+
82
+ class SessionsController < ApplicationController
83
+ end
84
+
85
+ class UnlimitedController < ApplicationController
86
+
87
+ def self.model
88
+ Account
89
+ end
90
+
91
+ def resource_limit
92
+ nil
93
+ end
94
+
95
+ end
96
+
97
+ class DefaultLimitController < ApplicationController
98
+
99
+ def self.model
100
+ Account
101
+ end
102
+
103
+ def default_limit
104
+ 100
105
+ end
106
+
107
+ end
@@ -0,0 +1,94 @@
1
+ # = Models
2
+
3
+ class Account < ActiveRecord::Base
4
+ has_many :photos
5
+ belongs_to :property
6
+ end
7
+
8
+ class Photo < ActiveRecord::Base
9
+ belongs_to :account, :counter_cache => true
10
+ has_and_belongs_to_many :properties
11
+ end
12
+
13
+ class Document < ActiveRecord::Base
14
+ attr_accessor :file
15
+ end
16
+
17
+ class Pdf < Document
18
+ end
19
+
20
+ class Property < ActiveRecord::Base
21
+ has_and_belongs_to_many :photos
22
+ has_many :accounts
23
+ has_one :landlord, class_name: 'Account'
24
+
25
+ validates :name, presence: true
26
+ accepts_nested_attributes_for :photos
27
+
28
+ def english_name
29
+ 'A Name'
30
+ end
31
+ end
32
+
33
+ class Reference < ActiveRecord::Base
34
+ belongs_to :subject, polymorphic: true
35
+ end
36
+
37
+ # = Migration
38
+
39
+ class CreateModelTables < ActiveRecord::Migration[6.0]
40
+
41
+ def self.up
42
+
43
+ comment = "test comment"
44
+ exec_query(<<-SQL, "SQL")
45
+ COMMENT ON DATABASE #{quote_column_name(current_database)} IS #{quote(comment)};
46
+ SQL
47
+
48
+ create_table "accounts", force: :cascade do |t|
49
+ t.string 'name', limit: 255
50
+ t.integer 'property_id'
51
+ t.integer 'photos_count', null: false, default: 0
52
+ end
53
+
54
+ create_table "photos", force: :cascade do |t|
55
+ t.integer "account_id"
56
+ t.integer "property_id"
57
+ t.string "format", limit: 255
58
+ end
59
+
60
+ create_table "properties", force: :cascade do |t|
61
+ t.string "name", limit: 255
62
+ t.string "aliases", default: [], array: true
63
+ t.text "description"
64
+ t.integer "constructed"
65
+ t.decimal "size"
66
+ t.datetime "created_at", null: false
67
+ t.boolean "active", default: false
68
+ end
69
+
70
+ create_table "references", force: :cascade do |t|
71
+ t.integer "subject_id"
72
+ t.string "subject_type", limit: 255
73
+ t.string "key"
74
+ t.string "value"
75
+ end
76
+
77
+ create_table "photos_properties", force: :cascade do |t|
78
+ t.integer "photo_id"
79
+ t.integer "property_id"
80
+ end
81
+
82
+ create_table "landlords_properties", force: :cascade do |t|
83
+ t.integer "landlord_id"
84
+ t.integer "property_id"
85
+ end
86
+
87
+ create_table "documents", force: :cascade do |t|
88
+ t.string 'type'
89
+ end
90
+ end
91
+
92
+ end
93
+ ActiveRecord::Migration.verbose = false
94
+ CreateModelTables.up
@@ -0,0 +1,50 @@
1
+ FactoryBot.define do
2
+ factory :account do
3
+ name { Faker::Name.name }
4
+
5
+ trait(:nested) { }
6
+ trait(:invalid) do
7
+ name { nil }
8
+ end
9
+ end
10
+
11
+ factory :landlord do
12
+ name { Faker::Name.name }
13
+ end
14
+
15
+ factory :photo do
16
+ format { ['jpg', 'png', 'tiff'].sample }
17
+ end
18
+
19
+ factory :document do
20
+ file { fixture_file_upload(Rails.root + 'test/fixtures/photo.png', 'image/png') }
21
+ end
22
+
23
+ factory :pdf do
24
+ type { 'Pdf' }
25
+ file { fixture_file_upload(Rails.root + 'test/fixtures/photo.png', 'image/png') }
26
+ end
27
+
28
+ factory :reference do
29
+ subject_type { 'Photo' }
30
+ subject_id { create(:photo).id }
31
+ end
32
+
33
+ factory :property do
34
+ name { Faker::Lorem.words(number: Kernel.rand(1..4)).join(' ') }
35
+ description { Faker::Lorem.paragraphs.join("\n\n") }
36
+ constructed { Kernel.rand(1800..(Time.now.year - 2)) }
37
+ size { Kernel.rand(1000..10000000).to_f / 100 }
38
+ active { [true, false].sample }
39
+ photos { [create(:photo)] }
40
+
41
+ trait(:nested) do
42
+ photos_attributes { [attributes_for(:photo)] }
43
+ end
44
+
45
+ trait(:invalid) do
46
+ name { nil }
47
+ end
48
+ end
49
+
50
+ end
@@ -0,0 +1,15 @@
1
+ json.set! :id, photo.id
2
+ json.set! :account_id, photo.account_id
3
+ json.set! :property_id, photo.property_id
4
+ json.set! :format, photo.format
5
+ json.set! :template, 'photos/_photo'
6
+
7
+ if includes[:account]
8
+ json.set! :account do
9
+ if photo.account
10
+ json.partial! 'application/record', record: photo.account, includes: includes[:account]
11
+ else
12
+ json.null!
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,17 @@
1
+ json.object! do
2
+ json.set! :id, photo.id
3
+ json.set! :account_id, photo.account_id
4
+ json.set! :property_id, photo.property_id
5
+ json.set! :format, photo.format
6
+ json.set! :template, 'photos/_photo'
7
+
8
+ if includes[:account]
9
+ json.set! :account do
10
+ if photo.account
11
+ json.partial! 'application/record', record: photo.account, includes: includes[:account]
12
+ else
13
+ json.null!
14
+ end
15
+ end
16
+ end
17
+ end