sinatra-rest-api 0.1.3 → 0.1.4

Sign up to get free protection for your applications and to get access to all the features.
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