sinatra-rest-api 0.1.3 → 0.1.4

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.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +4 -0
  3. data/.rubocop.yml +34 -0
  4. data/Gemfile +20 -0
  5. data/Gemfile.lock +92 -0
  6. data/LICENSE +5 -0
  7. data/README.md +135 -0
  8. data/examples/active_record/Gemfile +15 -0
  9. data/examples/active_record/Gemfile.lock +75 -0
  10. data/examples/active_record/Rakefile +8 -0
  11. data/examples/active_record/app.rb +117 -0
  12. data/examples/active_record/config.ru +8 -0
  13. data/examples/active_record/database.yml +7 -0
  14. data/examples/active_record/db/migrate/001_create_authors.rb +11 -0
  15. data/examples/active_record/db/migrate/002_create_categories.rb +10 -0
  16. data/examples/active_record/db/migrate/003_create_books.rb +16 -0
  17. data/examples/active_record/db/migrate/004_create_tags.rb +10 -0
  18. data/examples/active_record/db/migrate/005_create_books_tags.rb +11 -0
  19. data/examples/active_record/db/migrate/006_create_chapters.rb +12 -0
  20. data/examples/active_record/db/schema.rb +61 -0
  21. data/examples/active_record/db/seeds.rb +0 -0
  22. data/examples/activeresource/Gemfile +10 -0
  23. data/examples/activeresource/Gemfile.lock +68 -0
  24. data/examples/activeresource/app.rb +125 -0
  25. data/examples/activeresource/config.ru +9 -0
  26. data/examples/activeresource/layout.slim +78 -0
  27. data/examples/misc/set_verb_options.rb +12 -0
  28. data/examples/mongoid/Gemfile +11 -0
  29. data/examples/mongoid/Gemfile.lock +68 -0
  30. data/examples/mongoid/Rakefile +3 -0
  31. data/examples/mongoid/app.rb +144 -0
  32. data/examples/mongoid/config.ru +8 -0
  33. data/examples/mongoid/database.yml +13 -0
  34. data/examples/mongoid/lib/tasks/db.rake +79 -0
  35. data/examples/ng-admin/index.html +168 -0
  36. data/examples/ng-admin/package.json +14 -0
  37. data/examples/sequel/Gemfile +14 -0
  38. data/examples/sequel/Gemfile.lock +54 -0
  39. data/examples/sequel/Rakefile +3 -0
  40. data/examples/sequel/app.rb +138 -0
  41. data/examples/sequel/config.ru +9 -0
  42. data/examples/sequel/database.yml +7 -0
  43. data/examples/sequel/db/migrate/001_create_authors.rb +15 -0
  44. data/examples/sequel/db/migrate/002_create_categories.rb +14 -0
  45. data/examples/sequel/db/migrate/003_create_books.rb +20 -0
  46. data/examples/sequel/db/migrate/004_create_tags.rb +14 -0
  47. data/examples/sequel/db/migrate/005_create_books_tags.rb +15 -0
  48. data/examples/sequel/db/migrate/006_create_chapters.rb +16 -0
  49. data/examples/sequel/lib/tasks/db.rake +44 -0
  50. data/lib/sinatra-rest-api/actions.rb +2 -1
  51. data/sinatra-rest-api.gemspec +24 -0
  52. data/spec/action_create_spec.rb +164 -0
  53. data/spec/action_delete_spec.rb +32 -0
  54. data/spec/action_list_spec.rb +31 -0
  55. data/spec/action_read_spec.rb +28 -0
  56. data/spec/action_update_spec.rb +98 -0
  57. data/spec/app_active_record_spec.rb +53 -0
  58. data/spec/app_mongoid_spec.rb +46 -0
  59. data/spec/app_sequel_spec.rb +45 -0
  60. data/spec/spec_helper.rb +59 -0
  61. metadata +70 -3
@@ -0,0 +1,32 @@
1
+ $VERBOSE = false
2
+
3
+ # require 'pry'
4
+
5
+ # Tests actions
6
+ module ActionTests
7
+ RSpec.shared_examples 'Action: delete' do |models|
8
+ context 'Deleting authors...' do
9
+ # path = '/authors'
10
+ path = '/writers' # renamed resource
11
+
12
+ # action: delete
13
+ it 'should remove an author' do
14
+ cnt = models[:author].count
15
+ delete path + '/' + models[:author].last.id.to_s
16
+ expect( last_response.status ).to eq( 200 )
17
+ get path
18
+ expect( last_response.status ).to eq( 200 )
19
+ expect( JSON.parse( last_response.body ).length ).to eq( cnt - 1 )
20
+ end
21
+
22
+ it 'should not remove an author with invalid id' do
23
+ cnt = models[:author].count
24
+ delete path + '/999'
25
+ expect( last_response.status ).to eq( 404 )
26
+ get path
27
+ expect( last_response.status ).to eq( 200 )
28
+ expect( JSON.parse( last_response.body ).length ).to eq( cnt )
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,31 @@
1
+ $VERBOSE = false
2
+
3
+ # require 'pry'
4
+
5
+ # Tests actions
6
+ module ActionTests
7
+ RSpec.shared_examples 'Action: list' do |models|
8
+ context 'Listing books...' do
9
+ cnt = 0
10
+
11
+ # action: list
12
+ it 'should list all books' do
13
+ cnt = models[:book].count
14
+ get '/books'
15
+ expect( last_response.status ).to eq( 200 )
16
+ expect( JSON.parse( last_response.body ).length ).to eq( cnt )
17
+ end
18
+
19
+ it 'should paginate books' do
20
+ page_size = 2
21
+ limit = cnt - page_size
22
+ get "/books?limit=#{limit}"
23
+ expect( last_response.status ).to eq( 200 )
24
+ expect( JSON.parse( last_response.body ).length ).to eq( limit )
25
+ get "/books?limit=#{limit}&offset=#{limit}"
26
+ expect( last_response.status ).to eq( 200 )
27
+ expect( JSON.parse( last_response.body ).length ).to eq( page_size )
28
+ end
29
+ end
30
+ end
31
+ end
@@ -0,0 +1,28 @@
1
+ $VERBOSE = false
2
+
3
+ # require 'pry'
4
+
5
+ # Tests actions
6
+ module ActionTests
7
+ RSpec.shared_examples 'Action: read' do |models|
8
+ context 'Reading books...' do
9
+ path = '/books'
10
+
11
+ # action: read
12
+ it 'should read the first book' do
13
+ get path + '/' + models[:book].first.id.to_s
14
+ expect( last_response.status ).to eq( 200 )
15
+ end
16
+
17
+ it 'should read the last book' do
18
+ get path + '/' + models[:book].last.id.to_s
19
+ expect( last_response.status ).to eq( 200 )
20
+ end
21
+
22
+ it 'should not read an author with invalid id' do
23
+ get path + '/999'
24
+ expect( last_response.status ).to eq( 404 )
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,98 @@
1
+ $VERBOSE = false
2
+
3
+ # require 'pry'
4
+
5
+ # Tests actions
6
+ module ActionTests
7
+ RSpec.shared_examples 'Action: update' do |models|
8
+ context 'Updating authors...' do
9
+ # path = '/authors'
10
+ path = '/writers' # renamed resource
11
+
12
+ # action: update
13
+ it 'should update some authors' do
14
+ random_authors = []
15
+ (1..(models[:author].count / 2 )).each do |_i|
16
+ random_authors.push( name: Faker::Book.author, email: Faker::Internet.email )
17
+ end
18
+ random_authors.uniq! { |a| a[:email] }
19
+ ids = models[:author].all.sample( random_authors.length ).map( &:id )
20
+ random_authors.each_with_index do |author, index|
21
+ put path + '/' + ids[index].to_s, writer: author
22
+ expect( last_response.status ).to eq( 200 ) # status = ok ?
23
+ expect( JSON.parse( last_response.body )['message'] ).to eq 'ok' # message = ok ?
24
+ row = models[:author].where( author )
25
+ expect( row.count ).to eq 1 # record exists ?
26
+ expect( row.first.id ).to eq ids[index] # record corresponds ?
27
+ end
28
+ end
29
+
30
+ it 'should not update an author with invalid data' do
31
+ id = models[:author].all.sample.id
32
+ authors = [
33
+ { name: '' },
34
+ { email: '' },
35
+ { name: '', email: '' },
36
+ { name: ' ', email: ' ' }
37
+ ]
38
+ authors.each do |author|
39
+ put path + '/' + id.to_s, writer: author
40
+ expect( last_response.status ).to eq( 400 )
41
+ end
42
+ end
43
+ end
44
+
45
+ ##############################################################################
46
+
47
+ context 'Updating books...' do
48
+ # action: update
49
+ it 'should update some books' do
50
+ cnt = ( models[:book].count - 1 ) / 4
51
+ random_books = []
52
+ (1..cnt).each do |_i|
53
+ random_books.push( title: Faker::Book.title + " [#{rand( 8 ) + 1}]" )
54
+ end
55
+ random_books.uniq! { |b| b[:title] }
56
+ (1..cnt).each do |_i|
57
+ random_books.push( title: Faker::Hipster.sentence, pages: rand( 1000 ), price: rand * 20 )
58
+ end
59
+ (1..cnt).each do |_i|
60
+ random_books.push( title: Faker::StarWars.quote, pages: rand( 1000 ), price: rand * 20, category_attributes: { name: Faker::Book.genre } )
61
+ end
62
+ tags_ids = models[:tag].all.map( &:id )
63
+ (1..cnt).each do |_i|
64
+ random_books.push( title: Faker::University.name, pages: rand( 1000 ), price: rand * 20, category_id: models[:category].all.sample.id, tag_ids: tags_ids.sample( rand( 3 ) ) )
65
+ end
66
+ ids = models[:book].all.sample( random_books.length ).map( &:id )
67
+ random_books.each_with_index do |book, index|
68
+ put '/books/' + ids[index].to_s, book: book
69
+ expect( last_response.status ).to eq( 200 ) # check if the status is equal to ok
70
+ category_attributes = book.delete :category_attributes
71
+ tags_attributes = book.delete :tags_attributes
72
+ tag_ids = book.delete :tag_ids
73
+ expect( models[:book].where( book ).count ).to eq( 1 ) # check if book is created
74
+ # check the relations
75
+ row = models[:book].where( id: ids[index] ).first
76
+ expect( row.tags.map( &:id ).sort ).to eq( tag_ids.sort ) if !tag_ids.nil? && tag_ids.any?
77
+ expect( row.tags.map( &:name ) ).to eq( tags_attributes.map { |a| a[:name] } ) unless tags_attributes.nil?
78
+ expect( row.category.name ).to eq( category_attributes[:name] ) unless category_attributes.nil?
79
+ end
80
+ end
81
+
82
+ it 'should not update a book without title' do
83
+ put '/books/' + models[:book].all.sample.id.to_s, book: { title: '', pages: rand( 1000 ), price: rand * 20 }
84
+ expect( last_response.status ).to eq( 400 )
85
+ end
86
+ end
87
+
88
+ ##############################################################################
89
+
90
+ context 'Updating categories...' do
91
+ # action: update
92
+ it 'should not update categories' do
93
+ put '/categories/' + models[:category].all.sample.id.to_s, category: { name: 'A cat' }
94
+ expect( last_response.status ).to eq( 404 )
95
+ end
96
+ end
97
+ end
98
+ end
@@ -0,0 +1,53 @@
1
+
2
+ ENV['RACK_ENV'] ||= 'test'
3
+
4
+ # App path
5
+ APP_AR = File.expand_path( '../../examples/active_record', __FILE__ ).freeze
6
+
7
+ require File.join( APP_AR, 'app.rb' )
8
+ require File.expand_path( '../spec_helper.rb', __FILE__ )
9
+
10
+ # AR tests
11
+ module ActiveRecordTest
12
+ $VERBOSE = false
13
+
14
+ models = {
15
+ author: Author,
16
+ book: Book,
17
+ category: Category,
18
+ chapter: Chapter,
19
+ tag: Tag
20
+ }
21
+
22
+ load File.join( APP_AR, 'Rakefile' )
23
+ ActiveRecord::Tasks::DatabaseTasks.db_dir = File.join( APP_AR, 'db' )
24
+ ActiveRecord::Tasks::DatabaseTasks.migrations_paths = File.join( APP_AR, 'db', 'migrate' )
25
+
26
+ describe 'ActiveRecord Test App' do
27
+ def app
28
+ App
29
+ end
30
+
31
+ before( :all ) do
32
+ # $VERBOSE = false
33
+ # Rake::Task.define_task( :environment )
34
+ Rake::Task['db:environment:set'].invoke
35
+ Rake::Task['db:drop'].invoke
36
+ Rake::Task['db:create'].invoke
37
+ Rake::Task['db:migrate'].invoke
38
+ # $VERBOSE = true
39
+ end
40
+
41
+ it 'should list routes in home page' do
42
+ get '/'
43
+ expect( last_response ).to be_ok
44
+ expect( JSON.parse( last_response.body ).count ).to be > 0
45
+ end
46
+
47
+ include_examples 'Action: create', models
48
+ include_examples 'Action: read', models
49
+ include_examples 'Action: update', models
50
+ include_examples 'Action: delete', models
51
+ include_examples 'Action: list', models
52
+ end
53
+ end
@@ -0,0 +1,46 @@
1
+ ENV['RACK_ENV'] ||= 'test'
2
+
3
+ # App path
4
+ APP_MONGO = File.expand_path( '../../examples/mongoid', __FILE__ ).freeze
5
+
6
+ require File.join( APP_MONGO, 'app.rb' )
7
+ require File.expand_path( '../spec_helper.rb', __FILE__ )
8
+
9
+ # Mongo tests
10
+ module MongoidTest
11
+ $VERBOSE = false
12
+
13
+ models = {
14
+ author: Author,
15
+ book: Book,
16
+ category: Category,
17
+ chapter: Chapter,
18
+ tag: Tag
19
+ }
20
+
21
+ load File.join( APP_MONGO, 'lib', 'tasks', 'db.rake' )
22
+
23
+ describe 'Mongoid Test App' do
24
+ def app
25
+ App
26
+ end
27
+
28
+ before( :all ) do
29
+ $VERBOSE = false
30
+ Rake::Task.define_task( :environment )
31
+ Rake::Task['db:drop'].invoke
32
+ end
33
+
34
+ it 'should list routes in home page' do
35
+ get '/'
36
+ expect( last_response ).to be_ok
37
+ expect( JSON.parse( last_response.body ).count ).to be > 0
38
+ end
39
+
40
+ include_examples 'Action: create', models
41
+ include_examples 'Action: read', models
42
+ include_examples 'Action: update', models
43
+ include_examples 'Action: delete', models
44
+ include_examples 'Action: list', models
45
+ end
46
+ end
@@ -0,0 +1,45 @@
1
+
2
+ ENV['RACK_ENV'] ||= 'test'
3
+ ENV['SEQUEL_RECREATE_DB'] = '1'
4
+
5
+ APP_SEQUEL = File.expand_path( '../../examples/sequel', __FILE__ ).freeze
6
+
7
+ require File.join( APP_SEQUEL, 'app.rb' )
8
+ require File.expand_path( '../spec_helper.rb', __FILE__ )
9
+
10
+ # Sequel tests
11
+ module SequelTest
12
+ models = {
13
+ author: Author,
14
+ book: Book,
15
+ category: Category,
16
+ chapter: Chapter,
17
+ tag: Tag
18
+ }
19
+
20
+ load File.join( APP_SEQUEL, 'lib', 'tasks', 'db.rake' )
21
+
22
+ describe 'Sequel Test App' do
23
+ def app
24
+ App
25
+ end
26
+
27
+ before( :all ) do
28
+ $VERBOSE = false
29
+ # DB clean is done in the test app
30
+ end
31
+
32
+ it 'should list routes in home page' do
33
+ get '/'
34
+ expect( last_response ).to be_ok
35
+ expect( JSON.parse( last_response.body ).count ).to be > 0
36
+ end
37
+
38
+ # TODO: solve the problem Sequel::DatabaseError: SQLite3::ReadOnlyException: attempt to write a readonly database
39
+ # include_examples 'Action: create', models
40
+ # include_examples 'Action: read', models
41
+ # include_examples 'Action: update', models
42
+ # include_examples 'Action: delete', models
43
+ # include_examples 'Action: list', models
44
+ end
45
+ end
@@ -0,0 +1,59 @@
1
+ # spec/spec_helper.rb
2
+ require 'rack/test'
3
+ require 'rake'
4
+ require 'rspec'
5
+ require 'faker'
6
+
7
+ # RSpecMixin
8
+ module RSpecMixin
9
+ unless RSpecMixin.const_defined?( :ActionTests )
10
+ require File.expand_path( '../action_create_spec.rb', __FILE__ )
11
+ require File.expand_path( '../action_read_spec.rb', __FILE__ )
12
+ require File.expand_path( '../action_update_spec.rb', __FILE__ )
13
+ require File.expand_path( '../action_delete_spec.rb', __FILE__ )
14
+ require File.expand_path( '../action_list_spec.rb', __FILE__ )
15
+
16
+ include Rack::Test::Methods
17
+ end
18
+ end
19
+
20
+ # RSpec.shared_examples 'Basic tests' do
21
+ # it 'should list routes in home page' do
22
+ # get '/'
23
+ # expect( last_response.status ).to eq( 200 )
24
+ # # TODO: check the content partially
25
+ # # expect( last_response.body ).to eq( 'Hello world!' )
26
+ # end
27
+ # end
28
+
29
+ RSpec.configure do |config|
30
+ config.include RSpecMixin
31
+
32
+ config.filter_run :run_single_tests if RSpec.configuration.files_to_run.length > 1
33
+
34
+ # config.run_all_when_everything_filtered = true
35
+
36
+ # config.disable_monkey_patching!
37
+
38
+ config.warnings = true
39
+
40
+ config.default_formatter = 'doc' if config.files_to_run.one?
41
+
42
+ # config.profile_examples = 10
43
+
44
+ # config.order = :random
45
+
46
+ # Kernel.srand config.seed
47
+
48
+ # config.before(:each) do
49
+ # db = []
50
+ # end
51
+
52
+ # config.expect_with :rspec do |expectations|
53
+ # expectations.include_chain_clauses_in_custom_matcher_descriptions = true
54
+ # end
55
+
56
+ # config.mock_with :rspec do |mocks|
57
+ # mocks.verify_partial_doubles = true
58
+ # end
59
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sinatra-rest-api
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.3
4
+ version: 0.1.4
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mattia Roccoberton
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2017-10-01 00:00:00.000000000 Z
11
+ date: 2017-10-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: sinatra
@@ -31,11 +31,69 @@ executables: []
31
31
  extensions: []
32
32
  extra_rdoc_files: []
33
33
  files:
34
+ - ".gitignore"
35
+ - ".rubocop.yml"
36
+ - Gemfile
37
+ - Gemfile.lock
38
+ - LICENSE
39
+ - README.md
40
+ - examples/active_record/Gemfile
41
+ - examples/active_record/Gemfile.lock
42
+ - examples/active_record/Rakefile
43
+ - examples/active_record/app.rb
44
+ - examples/active_record/config.ru
45
+ - examples/active_record/database.yml
46
+ - examples/active_record/db/migrate/001_create_authors.rb
47
+ - examples/active_record/db/migrate/002_create_categories.rb
48
+ - examples/active_record/db/migrate/003_create_books.rb
49
+ - examples/active_record/db/migrate/004_create_tags.rb
50
+ - examples/active_record/db/migrate/005_create_books_tags.rb
51
+ - examples/active_record/db/migrate/006_create_chapters.rb
52
+ - examples/active_record/db/schema.rb
53
+ - examples/active_record/db/seeds.rb
54
+ - examples/activeresource/Gemfile
55
+ - examples/activeresource/Gemfile.lock
56
+ - examples/activeresource/app.rb
57
+ - examples/activeresource/config.ru
58
+ - examples/activeresource/layout.slim
59
+ - examples/misc/set_verb_options.rb
60
+ - examples/mongoid/Gemfile
61
+ - examples/mongoid/Gemfile.lock
62
+ - examples/mongoid/Rakefile
63
+ - examples/mongoid/app.rb
64
+ - examples/mongoid/config.ru
65
+ - examples/mongoid/database.yml
66
+ - examples/mongoid/lib/tasks/db.rake
67
+ - examples/ng-admin/index.html
68
+ - examples/ng-admin/package.json
69
+ - examples/sequel/Gemfile
70
+ - examples/sequel/Gemfile.lock
71
+ - examples/sequel/Rakefile
72
+ - examples/sequel/app.rb
73
+ - examples/sequel/config.ru
74
+ - examples/sequel/database.yml
75
+ - examples/sequel/db/migrate/001_create_authors.rb
76
+ - examples/sequel/db/migrate/002_create_categories.rb
77
+ - examples/sequel/db/migrate/003_create_books.rb
78
+ - examples/sequel/db/migrate/004_create_tags.rb
79
+ - examples/sequel/db/migrate/005_create_books_tags.rb
80
+ - examples/sequel/db/migrate/006_create_chapters.rb
81
+ - examples/sequel/lib/tasks/db.rake
34
82
  - lib/sinatra-rest-api.rb
35
83
  - lib/sinatra-rest-api/actions.rb
36
84
  - lib/sinatra-rest-api/adapter.rb
37
85
  - lib/sinatra-rest-api/provider.rb
38
86
  - lib/sinatra-rest-api/router.rb
87
+ - sinatra-rest-api.gemspec
88
+ - spec/action_create_spec.rb
89
+ - spec/action_delete_spec.rb
90
+ - spec/action_list_spec.rb
91
+ - spec/action_read_spec.rb
92
+ - spec/action_update_spec.rb
93
+ - spec/app_active_record_spec.rb
94
+ - spec/app_mongoid_spec.rb
95
+ - spec/app_sequel_spec.rb
96
+ - spec/spec_helper.rb
39
97
  homepage: https://github.com/blocknotes/sinatra-rest-api
40
98
  licenses:
41
99
  - ISC
@@ -60,4 +118,13 @@ rubygems_version: 2.6.13
60
118
  signing_key:
61
119
  specification_version: 4
62
120
  summary: Sinatra REST API generator
63
- test_files: []
121
+ test_files:
122
+ - spec/action_create_spec.rb
123
+ - spec/action_delete_spec.rb
124
+ - spec/action_list_spec.rb
125
+ - spec/action_read_spec.rb
126
+ - spec/action_update_spec.rb
127
+ - spec/app_active_record_spec.rb
128
+ - spec/app_mongoid_spec.rb
129
+ - spec/app_sequel_spec.rb
130
+ - spec/spec_helper.rb