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
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f221bc7f806a2770f5903144a0e72fbb9f91be3b
4
- data.tar.gz: e68a253284bf6490d89f9327d345469c25f9beb9
3
+ metadata.gz: 797c81c8b82f82d443d4d866f00fe0ca445058e0
4
+ data.tar.gz: 24c413e0fb58eb2947346ecb48efcdc711f7feb0
5
5
  SHA512:
6
- metadata.gz: a74fd00c70ce021325e9997836b7f70a8f9d276bdef3e31da2fa0811b6ffe01ef207070f838c715c4a750ebaab7eec4abf6c455b1fef0950515c361bb0e7a029
7
- data.tar.gz: c3dc877e255474a1ee504a2d29dfe476c8d0cfcf9aeb60b013a76c0bc408cef2a948fac7a099760bcafcb6fd0a940de6666a81707a77285baeb58767a9d4250f
6
+ metadata.gz: adff2d50c73dd49a2921488607fce33d1b71eab4a881d83ea570ad9626274735550df52c0776ee4641306ecba5873cac6c6f28443fb65ba71cf7b3d3d3dc240a
7
+ data.tar.gz: 7fb8cb86191aca81939733097e64b31a469b866e9144f6ad65a350e82ee73f8942e0bca81b853ab3fc5a756f63deceb628e00f679a976a5528d961dd632303b6
@@ -0,0 +1,4 @@
1
+ _misc/
2
+ node_modules/
3
+ examples/ng-admin/ng-admin/
4
+ *.sqlite3
@@ -0,0 +1,34 @@
1
+ AllCops:
2
+ TargetRubyVersion: 2.1
3
+
4
+ # generic rules
5
+ Metrics/LineLength:
6
+ Enabled: false
7
+ Style/FileName:
8
+ Enabled: false
9
+ Style/SpaceInsideBrackets:
10
+ Enabled: false
11
+ Style/SpaceInsideParens:
12
+ Enabled: false
13
+ Style/SpaceAroundBlockParameters:
14
+ Enabled: false
15
+
16
+ # specific project rules
17
+ Metrics/AbcSize:
18
+ Enabled: false
19
+ Metrics/BlockLength:
20
+ Enabled: false
21
+ Metrics/ClassLength:
22
+ Enabled: false
23
+ Metrics/CyclomaticComplexity:
24
+ Max: 10
25
+ Metrics/MethodLength:
26
+ Enabled: false
27
+ Metrics/PerceivedComplexity:
28
+ Enabled: false
29
+ Style/IfInsideElse:
30
+ Enabled: false
31
+ Style/RescueModifier:
32
+ Enabled: false
33
+ Style/ClassVars:
34
+ Enabled: false
data/Gemfile ADDED
@@ -0,0 +1,20 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem 'rack-test'
7
+ gem 'rspec'
8
+ gem 'faker'
9
+
10
+ gem 'pry'
11
+ gem 'rake'
12
+
13
+ gem 'sinatra'
14
+
15
+ gem 'activerecord'
16
+ gem 'sinatra-activerecord'
17
+ gem 'sequel'
18
+ gem 'mongoid'
19
+ gem 'sqlite3'
20
+ end
@@ -0,0 +1,92 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sinatra-rest-api (0.1.0)
5
+ sinatra (= 1.4.7)
6
+
7
+ GEM
8
+ remote: https://rubygems.org/
9
+ specs:
10
+ activemodel (5.0.0.1)
11
+ activesupport (= 5.0.0.1)
12
+ activerecord (5.0.0.1)
13
+ activemodel (= 5.0.0.1)
14
+ activesupport (= 5.0.0.1)
15
+ arel (~> 7.0)
16
+ activesupport (5.0.0.1)
17
+ concurrent-ruby (~> 1.0, >= 1.0.2)
18
+ i18n (~> 0.7)
19
+ minitest (~> 5.1)
20
+ tzinfo (~> 1.1)
21
+ arel (7.1.4)
22
+ bson (4.1.1)
23
+ coderay (1.1.1)
24
+ concurrent-ruby (1.0.2)
25
+ diff-lcs (1.2.5)
26
+ faker (1.6.6)
27
+ i18n (~> 0.5)
28
+ i18n (0.7.0)
29
+ method_source (0.8.2)
30
+ minitest (5.9.1)
31
+ mongo (2.3.0)
32
+ bson (~> 4.1)
33
+ mongoid (6.0.2)
34
+ activemodel (~> 5.0)
35
+ mongo (~> 2.3)
36
+ pry (0.10.4)
37
+ coderay (~> 1.1.0)
38
+ method_source (~> 0.8.1)
39
+ slop (~> 3.4)
40
+ rack (1.6.4)
41
+ rack-protection (1.5.3)
42
+ rack
43
+ rack-test (0.6.3)
44
+ rack (>= 1.0)
45
+ rake (11.3.0)
46
+ rspec (3.5.0)
47
+ rspec-core (~> 3.5.0)
48
+ rspec-expectations (~> 3.5.0)
49
+ rspec-mocks (~> 3.5.0)
50
+ rspec-core (3.5.4)
51
+ rspec-support (~> 3.5.0)
52
+ rspec-expectations (3.5.0)
53
+ diff-lcs (>= 1.2.0, < 2.0)
54
+ rspec-support (~> 3.5.0)
55
+ rspec-mocks (3.5.0)
56
+ diff-lcs (>= 1.2.0, < 2.0)
57
+ rspec-support (~> 3.5.0)
58
+ rspec-support (3.5.0)
59
+ sequel (4.40.0)
60
+ sinatra (1.4.7)
61
+ rack (~> 1.5)
62
+ rack-protection (~> 1.4)
63
+ tilt (>= 1.3, < 3)
64
+ sinatra-activerecord (2.0.11)
65
+ activerecord (>= 3.2)
66
+ sinatra (~> 1.0)
67
+ slop (3.6.0)
68
+ sqlite3 (1.3.12)
69
+ thread_safe (0.3.5)
70
+ tilt (2.0.5)
71
+ tzinfo (1.2.2)
72
+ thread_safe (~> 0.1)
73
+
74
+ PLATFORMS
75
+ ruby
76
+
77
+ DEPENDENCIES
78
+ activerecord
79
+ faker
80
+ mongoid
81
+ pry
82
+ rack-test
83
+ rake
84
+ rspec
85
+ sequel
86
+ sinatra
87
+ sinatra-activerecord
88
+ sinatra-rest-api!
89
+ sqlite3
90
+
91
+ BUNDLED WITH
92
+ 1.13.5
data/LICENSE ADDED
@@ -0,0 +1,5 @@
1
+ Copyright (c) 2016, Mattia Roccoberton
2
+
3
+ Permission to use, copy, modify, and/or distribute this software for any purpose with or without fee is hereby granted, provided that the above copyright notice and this permission notice appear in all copies.
4
+
5
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
@@ -0,0 +1,135 @@
1
+ # Sinatra REST API [![Gem Version](https://badge.fury.io/rb/sinatra-rest-api.svg)](https://badge.fury.io/rb/sinatra-rest-api)
2
+
3
+ A Sinatra component that generates CRUD routes for database ORM models.
4
+
5
+ Features:
6
+ - supports Active Record, Mongoid and Sequel ORMs
7
+ - default actions already setup
8
+ - nested resources available
9
+
10
+ Install: `gem install sinatra-rest-api` (or in Gemfile)
11
+
12
+ ## Options
13
+
14
+ For *resource* DSL keyword:
15
+ - **actions**: list of actions to enable (array of symbols)
16
+ - **include**: list of associations to expose in list/read actions (array of symbols) or false to skip every association
17
+ - **limit**: set a fixed limit server side
18
+ - **plural**: plural model name used for routes (string)
19
+ - **singular**: singular model name for resource key (string)
20
+
21
+ Routes parameters:
22
+ - **limit**: limit results (ex. 20)
23
+ - **offset**: results offset (ex. 40)
24
+
25
+ ## Examples
26
+
27
+ ```rb
28
+ class Book < ActiveRecord::Base
29
+ end
30
+
31
+ class App < Sinatra::Application
32
+ register Sinatra::RestApi
33
+
34
+ resource Book
35
+ resource Category do
36
+ actions [ :list, :read ]
37
+ end
38
+ end
39
+ ```
40
+
41
+ Generates:
42
+
43
+ ```
44
+ GET: /books/:id.?:format?
45
+ PUT: /books/:id.?:format?
46
+ DELETE: /books/:id.?:format?
47
+ PUT: /books/?.?:format?
48
+ POST: /books/?.?:format?
49
+ DELETE: /books/?.?:format?
50
+ GET: /books/?.?:format?
51
+ GET: /categories/:id.?:format?
52
+ GET: /categories/?.?:format?
53
+ ```
54
+
55
+ #### More examples
56
+
57
+ See [examples](examples/). Execute: `thin start` in the folder of an example.
58
+
59
+ #### Using inside a Rails app
60
+
61
+ Let's create an Importer class to import data between 2 Rails app.
62
+
63
+ A simple way to add an API for every model on the source app:
64
+
65
+ - create a sinatra app in: `lib/sinatra_app/app.rb`:
66
+
67
+ ```rb
68
+ Rails.application.eager_load! # if cache_classes is off
69
+
70
+ class MySinatraApp < Sinatra::Base
71
+ register Sinatra::RestApi
72
+
73
+ ActiveRecord::Base.descendants.each do |model| # Iterate all models
74
+ next if model.abstract_class
75
+ resource model, actions: [ :list, :read ], include: false
76
+ end
77
+ end
78
+ ```
79
+
80
+ - load the sinatra app editing `config/application.rb`:
81
+
82
+ ```rb
83
+ module RailsSinatra
84
+ class Application < Rails::Application
85
+ config.after_initialize do
86
+ require_relative '../lib/sinatra_app/app'
87
+ end
88
+ end
89
+ end
90
+ ```
91
+
92
+ - setup the routes editing `config/routes.rb`:
93
+
94
+ ```rb
95
+ Rails.application.routes.draw do
96
+ mount MySinatraApp.new => '/sinatra'
97
+ end
98
+ ```
99
+
100
+ - now you can access to every model under 'sinatra' path, example: '/sinatra/posts.json'
101
+
102
+ - on the destination app you can access these models using *ActiveResource* gem:
103
+
104
+ ```rb
105
+ class Importer < ActiveResource::Base
106
+ self.site = 'http://127.0.0.1:3000/sinatra' # first app path
107
+
108
+ def self.init( collection_name )
109
+ set_collection_name collection_name
110
+ self
111
+ end
112
+ end
113
+
114
+ # List of tags names:
115
+ Importer.init( 'tags' ).all.map( &:name )
116
+ ```
117
+
118
+ ## Tests
119
+
120
+ Run individual example apps tests:
121
+ - `rspec spec/app_active_record_spec.rb`
122
+ - `rspec spec/app_mongoid_spec.rb`
123
+ - `rspec spec/app_sequel_spec.rb`
124
+
125
+ ## Do you like it? Star it!
126
+
127
+ If you use this component just star it. A developer is more motivated to improve a project when there is some interest.
128
+
129
+ ## Contributors
130
+
131
+ - [Mattia Roccoberton](http://blocknot.es) - creator, maintainer
132
+
133
+ ## License
134
+
135
+ [ISC](LICENSE)
@@ -0,0 +1,15 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'pry'
4
+
5
+ gem 'sinatra'
6
+ gem 'sinatra-contrib'
7
+
8
+ gem 'rake'
9
+ gem 'thin'
10
+
11
+ gem 'activerecord'
12
+ gem 'sinatra-activerecord'
13
+ gem 'sqlite3'
14
+
15
+ gem 'sinatra-rest-api' # , path: '../../../sinatra-rest-api'
@@ -0,0 +1,75 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activemodel (5.1.4)
5
+ activesupport (= 5.1.4)
6
+ activerecord (5.1.4)
7
+ activemodel (= 5.1.4)
8
+ activesupport (= 5.1.4)
9
+ arel (~> 8.0)
10
+ activesupport (5.1.4)
11
+ concurrent-ruby (~> 1.0, >= 1.0.2)
12
+ i18n (~> 0.7)
13
+ minitest (~> 5.1)
14
+ tzinfo (~> 1.1)
15
+ arel (8.0.0)
16
+ backports (3.8.0)
17
+ coderay (1.1.2)
18
+ concurrent-ruby (1.0.5)
19
+ daemons (1.2.4)
20
+ eventmachine (1.2.5)
21
+ i18n (0.8.6)
22
+ method_source (0.9.0)
23
+ minitest (5.10.3)
24
+ multi_json (1.12.2)
25
+ mustermann (1.0.1)
26
+ pry (0.11.1)
27
+ coderay (~> 1.1.0)
28
+ method_source (~> 0.9.0)
29
+ rack (2.0.3)
30
+ rack-protection (2.0.0)
31
+ rack
32
+ rake (12.1.0)
33
+ sinatra (2.0.0)
34
+ mustermann (~> 1.0)
35
+ rack (~> 2.0)
36
+ rack-protection (= 2.0.0)
37
+ tilt (~> 2.0)
38
+ sinatra-activerecord (2.0.13)
39
+ activerecord (>= 3.2)
40
+ sinatra (>= 1.0)
41
+ sinatra-contrib (2.0.0)
42
+ backports (>= 2.0)
43
+ multi_json
44
+ mustermann (~> 1.0)
45
+ rack-protection (= 2.0.0)
46
+ sinatra (= 2.0.0)
47
+ tilt (>= 1.3, < 3)
48
+ sinatra-rest-api (0.1.2)
49
+ sinatra (~> 2.0, > 1.4.0)
50
+ sqlite3 (1.3.13)
51
+ thin (1.7.2)
52
+ daemons (~> 1.0, >= 1.0.9)
53
+ eventmachine (~> 1.0, >= 1.0.4)
54
+ rack (>= 1, < 3)
55
+ thread_safe (0.3.6)
56
+ tilt (2.0.8)
57
+ tzinfo (1.2.3)
58
+ thread_safe (~> 0.1)
59
+
60
+ PLATFORMS
61
+ ruby
62
+
63
+ DEPENDENCIES
64
+ activerecord
65
+ pry
66
+ rake
67
+ sinatra
68
+ sinatra-activerecord
69
+ sinatra-contrib
70
+ sinatra-rest-api
71
+ sqlite3
72
+ thin
73
+
74
+ BUNDLED WITH
75
+ 1.15.4
@@ -0,0 +1,8 @@
1
+ # Rakefile
2
+ require 'sinatra/activerecord/rake'
3
+
4
+ namespace :db do
5
+ task :load_config do
6
+ require File.expand_path( '../app', __FILE__ )
7
+ end
8
+ end
@@ -0,0 +1,117 @@
1
+ # require 'pry'
2
+
3
+ require 'json'
4
+ require 'yaml'
5
+
6
+ require 'sinatra/activerecord'
7
+ require 'sinatra/base'
8
+
9
+ require 'active_record'
10
+ require 'sqlite3'
11
+
12
+ require 'sinatra-rest-api'
13
+
14
+ # ActiveRecordTest App
15
+ module ActiveRecordTest
16
+ env = ENV['RACK_ENV'] || 'development'
17
+ conf = YAML.load( File.read( File.expand_path( '../database.yml', __FILE__ ) ) )
18
+ conf[env]['database'] = File.expand_path( '../' + conf[env]['database'], __FILE__ )
19
+
20
+ ActiveRecord::Base.establish_connection( conf[env] )
21
+
22
+ # An author
23
+ class Author < ActiveRecord::Base
24
+ has_many :books, dependent: :destroy
25
+
26
+ validates :name, presence: true
27
+ validates :email, presence: true, uniqueness: true
28
+ end
29
+
30
+ # A book
31
+ class Book < ActiveRecord::Base
32
+ belongs_to :author
33
+ belongs_to :category
34
+ has_and_belongs_to_many :tags
35
+ has_many :chapters
36
+
37
+ accepts_nested_attributes_for :author
38
+ accepts_nested_attributes_for :category
39
+ accepts_nested_attributes_for :tags
40
+
41
+ # default_scope { where( 'id > 2' ) }
42
+ # default_scope { where( published: true ) }
43
+
44
+ validates :title, presence: true
45
+ end
46
+
47
+ # A category
48
+ class Category < ActiveRecord::Base
49
+ has_many :books
50
+ end
51
+
52
+ # A tag
53
+ class Tag < ActiveRecord::Base
54
+ has_and_belongs_to_many :books
55
+ end
56
+
57
+ # A chapter
58
+ class Chapter < ActiveRecord::Base
59
+ belongs_to :book
60
+
61
+ validates :title, presence: true
62
+ end
63
+
64
+ ##############################################################################
65
+
66
+ # App main class
67
+ class App < Sinatra::Application
68
+ register Sinatra::RestApi
69
+ register Sinatra::ActiveRecordExtension
70
+
71
+ # model Author, actions: { list: { verb: :post }, read: { verb: :post } }
72
+ # model Author, actions: { list: true, read: true }
73
+
74
+ # set :restapi_request_type, :json
75
+
76
+ resource Author, singular: 'writer' # , plural: 'writers'
77
+ resource Book
78
+ resource Category do
79
+ actions [ :list, :read ]
80
+ end
81
+ resource Chapter
82
+ resource Tag # , actions: [ :list, :read ]
83
+
84
+ configure do
85
+ env = ENV['RACK_ENV'] || 'development'
86
+ conf = YAML.load( File.read( File.expand_path( '../database.yml', __FILE__ ) ) )
87
+ conf[env]['database'] = File.expand_path( '../' + conf[env]['database'], __FILE__ )
88
+ set :database, conf[env]
89
+ end
90
+
91
+ before do
92
+ content_type :json
93
+ headers( 'Access-Control-Allow-Origin' => '*',
94
+ 'Access-Control-Allow-Methods' => Sinatra::RestApi::Router::VERBS.join(',').upcase,
95
+ 'Access-Control-Allow-Headers' => 'Origin, Content-Type, Accept, Authorization, Token',
96
+ 'Access-Control-Expose-Headers' => 'X-Total-Count' )
97
+ end
98
+
99
+ options '*' do
100
+ response.headers['Access-Control-Allow-Origin'] = '*'
101
+ response.headers['Access-Control-Allow-Methods'] = 'HEAD,GET,PUT,DELETE,OPTIONS'
102
+ response.headers['Access-Control-Allow-Headers'] = 'X-Requested-With, X-HTTP-Method-Override, Content-Type, Cache-Control, Accept'
103
+ halt 200
104
+ end
105
+
106
+ get '/' do
107
+ Sinatra::RestApi::Router.list_routes.to_json
108
+ end
109
+
110
+ not_found do
111
+ return if JSON.parse( body[0] ).include?( 'error' ) rescue nil # Error already defined
112
+ [ 404, { message: 'This is not the page you are looking for...' }.to_json ]
113
+ end
114
+
115
+ run! if app_file == $PROGRAM_NAME # = $0 ## starts the server if executed directly by ruby
116
+ end
117
+ end