hobbit-contrib 0.0.1 → 0.1.0

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 099f376fda08a626af17438fbf1e3642602ace9c
4
- data.tar.gz: 2eb4379e2612f064b90b7d0b6d9d0d02fc043a28
3
+ metadata.gz: b7f3320b3437d3168749e5581b999a443a48e001
4
+ data.tar.gz: 4cc4a32c36aeb3068cfc17aca524be92ecbee78d
5
5
  SHA512:
6
- metadata.gz: 6d571097bd56bc82f5d2602875df361b7dc00b4ac843482aa178c6ff5e0c24010ffe930eadab8b34ffeed950c7a16b833b436b513c3b55839a9539a758d8dc12
7
- data.tar.gz: a682e80b5c624d83fda243403484dfed7837a3f0e8c834b24941b0033bedec2c0565cfc8a579f7f619c3a8cb9f9213d21a1aeed2b8220be00b934ec0f22fcca3
6
+ metadata.gz: a3464d83f2d94c32c9a32d29afa4a5a7548539d9fa00876ba20b9301b43b306aa4b56f219b4854006fb9f50b96963634a586eedcff26825eeb49e67c9c2b9c39
7
+ data.tar.gz: 0248e6223440165e6f2c0efe3ab91ea95c50c3af3c67496d4061edce43a866c7607a4b86da1008b45cffa9ab8ab76af3139da33ceeb60bf96b0136ba8d5223e1
data/README.md CHANGED
@@ -1,7 +1,4 @@
1
- # Hobbit::Contrib
2
-
3
- [![Build Status](https://travis-ci.org/patriciomacadden/hobbit-contrib.png?branch=master)](https://travis-ci.org/patriciomacadden/hobbit-contrib)
4
- [![Code Climate](https://codeclimate.com/github/patriciomacadden/hobbit-contrib.png)](https://codeclimate.com/github/patriciomacadden/hobbit-contrib)
1
+ # Hobbit::Contrib [![Build Status](https://travis-ci.org/patriciomacadden/hobbit-contrib.png?branch=master)](https://travis-ci.org/patriciomacadden/hobbit-contrib) [![Code Climate](https://codeclimate.com/github/patriciomacadden/hobbit-contrib.png)](https://codeclimate.com/github/patriciomacadden/hobbit-contrib) [![Coverage Status](https://coveralls.io/repos/patriciomacadden/hobbit-contrib/badge.png?branch=master)](https://coveralls.io/r/patriciomacadden/hobbit-contrib) [![Dependency Status](https://gemnasium.com/patriciomacadden/hobbit-contrib.png)](https://gemnasium.com/patriciomacadden/hobbit-contrib) [![Gem Version](https://badge.fury.io/rb/hobbit-contrib.png)](http://badge.fury.io/rb/hobbit-contrib)
5
2
 
6
3
  Contributed Hobbit extensions.
7
4
 
@@ -29,20 +26,98 @@ $ gem install hobbit-contrib
29
26
 
30
27
  ## Usage
31
28
 
32
- Each extension may have its own usage. In general, including (or extending) the
33
- module will be enough.
29
+ Each extension may have its own usage. In general, including the module will be
30
+ enough.
34
31
 
35
32
  ```ruby
36
33
  require 'hobbit'
37
34
  require 'hobbit/contrib'
38
35
 
39
36
  class App < Hobbit::Base
37
+ # include hobbit session extension
38
+ include Hobbit::Session
39
+
40
40
  # define your application
41
41
  end
42
42
  ```
43
43
 
44
44
  ## Available extensions
45
45
 
46
+ ### Hobbit::AssetTag
47
+
48
+ This module allows you to include images, javascripts and stylesheets in a easy
49
+ way. To use this extension just include the module:
50
+
51
+ In `config.ru`:
52
+
53
+ ```ruby
54
+ require 'hobbit'
55
+ require 'hobbit/contrib'
56
+
57
+ class App < Hobbit::Base
58
+ # Put your assets in:
59
+ # * public/images
60
+ # * public/javascripts
61
+ # * public/stylesheets
62
+ use Rack::Static, root: 'public', urls: ['/images', '/javascripts', '/stylesheets']
63
+ include Hobbit::AssetTag
64
+ include Hobbit::EnhancedRender # see below
65
+
66
+ get '/' do
67
+ render 'index', {}, layout: 'layout'
68
+ end
69
+ end
70
+
71
+ run App.new
72
+ ```
73
+
74
+ in `views/layouts/layout.erb`:
75
+
76
+ ```ruby
77
+ <!DOCTYPE html>
78
+ <html>
79
+ <head>
80
+ <title>Hobbit::AssetTag</title>
81
+ <!--
82
+ becomes:
83
+ <script src="http://code.jquery.com/jquery-2.0.0.min.js" type="text/javascript"></script>
84
+ <script src="/javascripts/application.js" type="text/javascript"></script>
85
+ -->
86
+ <%= javascript 'http://code.jquery.com/jquery-2.0.0.min.js', 'application' %>
87
+ <!--
88
+ becomes:
89
+ <link href="/stylesheets/application.css" rel="stylesheet"/>
90
+ -->
91
+ <%= stylesheet 'application' %>
92
+ </head>
93
+ <body>
94
+ <%= yield %>
95
+ </body>
96
+ </html>
97
+ ```
98
+
99
+ and in `views/index.erb`:
100
+
101
+ ```ruby
102
+ <h1>Hobbit::AssetTag</h1>
103
+ <!-- becomes: /images/some-hobbit.png -->
104
+ <img src="<%= image_path 'some-hobbit.png' %>"/>
105
+ ```
106
+
107
+ #### Available methods
108
+
109
+ * `image_path`: Returns the path for a given image.
110
+ * `javascript`: Returns a list of one or more script tags (see the example
111
+ above).
112
+ * `javascript_path`: Returns the path for a given javascript file. If you pass
113
+ an url, it returns the given url. If you pass an arbitrary string, it returns
114
+ `/javascripts/#{url}.js`.
115
+ * `stylesheet`: Returns a list of one or more link tags (see the example
116
+ above).
117
+ * `stylesheet_path`: Returns the path for a given stylesheet file. If you pass
118
+ an url, it returns the given url. If you pass an arbitrary string, it returns
119
+ `/stylesheets/#{url}.css`.
120
+
46
121
  ### Hobbit::EnhancedRender
47
122
 
48
123
  This module extends the functionality of `Hobbit::Render`. To use this extension
@@ -78,6 +153,159 @@ views path, except that the template name will start with an underscore. For
78
153
  instance, if you call `partial 'partial'`, the path will become
79
154
  `views/_partial.erb`
80
155
 
156
+ ### Hobbit::Environment
157
+
158
+ This extension allows you to control the application environment by using the
159
+ provided methods. To use this extension just include the module:
160
+
161
+ ```ruby
162
+ require 'hobbit'
163
+ require 'hobbit/contrib'
164
+
165
+ class App < Hobbit::Base
166
+ include Hobbit::Environment
167
+
168
+ get '/' do
169
+ "currently in #{environment}"
170
+ end
171
+ end
172
+
173
+ run App.new
174
+ ```
175
+
176
+ #### Available methods
177
+
178
+ * `environment`: Returns the current environment. By default is
179
+ `ENV['RACK_ENV']`.
180
+ * `environment=()`: Sets the environment.
181
+ * `development?`: Returns true if the current environment is `:development`.
182
+ * `production?`: Returns true if the current environment is `:production`.
183
+ * `test?`: Returns true if the current environment is `:test`.
184
+
185
+ ### Hobbit::ErrorHandling
186
+
187
+ This extension provides a way of handling errors raised by your application. To
188
+ use this extension just include the module:
189
+
190
+ ```ruby
191
+ require 'hobbit'
192
+ require 'hobbit/contrib'
193
+
194
+ class App < Hobbit::Base
195
+ include Hobbit::ErrorHandling
196
+
197
+ error Exception do |exception|
198
+ exception.message
199
+ end
200
+
201
+ get '/' do
202
+ raise Exception, 'Oops'
203
+ end
204
+ end
205
+
206
+ run App.new
207
+ ```
208
+
209
+ #### Available methods
210
+
211
+ * `errors`: Returns a hash with the exceptions being handled and its
212
+ corresponding handler.
213
+ * `error`: Sets a handler for a given exception.
214
+
215
+ **Note**: If you define more than one handler per exception the last one
216
+ defined will have precedence over the others.
217
+
218
+ ### Hobbit::Filter
219
+
220
+ This extension provides a way of calling blocks before and after the
221
+ evaluation of a route (just like sinatra's filters). To use this extension just
222
+ include the module:
223
+
224
+ ```ruby
225
+ require 'hobbit'
226
+ require 'hobbit/contrib'
227
+
228
+ class App < Hobbit::Base
229
+ include Hobbit::Filter
230
+
231
+ def authenticate_user!
232
+ # ...
233
+ end
234
+
235
+ before do
236
+ authenticate_user!
237
+ end
238
+
239
+ get '/' do
240
+ # ...
241
+ end
242
+ end
243
+
244
+ run App.new
245
+ ```
246
+
247
+ #### Available methods
248
+
249
+ * `after`: Sets an after filter. Optionally, you can specify a route.
250
+ * `before`: Sets a before filter. Optionally, you can specify a route.
251
+
252
+ **Note**: It is recommended to include `Hobbit::Filter` before
253
+ `Hobbit::ErrorHandling` if you want to use both extensions.
254
+
255
+ ### Hobbit::Render
256
+
257
+ This module provides rendering to your hobbit application. To use this
258
+ extension just include the module:
259
+
260
+ ```ruby
261
+ require 'hobbit'
262
+ require 'hobbit/contrib'
263
+
264
+ class App < Hobbit::Base
265
+ include Hobbit::Render
266
+
267
+ get '/' do
268
+ render 'views/index.erb'
269
+ end
270
+
271
+ get '/with-layout' do
272
+ render 'views/layout.erb' do
273
+ render 'views/index.erb'
274
+ end
275
+ end
276
+ end
277
+ ```
278
+
279
+ #### Available methods
280
+
281
+ * `render`: Renders the given template using tilt.
282
+
283
+ ### Hobbit::Session
284
+
285
+ This module provides helper methods for handling user sessions. To use this
286
+ extension just include the module:
287
+
288
+ ```ruby
289
+ require 'hobbit'
290
+ require 'hobbit/contrib'
291
+
292
+ class App < Hobbit::Base
293
+ include Hobbit::Session
294
+
295
+ post '/' do
296
+ session[:name] = 'hobbit'
297
+ end
298
+
299
+ get '/' do
300
+ "Hello #{session[:name]}!"
301
+ end
302
+ end
303
+ ```
304
+
305
+ #### Available methods
306
+
307
+ * `session`: Returns the user's session.
308
+
81
309
  ## Contributing
82
310
 
83
311
  1. Fork it
@@ -18,10 +18,14 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ['lib']
20
20
 
21
- spec.add_dependency 'hobbit'
22
-
23
21
  spec.add_development_dependency 'bundler', '~> 1.3'
22
+ spec.add_development_dependency 'coveralls'
23
+ spec.add_development_dependency 'hobbit'
24
24
  spec.add_development_dependency 'minitest'
25
25
  spec.add_development_dependency 'rack-test'
26
26
  spec.add_development_dependency 'rake'
27
+ spec.add_development_dependency 'tilt'
28
+
29
+ spec.add_runtime_dependency 'hobbit'
30
+ spec.add_runtime_dependency 'tilt'
27
31
  end
@@ -0,0 +1,23 @@
1
+ module Hobbit
2
+ module AssetTag
3
+ def image_path(url)
4
+ url =~ /^https?:\/\// ? url : "/images/#{url}"
5
+ end
6
+
7
+ def javascript(*urls)
8
+ urls.map { |url| "<script src=\"#{javascript_path url}\" type=\"text/javascript\"></script>" }.join
9
+ end
10
+
11
+ def javascript_path(url)
12
+ url =~ /^https?:\/\// ? url : "/javascripts/#{url}.js"
13
+ end
14
+
15
+ def stylesheet(*urls)
16
+ urls.map { |url| "<link href=\"#{stylesheet_path url}\" rel=\"stylesheet\"/>" }.join
17
+ end
18
+
19
+ def stylesheet_path(url)
20
+ url =~ /^http(s)?:\/\// ? url : "/stylesheets/#{url}.css"
21
+ end
22
+ end
23
+ end
@@ -1,5 +1,5 @@
1
1
  module Hobbit
2
2
  module Contrib
3
- VERSION = '0.0.1'
3
+ VERSION = '0.1.0'
4
4
  end
5
5
  end
@@ -1,2 +1,8 @@
1
+ require 'hobbit/asset_tag'
1
2
  require 'hobbit/contrib/version'
2
3
  require 'hobbit/enhanced_render'
4
+ require 'hobbit/environment'
5
+ require 'hobbit/error_handling'
6
+ require 'hobbit/filter'
7
+ require 'hobbit/render'
8
+ require 'hobbit/session'
@@ -27,7 +27,7 @@ module Hobbit
27
27
  end
28
28
 
29
29
  def view_path(template)
30
- "views/#{template}.erb"
30
+ "views/#{template}.#{template_engine}"
31
31
  end
32
32
  end
33
33
  end
@@ -0,0 +1,15 @@
1
+ module Hobbit
2
+ module Environment
3
+ def environment
4
+ self.class.settings[:environment] || ENV['RACK_ENV'].to_sym
5
+ end
6
+
7
+ def environment=(environment)
8
+ self.class.settings[:environment] = environment.to_sym
9
+ end
10
+
11
+ %w(development production test).each do |environment|
12
+ define_method("#{environment}?") { self.class.settings[:environment] == environment.to_sym }
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,25 @@
1
+ module Hobbit
2
+ module ErrorHandling
3
+ module ClassMethods
4
+ def error(exception, &block)
5
+ errors[exception] = block
6
+ end
7
+
8
+ def errors
9
+ @errors ||= Hash.new
10
+ end
11
+ end
12
+
13
+ def _call(env)
14
+ super
15
+ rescue Exception => e
16
+ body = instance_eval { self.class.errors[e.class].call(e) }
17
+ response.body = [body] if self.class.errors.include? e.class
18
+ response.finish
19
+ end
20
+
21
+ def self.included(othermod)
22
+ othermod.extend ClassMethods
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,54 @@
1
+ module Hobbit
2
+ module Filter
3
+ module ClassMethods
4
+ %w(after before).each do |kind|
5
+ define_method(kind) { |path = '', &block| filters[kind.to_sym] << compile_filter!(path, &block) }
6
+ end
7
+
8
+ def filters
9
+ @filters ||= Hash.new { |hash, key| hash[key] = [] }
10
+ end
11
+
12
+ private
13
+
14
+ def compile_filter!(path, &block)
15
+ filter = { block: block, compiled_path: nil, extra_params: [], path: path }
16
+
17
+ compiled_path = path.gsub(/:\w+/) do |match|
18
+ filter[:extra_params] << match.gsub(':', '').to_sym
19
+ '([^/?#]+)'
20
+ end
21
+ filter[:compiled_path] = /^#{compiled_path}$/
22
+
23
+ filter
24
+ end
25
+ end
26
+
27
+ def _call(env)
28
+ @env = env
29
+ @request = self.class.settings[:request_class].new(@env)
30
+ @response = self.class.settings[:response_class].new
31
+ filter!(:before)
32
+ super
33
+ filter!(:after)
34
+ @response.finish
35
+ end
36
+
37
+ def self.included(othermod)
38
+ othermod.extend ClassMethods
39
+ end
40
+
41
+ private
42
+
43
+ def filter!(kind)
44
+ filter = self.class.filters[kind].detect { |f| f[:compiled_path] =~ request.path_info || f[:path] =~ // }
45
+ if filter
46
+ $~.captures.each_with_index do |value, index|
47
+ param = filter[:extra_params][index]
48
+ request.params[param] = value
49
+ end
50
+ instance_eval(&filter[:block])
51
+ end
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,17 @@
1
+ require 'tilt'
2
+
3
+ module Hobbit
4
+ module Render
5
+ def render(template, locals = {}, options = {}, &block)
6
+ cache.fetch(template) do
7
+ Tilt.new(template, options)
8
+ end.render(self, locals, &block)
9
+ end
10
+
11
+ private
12
+
13
+ def cache
14
+ Thread.current[:cache] ||= Tilt::Cache.new
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,7 @@
1
+ module Hobbit
2
+ module Session
3
+ def session
4
+ env['rack.session']
5
+ end
6
+ end
7
+ end
@@ -0,0 +1,84 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hobbit::AssetTag do
4
+ include Hobbit::Contrib::Mock
5
+
6
+ def app
7
+ mock_app do
8
+ include Hobbit::AssetTag
9
+ end
10
+ end
11
+
12
+ describe '#image_path' do
13
+ describe 'when passing an url' do
14
+ it 'must return the url' do
15
+ url = 'http://example.com/image.png'
16
+ app.to_app.image_path(url).must_equal url
17
+ end
18
+ end
19
+
20
+ describe 'when not passing an url' do
21
+ it 'must return a path to an image' do
22
+ app.to_app.image_path('hobbit.png').must_equal '/images/hobbit.png'
23
+ end
24
+ end
25
+ end
26
+
27
+ describe '#javascript' do
28
+ describe 'when passing one string' do
29
+ it 'must return one script tag' do
30
+ app.to_app.javascript('application').scan('script src').size.must_equal 1
31
+ end
32
+ end
33
+
34
+ describe 'when passing more than one string' do
35
+ it 'must return more than one script tag' do
36
+ app.to_app.javascript('application', 'other_script').scan('script src').size.must_equal 2
37
+ end
38
+ end
39
+ end
40
+
41
+ describe '#javascript_path' do
42
+ describe 'when passing an url' do
43
+ it 'must return the url' do
44
+ url = 'http://example.com/app.js'
45
+ app.to_app.javascript_path(url).must_equal url
46
+ end
47
+ end
48
+
49
+ describe 'when not passing an url' do
50
+ it 'must return a path to a javascript file' do
51
+ app.to_app.javascript_path('application').must_equal '/javascripts/application.js'
52
+ end
53
+ end
54
+ end
55
+
56
+ describe '#stylesheet' do
57
+ describe 'when passing one string' do
58
+ it 'must return one link tag' do
59
+ app.to_app.stylesheet('application').scan('link href').size.must_equal 1
60
+ end
61
+ end
62
+
63
+ describe 'when passing more than one string' do
64
+ it 'must return more than one link tag' do
65
+ app.to_app.stylesheet('application', 'other_style').scan('link href').size.must_equal 2
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '#stylesheet_path' do
71
+ describe 'when passing an url' do
72
+ it 'must return the url' do
73
+ url = 'http://example.com/app.css'
74
+ app.to_app.stylesheet_path(url).must_equal url
75
+ end
76
+ end
77
+
78
+ describe 'when not passing an url' do
79
+ it 'must return a path to a stylesheet file' do
80
+ app.to_app.stylesheet_path('application').must_equal '/stylesheets/application.css'
81
+ end
82
+ end
83
+ end
84
+ end
@@ -1,15 +1,40 @@
1
1
  require 'minitest_helper'
2
2
 
3
3
  describe Hobbit::EnhancedRender do
4
+ include Hobbit::Contrib::Mock
4
5
  include Rack::Test::Methods
5
6
 
6
7
  def app
7
- TestEnhancedRenderApp.new
8
+ mock_app do
9
+ include Hobbit::EnhancedRender
10
+
11
+ # we do this because it the layout path is relative to file being run
12
+ def layout_path(template)
13
+ File.expand_path("../fixtures/enhanced_render/#{super}", __FILE__)
14
+ end
15
+
16
+ # we do this because it the view path is relative to file being run
17
+ def view_path(template)
18
+ File.expand_path("../fixtures/enhanced_render/#{super}", __FILE__)
19
+ end
20
+
21
+ get '/' do
22
+ render 'index', {}, layout: 'layout'
23
+ end
24
+
25
+ get '/without-layout' do
26
+ render 'index'
27
+ end
28
+
29
+ get '/partial' do
30
+ partial 'partial'
31
+ end
32
+ end
8
33
  end
9
34
 
10
35
  describe '#layout_path' do
11
36
  it 'must return a path' do
12
- path = File.expand_path('../fixtures/test_enhanced_render_app/views/layouts/layout.erb', __FILE__)
37
+ path = File.expand_path('../fixtures/enhanced_render/views/layouts/layout.erb', __FILE__)
13
38
  app.to_app.layout_path('layout').must_equal path
14
39
  end
15
40
  end
@@ -50,7 +75,7 @@ describe Hobbit::EnhancedRender do
50
75
 
51
76
  describe '#view_path' do
52
77
  it 'must return a path' do
53
- path = File.expand_path('../fixtures/test_enhanced_render_app/views/index.erb', __FILE__)
78
+ path = File.expand_path('../fixtures/enhanced_render/views/index.erb', __FILE__)
54
79
  app.to_app.view_path('index').must_equal path
55
80
  end
56
81
  end
@@ -0,0 +1,65 @@
1
+ require 'minitest_helper'
2
+
3
+ describe Hobbit::Environment do
4
+ include Hobbit::Contrib::Mock
5
+
6
+ let(:app) do
7
+ mock_app do
8
+ include Hobbit::Environment
9
+ end
10
+ end
11
+
12
+ describe '#environment' do
13
+ it 'must return the current environment' do
14
+ app.to_app.environment = :development
15
+ app.to_app.environment.must_equal :development
16
+ end
17
+
18
+ it 'must default to RACK_ENV' do
19
+ app.to_app.environment.must_equal ENV['RACK_ENV'].to_sym
20
+ end
21
+ end
22
+
23
+ describe '#environment=()' do
24
+ it 'must set the environment' do
25
+ app.to_app.environment = :test
26
+ app.to_app.environment.must_equal :test
27
+ end
28
+ end
29
+
30
+ describe '#development?' do
31
+ it 'must return true if self.class.settings[:environment] = :development' do
32
+ app.to_app.environment = :development
33
+ app.to_app.development?.must_equal true
34
+ end
35
+
36
+ it 'must return false if self.class.settings[:environment] != :development' do
37
+ app.to_app.environment = :production
38
+ app.to_app.development?.must_equal false
39
+ end
40
+ end
41
+
42
+ describe '#production?' do
43
+ it 'must return true if self.class.settings[:environment] = :production' do
44
+ app.to_app.environment = :production
45
+ app.to_app.production?.must_equal true
46
+ end
47
+
48
+ it 'must return false if self.class.settings[:environment] != :production' do
49
+ app.to_app.environment = :test
50
+ app.to_app.production?.must_equal false
51
+ end
52
+ end
53
+
54
+ describe '#test?' do
55
+ it 'must return true if self.class.settings[:environment] = :test' do
56
+ app.to_app.environment = :test
57
+ app.to_app.test?.must_equal true
58
+ end
59
+
60
+ it 'must return false if self.class.settings[:environment] != :test' do
61
+ app.to_app.environment = :development
62
+ app.to_app.test?.must_equal false
63
+ end
64
+ end
65
+ end