carte-server 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,20 @@
1
+ module Carte
2
+ class Server < Sinatra::Base
3
+ module Models
4
+ class History
5
+ include Mongoid::Document
6
+ include Mongoid::Timestamps
7
+ field :title, type: String
8
+ field :content, type: String
9
+ field :version, type: Integer
10
+ belongs_to :card
11
+
12
+ before_create do
13
+ self.title = self.card.title
14
+ self.content = self.card.content
15
+ self.version = self.card.version
16
+ end
17
+ end
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,7 @@
1
+ require 'sinatra/base'
2
+
3
+ module Carte
4
+ class Server < Sinatra::Base
5
+ VERSION = "0.0.1"
6
+ end
7
+ end
@@ -0,0 +1,18 @@
1
+ xml.instruct! :xml, version: '1.0'
2
+ xml.rss version: "2.0", :"xmlns:atom" => "http://www.w3.org/2005/Atom" do
3
+ xml.channel do
4
+ xml.tag! "atom:link", href: "http://#{request.host}/api/cards.xml?#{request.env['QUERY_STRING']}", rel: "self", type: "application/rss+xml"
5
+ xml.title "carte"
6
+ xml.description "something like dictionary, wiki, or information card"
7
+ xml.link "http://#{request.host}/"
8
+ @cards.each do |card|
9
+ xml.item do
10
+ xml.title(card.title)
11
+ xml.description card.content
12
+ xml.link("http://#{request.host}/#/#{URI.escape(card.title)}")
13
+ xml.pubDate card.updated_at.rfc822
14
+ xml.guid({isPermaLink: false}, "http://#{request.host}/#/#{URI.escape(card.title)}##{card.updated_at.to_i}")
15
+ end
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,27 @@
1
+ !!! 5
2
+ %html
3
+ %head
4
+ %meta{charset:"utf-8"}
5
+ %title= settings.title
6
+ %meta{name:"viewport",content:"width=device-width,initial-scale=1.0"}
7
+ %meta{name:"description",content:settings.description}
8
+ %script{type:"text/javascript",src:"/app.js"}
9
+ :css
10
+ a, a:hover, a:visited, a:active {
11
+ color: #333333 !important;
12
+ text-decoration: none !important;
13
+ }
14
+ .glyphicon-refresh-animate {
15
+ -animation: spin .7s infinite linear;
16
+ -webkit-animation: spin2 .7s infinite linear;
17
+ }
18
+ @-webkit-keyframes spin2 {
19
+ from { -webkit-transform: rotate(0deg);}
20
+ to { -webkit-transform: rotate(360deg);}
21
+ }
22
+ @keyframes spin {
23
+ from { transform: scale(1) rotate(0deg);}
24
+ to { transform: scale(1) rotate(360deg);}
25
+ }
26
+ %body
27
+ #app
File without changes
@@ -0,0 +1,10 @@
1
+ development:
2
+ sessions:
3
+ default:
4
+ database: carde_development
5
+ hosts:
6
+ - localhost:27017
7
+ production:
8
+ sessions:
9
+ default:
10
+ uri: <%= ENV['MONGOHQ_URL'] %>
@@ -0,0 +1,36 @@
1
+ {
2
+ "name": "carte-client",
3
+ "description": "something like dictionary, wiki, or information card",
4
+ "version": "0.0.1",
5
+ "main": "lib/carte.coffee",
6
+ "scripts": {
7
+ "test": "echo \"Error: no test specified\" && exit 1"
8
+ },
9
+ "repository": {
10
+ "type": "git",
11
+ "url": "git://github.com/tily/carte.git"
12
+ },
13
+ "author": "tily",
14
+ "license": "ISC",
15
+ "bugs": {
16
+ "url": "https://github.com/tily/carte/issues"
17
+ },
18
+ "homepage": "https://github.com/tily/carte",
19
+ "dependencies": {
20
+ "backbone": "^1.1.2",
21
+ "bootstrap": "^3.3.4",
22
+ "browserify": "^9.0.8",
23
+ "coffee-reactify": "^3.0.0",
24
+ "coffee-script": "^1.9.2",
25
+ "coffeeify": "^1.0.0",
26
+ "cssify": "^0.7.0",
27
+ "debowerify": "^1.2.1",
28
+ "gulp": "^3.8.11",
29
+ "gulp-util": "^3.0.4",
30
+ "jquery": "^2.1.3",
31
+ "react": "^0.13.2",
32
+ "react-bootstrap": "^0.21.0",
33
+ "vinyl-source-stream": "^1.1.0",
34
+ "watchify": "^3.1.2"
35
+ }
36
+ }
Binary file
@@ -0,0 +1,174 @@
1
+ require 'httparty'
2
+ require 'carte/server'
3
+ include Carte::Server::Models
4
+
5
+ class Carte::Server
6
+ configure do
7
+ Mongoid.load! 'mongoid.yml'
8
+ end
9
+ end
10
+
11
+ class DictionaryClient
12
+ include HTTParty
13
+ base_uri 'http://localhost/api/'
14
+ format :json
15
+ end
16
+
17
+ def client
18
+ @client ||= DictionaryClient
19
+ end
20
+
21
+ describe 'API' do
22
+ before do
23
+ [Card, History].each do |model|
24
+ model.delete_all
25
+ end
26
+ end
27
+
28
+ context 'POST /cards.json' do
29
+ it 'creates a card' do
30
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
31
+ expect(response.code).to eq(201)
32
+ expect(response['card']['id']).to be_numeric
33
+ response = client.get('/cards.json')
34
+ expect(response['cards'][0]['title']).to eq('card1')
35
+ expect(response['cards'][0]['content']).to eq('content1')
36
+ expect(response['cards'][0]['version']).to eq(1)
37
+ end
38
+
39
+ context 'error' do
40
+ it 'returns error when the title is not specified' do
41
+ response = client.post('/cards.json', body: {content: 'content1'}.to_json)
42
+ expect(response.code).to eq(400)
43
+ expect(response['card']['errors']).to eq({'title' => ['が入力されていません']})
44
+ end
45
+
46
+ it 'returns error when the content is not specified' do
47
+ response = client.post('/cards.json', body: {title: 'card1'}.to_json)
48
+ expect(response.code).to eq(400)
49
+ expect(response['card']['errors']).to eq({'content' => ['が入力されていません']})
50
+ end
51
+
52
+ it 'returns error when the title is not unique' do
53
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
54
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
55
+ expect(response.code).to eq(400)
56
+ expect(response['card']['errors']).to eq({'title' => ['は既に存在します']})
57
+ end
58
+
59
+ it 'returns error when the title is too long' do
60
+ response = client.post('/cards.json', body: {title: 'w' * 71, content: 'content1'}.to_json)
61
+ expect(response.code).to eq(400)
62
+ expect(response['card']['errors']).to eq({'title' => ['は 70 文字以内で入力してください']})
63
+ end
64
+
65
+ it 'returns error when the content is too long' do
66
+ response = client.post('/cards.json', body: {title: 'card1', content: 'd' * 561}.to_json)
67
+ expect(response.code).to eq(400)
68
+ expect(response['card']['errors']).to eq({'content' => ['は 560 文字以内で入力してください']})
69
+ end
70
+ end
71
+ end
72
+
73
+ context 'GET /cards.json' do
74
+ it 'returns cards' do
75
+ pending
76
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
77
+ response = client.get('/cards.json')
78
+ expect(response.code).to eq(200)
79
+ end
80
+
81
+ context 'with parameters' do
82
+ pending
83
+ end
84
+ end
85
+
86
+ context 'GET /cards/:title.json' do
87
+ it 'returns the card' do
88
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
89
+ response = client.get("/cards/card1.json")
90
+ expect(response.code).to eq(200)
91
+ expect(response['card']['title']).to eq('card1')
92
+ expect(response['card']['content']).to eq('content1')
93
+ expect(response['card']['version']).to be(1)
94
+ end
95
+
96
+ context 'error' do
97
+ it 'returns error when the card is not found' do
98
+ response = client.get("/cards/notexists.json")
99
+ expect(response.code).to eq(404)
100
+ expect(response.parsed_response).to eq({})
101
+ end
102
+ end
103
+ end
104
+
105
+ context 'PUT /cards/:title.json' do
106
+ it 'updates the card' do
107
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
108
+ response = client.put("/cards/card1.json", body: {new_title: 'card1updated', content: 'content1updated'}.to_json)
109
+ expect(response.code).to eq(201)
110
+ expect(response.parsed_response).to eq({})
111
+ response = client.get("/cards/card1updated.json")
112
+ expect(response['card']['title']).to eq('card1updated')
113
+ expect(response['card']['content']).to eq('content1updated')
114
+ expect(response['card']['version']).to eq(2)
115
+ end
116
+
117
+ context 'error' do
118
+ it 'returns error when the card is not found' do
119
+ response = client.put("/cards/notexists.json", body: {new_title: 'card1updated', content: 'content1updated'}.to_json)
120
+ expect(response.code).to eq(404)
121
+ expect(response.parsed_response).to eq({})
122
+ end
123
+
124
+ it 'returns error when the title is not unique' do
125
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
126
+ response = client.post('/cards.json', body: {title: 'card2', content: 'content2'}.to_json)
127
+ response = client.put("/cards/card2.json", body: {new_title: 'card1', content: 'content1'}.to_json)
128
+ expect(response.code).to eq(400)
129
+ expect(response['card']['errors']).to eq({'title' => ['は既に存在します']})
130
+ end
131
+
132
+ it 'returns error when the title is too long' do
133
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
134
+ response = client.put("/cards/card1.json", body: {new_title: 'w' * 71}.to_json)
135
+ expect(response.code).to eq(400)
136
+ expect(response['card']['errors']).to eq({'title' => ['は 70 文字以内で入力してください']})
137
+ end
138
+
139
+ it 'returns error when the content is too long' do
140
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
141
+ response = client.put("/cards/card1.json", body: {content: 'd' * 561}.to_json)
142
+ expect(response.code).to eq(400)
143
+ expect(response['card']['errors']).to eq({'content' => ['は 560 文字以内で入力してください']})
144
+ end
145
+ end
146
+ end
147
+
148
+ context 'GET /cards/:title/history.json' do
149
+ it 'returns no history when there is no history' do
150
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
151
+ response = client.get("/cards/card1/history.json")
152
+ expect(response.code).to eq(200)
153
+ expect(response['history']).to eq([])
154
+ end
155
+
156
+ it 'returns history when there is history' do
157
+ response = client.post('/cards.json', body: {title: 'card1', content: 'content1'}.to_json)
158
+ response = client.put("/cards/card1.json", body: {new_title: 'card1updated1', content: 'content1updated1'}.to_json)
159
+ response = client.put("/cards/card1updated1.json", body: {new_title: 'card1updated2', content: 'content1updated2'}.to_json)
160
+ response = client.put("/cards/card1updated2.json", body: {new_title: 'card1updated3', content: 'content1updated3'}.to_json)
161
+ response = client.get("/cards/card1updated3/history.json")
162
+ expect(response.code).to eq(200)
163
+ expect(response['history'].size).to eq(3)
164
+ end
165
+
166
+ context 'error' do
167
+ it 'returns error when the card is not found' do
168
+ response = client.get("/cards/notexists/history.json")
169
+ expect(response.code).to eq(404)
170
+ expect(response.parsed_response).to eq({})
171
+ end
172
+ end
173
+ end
174
+ end
metadata ADDED
@@ -0,0 +1,248 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: carte-server
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - tily
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2015-04-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: bundler
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.7'
20
+ type: :development
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.7'
27
+ - !ruby/object:Gem::Dependency
28
+ name: rake
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '10.0'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '10.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: shotgun
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rspec
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: httparty
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: sinatra
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :runtime
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: sinatra-contrib
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - '>='
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :runtime
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - '>='
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: mongoid
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :runtime
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - '>='
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: mongoid_auto_increment_id
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - '='
130
+ - !ruby/object:Gem::Version
131
+ version: 0.6.5
132
+ type: :runtime
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - '='
137
+ - !ruby/object:Gem::Version
138
+ version: 0.6.5
139
+ - !ruby/object:Gem::Dependency
140
+ name: will_paginate_mongoid
141
+ requirement: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ type: :runtime
147
+ prerelease: false
148
+ version_requirements: !ruby/object:Gem::Requirement
149
+ requirements:
150
+ - - '>='
151
+ - !ruby/object:Gem::Version
152
+ version: '0'
153
+ - !ruby/object:Gem::Dependency
154
+ name: activesupport
155
+ requirement: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - '>='
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ type: :runtime
161
+ prerelease: false
162
+ version_requirements: !ruby/object:Gem::Requirement
163
+ requirements:
164
+ - - '>='
165
+ - !ruby/object:Gem::Version
166
+ version: '0'
167
+ - !ruby/object:Gem::Dependency
168
+ name: haml
169
+ requirement: !ruby/object:Gem::Requirement
170
+ requirements:
171
+ - - '>='
172
+ - !ruby/object:Gem::Version
173
+ version: '0'
174
+ type: :runtime
175
+ prerelease: false
176
+ version_requirements: !ruby/object:Gem::Requirement
177
+ requirements:
178
+ - - '>='
179
+ - !ruby/object:Gem::Version
180
+ version: '0'
181
+ description: something like dictionary, wiki, or information card
182
+ email:
183
+ - tidnlyam@gmail.com
184
+ executables: []
185
+ extensions: []
186
+ extra_rdoc_files: []
187
+ files:
188
+ - .gitignore
189
+ - Gemfile
190
+ - LICENSE.txt
191
+ - README.md
192
+ - Rakefile
193
+ - carte.gemspec
194
+ - config.json
195
+ - config.ru
196
+ - gulpfile.coffee
197
+ - lib/carte.coffee
198
+ - lib/carte.rb
199
+ - lib/carte/client.coffee
200
+ - lib/carte/client/models/card.coffee
201
+ - lib/carte/client/models/cards.coffee
202
+ - lib/carte/client/router.coffee
203
+ - lib/carte/client/views/app.cjsx
204
+ - lib/carte/client/views/card.cjsx
205
+ - lib/carte/client/views/cards.cjsx
206
+ - lib/carte/client/views/content.cjsx
207
+ - lib/carte/client/views/edit.cjsx
208
+ - lib/carte/client/views/footer.cjsx
209
+ - lib/carte/client/views/header.cjsx
210
+ - lib/carte/client/views/list.cjsx
211
+ - lib/carte/server.rb
212
+ - lib/carte/server/models.rb
213
+ - lib/carte/server/models/card.rb
214
+ - lib/carte/server/models/history.rb
215
+ - lib/carte/server/version.rb
216
+ - lib/carte/server/views/cards.builder
217
+ - lib/carte/server/views/index.haml
218
+ - lib/carte/shared/.keep
219
+ - mongoid.yml
220
+ - package.json
221
+ - public/images/icon.png
222
+ - spec/server_spec.rb
223
+ homepage: ''
224
+ licenses:
225
+ - MIT
226
+ metadata: {}
227
+ post_install_message:
228
+ rdoc_options: []
229
+ require_paths:
230
+ - lib
231
+ required_ruby_version: !ruby/object:Gem::Requirement
232
+ requirements:
233
+ - - '>='
234
+ - !ruby/object:Gem::Version
235
+ version: '0'
236
+ required_rubygems_version: !ruby/object:Gem::Requirement
237
+ requirements:
238
+ - - '>='
239
+ - !ruby/object:Gem::Version
240
+ version: '0'
241
+ requirements: []
242
+ rubyforge_project:
243
+ rubygems_version: 2.3.0
244
+ signing_key:
245
+ specification_version: 4
246
+ summary: something like dictionary, wiki, or information card
247
+ test_files:
248
+ - spec/server_spec.rb