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,8 @@
1
+ # config.ru (run with rackup)
2
+
3
+ # Launch with:
4
+ # rackup -o 0.0.0.0 -p 4567
5
+
6
+ require './app'
7
+
8
+ run ActiveRecordTest::App
@@ -0,0 +1,7 @@
1
+ development:
2
+ adapter: sqlite3
3
+ database: 'db/db.sqlite3'
4
+
5
+ test:
6
+ adapter: sqlite3
7
+ database: 'db/test.sqlite3'
@@ -0,0 +1,11 @@
1
+ # Authors
2
+ class CreateAuthors < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :authors do |t|
5
+ t.string :name, null: false
6
+ t.string :email, null: false
7
+ t.timestamp :created_at
8
+ t.timestamp :updated_at
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,10 @@
1
+ # Categories
2
+ class CreateCategories < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :categories do |t|
5
+ t.string :name, null: false
6
+ t.timestamp :created_at
7
+ t.timestamp :updated_at
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,16 @@
1
+ # Books
2
+ class CreateBooks < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :books do |t|
5
+ t.string :title, null: false
6
+ t.text :description
7
+ t.integer :pages
8
+ t.float :price
9
+ t.datetime :dt
10
+ t.integer :author_id
11
+ t.integer :category_id
12
+ t.timestamp :created_at
13
+ t.timestamp :updated_at
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,10 @@
1
+ # Tags
2
+ class CreateTags < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :tags do |t|
5
+ t.string :name, null: false
6
+ t.timestamp :created_at
7
+ t.timestamp :updated_at
8
+ end
9
+ end
10
+ end
@@ -0,0 +1,11 @@
1
+ # BooksTags
2
+ class CreateBooksTags < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :books_tags do |t|
5
+ t.integer :book_id, null: false
6
+ t.integer :tag_id, null: false
7
+ t.timestamp :created_at
8
+ t.timestamp :updated_at
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,12 @@
1
+ # Authors
2
+ class CreateChapters < ActiveRecord::Migration[4.2]
3
+ def change
4
+ create_table :chapters do |t|
5
+ t.string :title, null: false
6
+ t.integer :page
7
+ t.integer :book_id
8
+ t.timestamp :created_at
9
+ t.timestamp :updated_at
10
+ end
11
+ end
12
+ end
@@ -0,0 +1,61 @@
1
+ # This file is auto-generated from the current state of the database. Instead
2
+ # of editing this file, please use the migrations feature of Active Record to
3
+ # incrementally modify your database, and then regenerate this schema definition.
4
+ #
5
+ # Note that this schema.rb definition is the authoritative source for your
6
+ # database schema. If you need to create the application database on another
7
+ # system, you should be using db:schema:load, not running all the migrations
8
+ # from scratch. The latter is a flawed and unsustainable approach (the more migrations
9
+ # you'll amass, the slower it'll run and the greater likelihood for issues).
10
+ #
11
+ # It's strongly recommended that you check this file into your version control system.
12
+
13
+ ActiveRecord::Schema.define(version: 6) do
14
+
15
+ create_table "authors", force: :cascade do |t|
16
+ t.string "name", null: false
17
+ t.string "email", null: false
18
+ t.datetime "created_at"
19
+ t.datetime "updated_at"
20
+ end
21
+
22
+ create_table "books", force: :cascade do |t|
23
+ t.string "title", null: false
24
+ t.text "description"
25
+ t.integer "pages"
26
+ t.float "price"
27
+ t.datetime "dt"
28
+ t.integer "author_id"
29
+ t.integer "category_id"
30
+ t.datetime "created_at"
31
+ t.datetime "updated_at"
32
+ end
33
+
34
+ create_table "books_tags", force: :cascade do |t|
35
+ t.integer "book_id", null: false
36
+ t.integer "tag_id", null: false
37
+ t.datetime "created_at"
38
+ t.datetime "updated_at"
39
+ end
40
+
41
+ create_table "categories", force: :cascade do |t|
42
+ t.string "name", null: false
43
+ t.datetime "created_at"
44
+ t.datetime "updated_at"
45
+ end
46
+
47
+ create_table "chapters", force: :cascade do |t|
48
+ t.string "title", null: false
49
+ t.integer "page"
50
+ t.integer "book_id"
51
+ t.datetime "created_at"
52
+ t.datetime "updated_at"
53
+ end
54
+
55
+ create_table "tags", force: :cascade do |t|
56
+ t.string "name", null: false
57
+ t.datetime "created_at"
58
+ t.datetime "updated_at"
59
+ end
60
+
61
+ end
File without changes
@@ -0,0 +1,10 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gem 'pry'
4
+ gem 'pry-rescue'
5
+
6
+ gem 'sinatra'
7
+ gem 'slim'
8
+ gem 'thin'
9
+
10
+ gem 'activeresource'
@@ -0,0 +1,68 @@
1
+ GEM
2
+ remote: https://rubygems.org/
3
+ specs:
4
+ activemodel (4.2.7.1)
5
+ activesupport (= 4.2.7.1)
6
+ builder (~> 3.1)
7
+ activeresource (4.1.0)
8
+ activemodel (~> 4.0)
9
+ activesupport (~> 4.0)
10
+ rails-observers (~> 0.1.2)
11
+ activesupport (4.2.7.1)
12
+ i18n (~> 0.7)
13
+ json (~> 1.7, >= 1.7.7)
14
+ minitest (~> 5.1)
15
+ thread_safe (~> 0.3, >= 0.3.4)
16
+ tzinfo (~> 1.1)
17
+ builder (3.2.2)
18
+ coderay (1.1.1)
19
+ daemons (1.2.4)
20
+ eventmachine (1.2.0.1)
21
+ i18n (0.7.0)
22
+ interception (0.5)
23
+ json (1.8.3)
24
+ method_source (0.8.2)
25
+ minitest (5.9.1)
26
+ pry (0.10.4)
27
+ coderay (~> 1.1.0)
28
+ method_source (~> 0.8.1)
29
+ slop (~> 3.4)
30
+ pry-rescue (1.4.4)
31
+ interception (>= 0.5)
32
+ pry
33
+ rack (1.6.4)
34
+ rack-protection (1.5.3)
35
+ rack
36
+ rails-observers (0.1.2)
37
+ activemodel (~> 4.0)
38
+ sinatra (1.4.7)
39
+ rack (~> 1.5)
40
+ rack-protection (~> 1.4)
41
+ tilt (>= 1.3, < 3)
42
+ slim (3.0.7)
43
+ temple (~> 0.7.6)
44
+ tilt (>= 1.3.3, < 2.1)
45
+ slop (3.6.0)
46
+ temple (0.7.7)
47
+ thin (1.7.0)
48
+ daemons (~> 1.0, >= 1.0.9)
49
+ eventmachine (~> 1.0, >= 1.0.4)
50
+ rack (>= 1, < 3)
51
+ thread_safe (0.3.5)
52
+ tilt (2.0.5)
53
+ tzinfo (1.2.2)
54
+ thread_safe (~> 0.1)
55
+
56
+ PLATFORMS
57
+ ruby
58
+
59
+ DEPENDENCIES
60
+ activeresource
61
+ pry
62
+ pry-rescue
63
+ sinatra
64
+ slim
65
+ thin
66
+
67
+ BUNDLED WITH
68
+ 1.13.5
@@ -0,0 +1,125 @@
1
+ require 'pry'
2
+
3
+ require 'sinatra/base'
4
+ require 'slim'
5
+ require 'activeresource'
6
+
7
+ # Active Resource Test client
8
+ module ActiveResourceTest
9
+ # Handle JSON response
10
+ class JsonFormatter
11
+ include ActiveResource::Formats::JsonFormat
12
+
13
+ attr_reader :collection_name
14
+
15
+ def initialize(collection_name)
16
+ @collection_name = collection_name.to_s
17
+ end
18
+
19
+ def decode(json)
20
+ remove_root(ActiveSupport::JSON.decode(json))
21
+ end
22
+
23
+ private
24
+
25
+ def remove_root(data)
26
+ if data.is_a?(Hash) && data[collection_name]
27
+ data[collection_name]
28
+ else
29
+ data
30
+ end
31
+ end
32
+ end
33
+
34
+ # Base class
35
+ class Base < ActiveResource::Base
36
+ self.site = 'http://localhost:3000'
37
+ self.include_root_in_json = true
38
+ self.format = JsonFormatter.new( :collection_name )
39
+ end
40
+
41
+ # Author class
42
+ class Writer < Base
43
+ # self.element_name = 'writer'
44
+ end
45
+
46
+ # Book class
47
+ class Book < Base; end
48
+
49
+ # Category class
50
+ class Category < Base; end
51
+
52
+ # Chapter class
53
+ class Chapter < Base; end
54
+
55
+ # Tag class
56
+ class Tag < Base; end
57
+
58
+ # Main class
59
+ class App < Sinatra::Application
60
+ configure do
61
+ set :port, 4000
62
+ set :views, settings.root
63
+ end
64
+
65
+ before do
66
+ @models ||= { writers: Writer, books: Book, categories: Category, chapters: Chapter, tags: Tag }
67
+ @links ||= [
68
+ [ '/', 'Main' ],
69
+ [ '/writers', 'Authors' ],
70
+ [ '/books', 'Books' ],
71
+ [ '/categories', 'Categories' ],
72
+ [ '/chapters', 'Chapters' ],
73
+ [ '/tags', 'Tags' ]
74
+ ]
75
+ end
76
+
77
+ get '/' do
78
+ @details = OpenStruct.new( attributes: {} )
79
+ slim 'h2 Main', layout: :layout
80
+ end
81
+
82
+ # List
83
+ get '/:model' do
84
+ mod = @models[params[:model].to_sym]
85
+ @model = mod.to_s.split( '::' ).last.gsub( /([A-Z]+)([A-Z][a-z])/, '\1_\2' ).gsub( /([a-z\d])([A-Z])/, '\1_\2' ).tr( '-', '_' ).downcase
86
+ @list = mod.all
87
+ slim "h2 #{params[:model]}", layout: :layout
88
+ end
89
+
90
+ # Create
91
+ post '/:model' do
92
+ mod = @models[params[:model].to_sym]
93
+ @model = mod.to_s.split( '::' ).last.gsub( /([A-Z]+)([A-Z][a-z])/, '\1_\2' ).gsub( /([a-z\d])([A-Z])/, '\1_\2' ).tr( '-', '_' ).downcase
94
+ mod.new( @model => params[@model] ).save
95
+ redirect to "/#{params[:model]}"
96
+ end
97
+
98
+ # Read
99
+ get '/:model/:id' do
100
+ mod = @models[params[:model].to_sym]
101
+ @details = mod.find( params[:id] )
102
+ @model = mod.to_s.split( '::' ).last.gsub( /([A-Z]+)([A-Z][a-z])/, '\1_\2' ).gsub( /([a-z\d])([A-Z])/, '\1_\2' ).tr( '-', '_' ).downcase
103
+ slim "h2 #{params[:model]}", layout: :layout
104
+ end
105
+
106
+ # Update
107
+ post '/:model/:id' do
108
+ mod = @models[params[:model].to_sym]
109
+ @details = mod.find( params[:id] )
110
+ @model = mod.to_s.split( '::' ).last.gsub( /([A-Z]+)([A-Z][a-z])/, '\1_\2' ).gsub( /([a-z\d])([A-Z])/, '\1_\2' ).tr( '-', '_' ).downcase
111
+ params[@model].each { |k, v| @details.send( "#{k}=", v ) }
112
+ @details.save
113
+ redirect to "/#{params[:model]}"
114
+ end
115
+
116
+ # Delete
117
+ get '/:model/:id/delete' do
118
+ @item = @models[params[:model].to_sym].find( params[:id] )
119
+ @item.destroy
120
+ redirect to "/#{params[:model]}"
121
+ end
122
+
123
+ run! if app_file == $PROGRAM_NAME # = $0 ## starts the server if executed directly by ruby
124
+ end
125
+ end
@@ -0,0 +1,9 @@
1
+ # config.ru (run with rackup)
2
+
3
+ # Launch with:
4
+ # rackup -o 0.0.0.0 -p 4567
5
+
6
+ require './app'
7
+
8
+ # run App
9
+ run ActiveResourceTest::App
@@ -0,0 +1,78 @@
1
+ doctype html
2
+ html
3
+ head
4
+ title Test
5
+ link rel='stylesheet' href='http://yui.yahooapis.com/pure/0.6.0/pure-min.css'
6
+ css:
7
+ a { color: #b00; text-decoration: none; }
8
+ body { padding: 0 15px; }
9
+ input[type='submit'] { margin-top: 15px; }
10
+ form { margin-top: 30px; }
11
+ hr { margin: 20px 0; }
12
+ legend { font-style: italic; font-weight: bold; }
13
+ table { font-size: 13px; }
14
+ body
15
+ == yield
16
+ - unless @links.nil?
17
+ / Menu
18
+ div
19
+ - @links.each do |link|
20
+ a.pure-button.pure-button-primary href="#{link[0]}" = link[1]
21
+ | &nbsp;
22
+ hr
23
+ - if !@list.nil? && @list.any?
24
+ / List
25
+ table.pure-table
26
+ thead
27
+ th
28
+ - @list.first.attributes.keys.each do |col|
29
+ th = col
30
+ tbody
31
+ - @list.each_with_index do |row, index|
32
+ tr
33
+ td
34
+ a href="#{request.path_info + '/' + row.id.to_s}"
35
+ = '#' + ( index + 1 ).to_s
36
+ - row.attributes.each do |cell|
37
+ - value = cell[1]
38
+ td
39
+ - if value.is_a? Array
40
+ = value.map( &:id ).join( ', ' )
41
+ - elsif value.class.ancestors.include? ActiveResource::Base
42
+ = value.name if value.attributes.has_key? :name
43
+ = value.title if value.attributes.has_key? :title
44
+ - else
45
+ = value
46
+ - if !@details.nil? && !@model.nil?
47
+ / Edit
48
+ form.pure-form.pure-form-stacked method='post' action=''
49
+ fieldset
50
+ legend = 'Edit ' + @model
51
+ table.pure-table
52
+ - @details.attributes.each do |key, value|
53
+ tr
54
+ td
55
+ b = key
56
+ td
57
+ - if value.is_a? Array
58
+ = value.map( &:id ).join( ', ' )
59
+ - elsif value.class.ancestors.include? ActiveResource::Base
60
+ = value.name if value.attributes.has_key? :name
61
+ = value.title if value.attributes.has_key? :title
62
+ - elsif key == 'id'
63
+ = value
64
+ - else
65
+ input type='text' name="#{@model}[#{key}]" value="#{value}"
66
+ input.pure-button.pure-button-success type='submit' value='update'
67
+ form.pure-form.pure-form-stacked method='delete' action='#{params[:id]}/delete'
68
+ input.pure-button.pure-button-success type='submit' value='delete'
69
+ - elsif !@model.nil?
70
+ / Form new
71
+ form.pure-form.pure-form-stacked method='post' action=''
72
+ fieldset
73
+ legend = 'Create ' + @model
74
+ - @list.first.attributes.keys.each do |col|
75
+ - if col != 'id'
76
+ label = col
77
+ input type='text' name="#{@model}[#{col}]" value=''
78
+ input.pure-button.pure-button-success type='submit' value='create'