noodles 0.0.1 → 0.0.6

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 (57) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +10 -0
  4. data/Gemfile +1 -0
  5. data/LICENSE.txt +1 -1
  6. data/README.md +9 -1
  7. data/Rakefile +10 -0
  8. data/bin/noodles +2 -0
  9. data/cli/noodles_cli.rb +92 -0
  10. data/cli/template/.gitignore +0 -0
  11. data/cli/template/Gemfile +6 -0
  12. data/cli/template/app/controllers/.keep +0 -0
  13. data/cli/template/app/handlers/.keep +0 -0
  14. data/cli/template/app/templates/.keep +0 -0
  15. data/cli/template/app/views/.keep +0 -0
  16. data/cli/template/config.ru +12 -0
  17. data/cli/template/config/application.rb +7 -0
  18. data/cli/template/config/router.rb +2 -0
  19. data/cli/template/config/secrets.yml +7 -0
  20. data/cli/template/config/setup.rb +3 -0
  21. data/cli/template/public/css/.keep +0 -0
  22. data/cli/template/public/images/.keep +0 -0
  23. data/cli/template/public/js/.keep +0 -0
  24. data/lib/noodles.rb +51 -3
  25. data/lib/noodles/application.rb +23 -0
  26. data/lib/noodles/cache.rb +6 -0
  27. data/lib/noodles/dependencies.rb +12 -0
  28. data/lib/noodles/environment.rb +47 -0
  29. data/lib/noodles/http/application.rb +34 -0
  30. data/lib/noodles/http/controller.rb +106 -0
  31. data/lib/noodles/http/errors/no_router_error.rb +9 -0
  32. data/lib/noodles/http/router.rb +81 -0
  33. data/lib/noodles/http/view.rb +6 -0
  34. data/lib/noodles/utils.rb +8 -0
  35. data/lib/noodles/version.rb +1 -1
  36. data/lib/noodles/websocket/application.rb +14 -0
  37. data/lib/noodles/websocket/channel.rb +22 -0
  38. data/lib/noodles/websocket/handler.rb +47 -0
  39. data/lib/noodles/websocket/routing.rb +12 -0
  40. data/noodles.gemspec +22 -6
  41. data/test/secrets.yml +11 -0
  42. data/test/templates/current_user_temp.erb +1 -0
  43. data/test/templates/current_user_temp.haml +1 -0
  44. data/test/templates/current_user_temp.slim +1 -0
  45. data/test/templates/index.haml +2 -0
  46. data/test/templates/index.slim +2 -0
  47. data/test/templates/layout.haml +3 -0
  48. data/test/templates/show.erb +1 -0
  49. data/test/templates/with_variables.erb +2 -0
  50. data/test/templates/with_variables.haml +2 -0
  51. data/test/templates/with_variables.slim +2 -0
  52. data/test/test_application.rb +299 -0
  53. data/test/test_cache.rb +66 -0
  54. data/test/test_environment.rb +24 -0
  55. data/test/test_helper.rb +10 -0
  56. data/test/test_secrets.rb +24 -0
  57. metadata +271 -10
@@ -0,0 +1,9 @@
1
+ module Noodles
2
+ module Http
3
+ class NoRouterError < StandardError
4
+ def initialize
5
+ super("No HTTP Routes defined!")
6
+ end
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,81 @@
1
+ module Noodles
2
+ module Http
3
+ class Router
4
+ attr_reader :routes
5
+
6
+ def initialize
7
+ @routes = []
8
+ end
9
+
10
+ [:get, :post, :put, :delete].each do |method|
11
+ define_method method do |url, destination|
12
+ match(method, url, destination)
13
+ end
14
+ end
15
+
16
+ def root_to(destination)
17
+ get('', destination)
18
+ end
19
+
20
+ def find_by_url(method, url)
21
+ method = method.downcase.to_sym
22
+
23
+ route = routes.find do |route|
24
+ route[:method] == method and route[:regexp].match(url)
25
+ end
26
+
27
+ return if route.nil?
28
+
29
+ data_match = route[:regexp].match(url)
30
+
31
+ path_params = {}
32
+ route[:path_params].each_with_index do |path_param, index|
33
+ path_params[path_param] = data_match.captures[index]
34
+ end
35
+ get_destination(route[:destination], path_params)
36
+ end
37
+
38
+ private
39
+
40
+ def match(method, url, destination)
41
+ regexp, path_params = regexed_url_and_path_params(url)
42
+
43
+ routes.push method: method, url: url, regexp: Regexp.new("^/#{regexp}$"),
44
+ destination: destination, path_params: path_params
45
+ end
46
+
47
+
48
+ def regexed_url_and_path_params(url)
49
+ url_parts = url.split("/")
50
+ url_parts.select! { |p| !p.empty? }
51
+
52
+ path_params = []
53
+
54
+ regexp_parts = url_parts.map do |url_part|
55
+ if url_part[0] == ":"
56
+ path_params << url_part[1..-1]
57
+ "([a-zA-Z0-9]+)"
58
+ elsif url_part[0] == "*"
59
+ path_params << url_part[1..-1]
60
+ "(.*)"
61
+ else
62
+ url_part
63
+ end
64
+ end
65
+
66
+ regexp = regexp_parts.join("/")
67
+ [regexp, path_params]
68
+ end
69
+
70
+ def get_destination(destination, path_params = {})
71
+ return destination if destination.respond_to?(:call)
72
+
73
+ controller_name, action = destination.split('#')
74
+ controller_name = controller_name.capitalize
75
+ controller = Object.const_get("#{controller_name}Controller")
76
+ controller.action(action, path_params)
77
+ end
78
+
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,6 @@
1
+ module Noodles
2
+ module Http
3
+ class View
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ module Noodles
2
+ def self.to_underscore(string)
3
+ string.gsub(/::/, '/').
4
+ gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
5
+ gsub(/([a-z\d])([A-Z])/,'\1_\2').
6
+ tr("-", "_").downcase
7
+ end
8
+ end
@@ -1,3 +1,3 @@
1
1
  module Noodles
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.6"
3
3
  end
@@ -0,0 +1,14 @@
1
+ require "noodles/websocket/routing"
2
+ require "noodles/websocket/handler"
3
+ require "noodles/websocket/channel"
4
+
5
+ module Noodles
6
+ module Websocket
7
+ class Application
8
+ def call(env)
9
+ handler = get_handler(env)
10
+ handler.new.call(env)
11
+ end
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,22 @@
1
+ module Noodles
2
+ module Websocket
3
+ class Channel
4
+ # class << self
5
+ # attr_accessor :connections
6
+ # end
7
+ # self.connections = []
8
+
9
+ def self.connections
10
+ @@connections ||= []
11
+ end
12
+
13
+ def self.broadcast(msg)
14
+ connections.each do |connection|
15
+ connection.send_data msg
16
+ end
17
+ end
18
+
19
+
20
+ end
21
+ end
22
+ end
@@ -0,0 +1,47 @@
1
+ require 'rack/websocket'
2
+
3
+ module Noodles
4
+ module Websocket
5
+ class Handler < Rack::WebSocket::Application
6
+
7
+ @@connections ||= []
8
+
9
+ # def connection
10
+ # @websocket_handler.instance_variable_get("@connection")
11
+ # end
12
+
13
+ def add_connection handler
14
+ @@connections << handler
15
+ end
16
+
17
+
18
+ def remove_connection handler
19
+ @@connections.delete handler
20
+ end
21
+
22
+ def broadcast msg
23
+ @@connections.each do |connection|
24
+ connection.send_data msg
25
+ end
26
+ end
27
+
28
+ def broadcast_but_self msg
29
+ (@@connections - [self]).each do |connection|
30
+ connection.send_data msg
31
+ end
32
+ end
33
+
34
+ def request(env)
35
+ Rack::Request.new(env)
36
+ end
37
+
38
+ def params(env)
39
+ request(env).params
40
+ end
41
+
42
+ def connection_storage
43
+
44
+ end
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,12 @@
1
+ module Noodles
2
+ module Websocket
3
+ class Application
4
+ def get_handler(env)
5
+ _, handler, after = env['PATH_INFO'].split('/', 3)
6
+ handler = handler.capitalize
7
+ handler += 'Handler'
8
+ Object.const_get(handler)
9
+ end
10
+ end
11
+ end
12
+ end
@@ -6,18 +6,34 @@ require 'noodles/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "noodles"
8
8
  spec.version = Noodles::VERSION
9
- spec.authors = ["damir"]
9
+ spec.authors = ["Damir Svrtan"]
10
10
  spec.email = ["damir.svrtan@gmail.com"]
11
- spec.description = "Noodles"
12
- spec.summary = "Noodles"
11
+ spec.summary = "Rack based web framework"
13
12
  spec.homepage = ""
14
13
  spec.license = "MIT"
15
14
 
16
- spec.files = `git ls-files`.split($/)
15
+ spec.files = `git ls-files -z`.split("\x0")
17
16
  spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
17
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
18
  spec.require_paths = ["lib"]
20
19
 
21
- spec.add_development_dependency "bundler", "~> 1.3"
22
- spec.add_development_dependency "rake"
20
+ spec.add_development_dependency 'bundler', '~> 1.5'
21
+ spec.add_development_dependency 'rake'
22
+ spec.add_development_dependency 'rack-test'
23
+ spec.add_development_dependency 'minitest'
24
+ spec.add_development_dependency 'pry'
25
+
26
+ spec.add_runtime_dependency 'rack'
27
+ spec.add_runtime_dependency 'websocket-rack-noodles'
28
+ spec.add_runtime_dependency 'better_errors'
29
+ spec.add_runtime_dependency 'multi_json'
30
+ spec.add_runtime_dependency 'thor'
31
+
32
+ spec.add_runtime_dependency 'erubis'
33
+ spec.add_runtime_dependency 'slim'
34
+ spec.add_runtime_dependency 'haml'
35
+ spec.add_runtime_dependency 'tilt'
36
+
37
+ spec.add_runtime_dependency 'colorize'
38
+ spec.add_runtime_dependency 'dalli'
23
39
  end
@@ -0,0 +1,11 @@
1
+ development:
2
+
3
+ staging:
4
+
5
+ production:
6
+ facebook_id: 'zzz'
7
+ facebook_secret: <%= ENV['NOODLE_FB_SECRET'] %>
8
+ test:
9
+ facebook_id: 'xxx'
10
+ facebook_secret: <%= ENV['NOODLE_FB_SECRET'] %>
11
+
@@ -0,0 +1 @@
1
+ <%= current_user %>
@@ -0,0 +1 @@
1
+ = current_user
@@ -0,0 +1 @@
1
+ = current_user
@@ -0,0 +1,2 @@
1
+ %h1 Hello
2
+ %h2 Hello Twice
@@ -0,0 +1,2 @@
1
+ h1 Hello
2
+ h2 Hello Twice
@@ -0,0 +1,3 @@
1
+ %h1 THIS IS THE LAYOUT FILE
2
+ = yield
3
+ %h1 THIS IS THA FOOTER
@@ -0,0 +1 @@
1
+ <h1>Show</h1>
@@ -0,0 +1,2 @@
1
+ <%= @username %>
2
+ <%= @hello_message %>
@@ -0,0 +1,2 @@
1
+ = @username
2
+ = @hello_message
@@ -0,0 +1,2 @@
1
+ = @username
2
+ = @hello_message
@@ -0,0 +1,299 @@
1
+ require_relative 'test_helper'
2
+
3
+ class TestApp < Noodles::Application
4
+ end
5
+
6
+ module NoodleCurrent
7
+ def current_user
8
+ "Damir"
9
+ end
10
+ end
11
+
12
+ class NoodleView
13
+ include NoodleCurrent
14
+ end
15
+
16
+ class TestController < Noodles::Http::Controller
17
+ view NoodleView
18
+
19
+ def root_page
20
+ text "Root Page"
21
+ end
22
+
23
+ def index
24
+ text "hello"
25
+ end
26
+
27
+ def show
28
+ erb 'show'
29
+ end
30
+
31
+ def index_with_slim
32
+ slim 'index'
33
+ end
34
+
35
+ def index_with_haml
36
+ haml 'index'
37
+ end
38
+
39
+ def with_current_user
40
+ erb 'current_user_temp'
41
+ end
42
+
43
+ def with_current_user_haml
44
+ haml 'current_user_temp'
45
+ end
46
+
47
+ def with_current_user_slim
48
+ slim 'current_user_temp'
49
+ end
50
+
51
+ def with_variables_erb
52
+ @username = "Jack"
53
+ @hello_message = "HI!"
54
+ erb 'with_variables'
55
+ end
56
+
57
+ def with_variables_haml
58
+ @username = "Jack"
59
+ @hello_message = "HI!"
60
+ haml 'with_variables'
61
+ end
62
+
63
+ def with_variables_slim
64
+ @username = "Jack"
65
+ @hello_message = "HI!"
66
+ slim 'with_variables'
67
+ end
68
+
69
+ def change_response_status_code
70
+ response.status = 201
71
+ haml 'index'
72
+ end
73
+
74
+ def post_request
75
+ haml 'index'
76
+ end
77
+
78
+ def cookie_setting
79
+ response.set_cookie "user_id", 1
80
+ haml 'index'
81
+ end
82
+
83
+ def cookie_deletion
84
+ response.delete_cookie 'user_id'
85
+ haml 'index'
86
+ end
87
+
88
+ def redirecting_path
89
+ redirect 'test/index'
90
+ end
91
+
92
+ def json_response
93
+ json({ username: "Jack", sex: "M" })
94
+ end
95
+
96
+ private
97
+
98
+ def get_rendering_path(view_name, template_name)
99
+ File.join 'test', 'templates', "#{view_name}.#{template_name}"
100
+ end
101
+ end
102
+
103
+ class NoodlesTestApp < Minitest::Test
104
+ include Rack::Test::Methods
105
+
106
+ def app
107
+ app = TestApp.new
108
+ app.http_app.routes do
109
+ root_to "test#root_page"
110
+ get "test/index", "test#index"
111
+ get "test/show", "test#show"
112
+ get "test/index_with_slim", "test#index_with_slim"
113
+ get "test/index_with_haml", "test#index_with_haml"
114
+ get "pipa/:id/slavina/:slavina_id", "test#hamly"
115
+ get "sub-app", proc { |env| [200, {}, [env['PATH_INFO']]] }
116
+ get "sub-app2", proc { [200, {}, ['ANOTHER SUB APP']] }
117
+ get "with_variables_erb", "test#with_variables_erb"
118
+ get "with_variables_haml", "test#with_variables_haml"
119
+ get "with_variables_slim", "test#with_variables_slim"
120
+ get "change_response_status_code", "test#change_response_status_code"
121
+ get "cookie_setting", "test#cookie_setting"
122
+ get "cookie_deletion", "test#cookie_deletion"
123
+ post "testing_post", "test#post_request"
124
+ get "redirecting_path", "test#redirecting_path"
125
+ get 'with_current_user', "test#with_current_user"
126
+ get 'with_current_user_slim', "test#with_current_user_slim"
127
+ get 'with_current_user_haml', "test#with_current_user_haml"
128
+ get 'json_response', 'test#json_response'
129
+ end
130
+ app
131
+ end
132
+
133
+ def test_root_request
134
+ get "/"
135
+
136
+ assert last_response.ok?
137
+ body = last_response.body
138
+ assert body["Root Page"]
139
+ end
140
+
141
+ def test_index_request
142
+ get "/test/index"
143
+
144
+ assert last_response.ok?
145
+ assert last_response.body["hello"]
146
+ end
147
+
148
+ def test_show_request
149
+ get "/test/show"
150
+
151
+ assert last_response.ok?
152
+ assert last_response.body["<h1>Show</h1>"]
153
+ end
154
+
155
+ def test_index_with_slim
156
+ get "/test/index_with_slim"
157
+
158
+ assert last_response.ok?
159
+ body = last_response.body
160
+ assert body["Hello"]
161
+ assert body["Hello Twice"]
162
+ end
163
+
164
+ def test_index_with_haml
165
+ get "/test/index_with_haml"
166
+
167
+ assert last_response.ok?
168
+ body = last_response.body
169
+ assert body["Hello"]
170
+ assert body["Hello Twice"]
171
+ end
172
+
173
+ def test_sub_app
174
+ get "/sub-app"
175
+
176
+ assert last_response.ok?
177
+ body = last_response.body
178
+ assert body["sub-app"]
179
+ end
180
+
181
+ def test_sub_app2
182
+ get "/sub-app2"
183
+
184
+ assert last_response.ok?
185
+ body = last_response.body
186
+ assert body["ANOTHER SUB APP"]
187
+ end
188
+
189
+ def test_bad_request
190
+ get "/something-bad"
191
+ assert last_response.status == 404
192
+ end
193
+
194
+ def test_with_variables_erb
195
+ get 'with_variables_erb'
196
+
197
+ assert last_response.ok?
198
+ body = last_response.body
199
+ assert body["Jack"]
200
+ assert body["HI!"]
201
+ end
202
+
203
+ def test_with_variables_haml
204
+ get 'with_variables_haml'
205
+
206
+ assert last_response.ok?
207
+ body = last_response.body
208
+ assert body["Jack"]
209
+ assert body["HI!"]
210
+ end
211
+
212
+ def test_with_variables_slim
213
+ get 'with_variables_slim'
214
+
215
+ assert last_response.ok?
216
+ body = last_response.body
217
+
218
+ assert body["Jack"]
219
+ assert body["HI!"]
220
+ end
221
+
222
+
223
+ def test_change_response_status_code
224
+ get 'change_response_status_code'
225
+
226
+ assert last_response.status == 201
227
+ end
228
+
229
+ def test_post_request
230
+ post 'testing_post'
231
+
232
+ assert last_response.ok?
233
+ end
234
+
235
+ def test_getting_a_post_request_should_return_bad_request
236
+ get 'testing_post'
237
+
238
+ assert last_response.status == 404
239
+ end
240
+
241
+ def test_cookie_setting
242
+ get 'cookie_setting'
243
+ assert last_response.headers['Set-Cookie'] == 'user_id=1'
244
+ end
245
+
246
+ def test_cookie_deletion
247
+ get 'cookie_deletion'
248
+ assert last_response.headers['Set-Cookie'] =~ /user_id=; max-age=0;/
249
+ end
250
+
251
+ def test_redirecting_path
252
+ get 'redirecting_path'
253
+ assert last_response.status == 302
254
+ assert last_response['Location'] == "test/index"
255
+ end
256
+
257
+ def test_with_current_user
258
+ get 'with_current_user'
259
+ assert last_response.ok?
260
+ assert last_response.body['Damir']
261
+ end
262
+
263
+ def test_with_current_user_slim
264
+ get 'with_current_user_slim'
265
+ assert last_response.ok?
266
+ assert last_response.body['Damir']
267
+ end
268
+
269
+ def test_with_current_user_haml
270
+ get 'with_current_user_haml'
271
+ assert last_response.ok?
272
+ assert last_response.body['Damir']
273
+ end
274
+
275
+ def test_json_response
276
+ get 'json_response'
277
+ assert last_response.ok?
278
+ body = last_response.body
279
+ body_hash = JSON.parse(body)
280
+ assert_equal "Jack", body_hash['username']
281
+ assert_equal "M", body_hash['sex']
282
+ end
283
+
284
+ end
285
+
286
+
287
+ class NoRouterTestApp < Minitest::Test
288
+ include Rack::Test::Methods
289
+
290
+ def app
291
+ app = TestApp.new
292
+ end
293
+
294
+ def test_no_routes
295
+ assert_raises Noodles::Http::NoRouterError do
296
+ get '/'
297
+ end
298
+ end
299
+ end