renee-core 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +242 -0
- data/Rakefile +8 -0
- data/ideal.rb +49 -0
- data/lib/renee-core/application/rack_interaction.rb +39 -0
- data/lib/renee-core/application/request_context.rb +22 -0
- data/lib/renee-core/application/responding.rb +122 -0
- data/lib/renee-core/application/routing.rb +245 -0
- data/lib/renee-core/application.rb +28 -0
- data/lib/renee-core/response.rb +78 -0
- data/lib/renee-core/settings.rb +34 -0
- data/lib/renee-core/url_generation.rb +109 -0
- data/lib/renee-core/version.rb +6 -0
- data/lib/renee-core.rb +64 -0
- data/renee-core.gemspec +26 -0
- data/test/responding_test.rb +128 -0
- data/test/routing_test.rb +422 -0
- data/test/test_helper.rb +4 -0
- data/test/url_generation_test.rb +66 -0
- metadata +169 -0
@@ -0,0 +1,245 @@
|
|
1
|
+
class Renee
|
2
|
+
class Core
|
3
|
+
class Application
|
4
|
+
# Collection of useful methods for routing within a {Renee::Core} app.
|
5
|
+
module Routing
|
6
|
+
# Match a path to respond to.
|
7
|
+
#
|
8
|
+
# @param [String] p
|
9
|
+
# path to match.
|
10
|
+
# @param [Proc] blk
|
11
|
+
# block to yield
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# path('/') { ... } #=> '/'
|
15
|
+
# path('test') { ... } #=> '/test'
|
16
|
+
#
|
17
|
+
# path 'foo' do
|
18
|
+
# path('bar') { ... } #=> '/foo/bar'
|
19
|
+
# end
|
20
|
+
#
|
21
|
+
# @api public
|
22
|
+
def path(p, &blk)
|
23
|
+
p = p[1, p.size] if p[0] == ?/
|
24
|
+
part(/^\/#{Regexp.quote(p)}(\/?$)?/, &blk)
|
25
|
+
end
|
26
|
+
|
27
|
+
# Like #path, but requires the entire path to be consumed.
|
28
|
+
# @see #path
|
29
|
+
def whole_path(p, &blk)
|
30
|
+
path(p) { complete(&blk) }
|
31
|
+
end
|
32
|
+
|
33
|
+
# Like #path, but doesn't automatically match trailing-slashes.
|
34
|
+
# @see #path
|
35
|
+
def exact_path(p, &blk)
|
36
|
+
p = p[1, part.size] if p[0] == ?/
|
37
|
+
part(/^\/#{Regexp.quote(p)}/, &blk)
|
38
|
+
end
|
39
|
+
|
40
|
+
# Like #path, doesn't look for leading slashes.
|
41
|
+
def part(p)
|
42
|
+
p = /\/?#{Regexp.quote(p)}/ if p.is_a?(String)
|
43
|
+
if match = env['PATH_INFO'][p]
|
44
|
+
with_path_part(match) { yield }
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
# Match parts off the path as variables.
|
49
|
+
#
|
50
|
+
# @example
|
51
|
+
# path '/' do
|
52
|
+
# variable { |id| halt [200, {}, id }
|
53
|
+
# end
|
54
|
+
# GET /hey #=> [200, {}, 'hey']
|
55
|
+
#
|
56
|
+
# path '/test' do
|
57
|
+
# variable { |foo, bar| halt [200, {}, "#{foo}-#{bar}"] }
|
58
|
+
# end
|
59
|
+
# GET /test/hey/there #=> [200, {}, 'hey-there']
|
60
|
+
#
|
61
|
+
# @api public
|
62
|
+
def variable(*args, &blk)
|
63
|
+
args << {} unless args.last.is_a?(Hash)
|
64
|
+
args.last[:prepend] = '/'
|
65
|
+
partial_variable(*args, &blk)
|
66
|
+
end
|
67
|
+
alias_method :var, :variable
|
68
|
+
|
69
|
+
# Match parts off the path as variables without a leading slash.
|
70
|
+
# @see #variable
|
71
|
+
# @api public
|
72
|
+
def partial_variable(*args, &blk)
|
73
|
+
opts = args.last.is_a?(Hash) ? args.pop : nil
|
74
|
+
type = args.first || opts && opts[:type]
|
75
|
+
prepend = opts && opts[:prepend] || ''
|
76
|
+
if type == Integer
|
77
|
+
complex_variable(/#{Regexp.quote(prepend)}(\d+)/, proc{|v| Integer(v)}, &blk)
|
78
|
+
else case type
|
79
|
+
when nil
|
80
|
+
complex_variable(/#{Regexp.quote(prepend)}([^\/]+)/, &blk)
|
81
|
+
when Regexp
|
82
|
+
complex_variable(/#{Regexp.quote(prepend)}(#{type.to_s})/, &blk)
|
83
|
+
else
|
84
|
+
raise "Unexpected variable type #{type.inspect}"
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
88
|
+
alias_method :part_var, :partial_variable
|
89
|
+
|
90
|
+
# Match an extension.
|
91
|
+
#
|
92
|
+
# @example
|
93
|
+
# extension('html') { |path| halt [200, {}, path] }
|
94
|
+
#
|
95
|
+
# @api public
|
96
|
+
def extension(ext)
|
97
|
+
if detected_extension && match = detected_extension[ext]
|
98
|
+
if match == detected_extension
|
99
|
+
(ext_match = env['PATH_INFO'][/\/?\.#{match}/]) ?
|
100
|
+
with_path_part(ext_match) { yield } : yield
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
alias_method :ext, :extension
|
105
|
+
|
106
|
+
# Match no extension.
|
107
|
+
#
|
108
|
+
# @example
|
109
|
+
# no_extension { |path| halt [200, {}, path] }
|
110
|
+
#
|
111
|
+
# @api public
|
112
|
+
def no_extension
|
113
|
+
yield if detected_extension.nil?
|
114
|
+
end
|
115
|
+
|
116
|
+
# Match any remaining path.
|
117
|
+
#
|
118
|
+
# @example
|
119
|
+
# remainder { |path| halt [200, {}, path] }
|
120
|
+
#
|
121
|
+
# @api public
|
122
|
+
def remainder
|
123
|
+
with_path_part(env['PATH_INFO']) { |var| yield var }
|
124
|
+
end
|
125
|
+
alias_method :catchall, :remainder
|
126
|
+
|
127
|
+
# Respond to a GET request and yield the block.
|
128
|
+
#
|
129
|
+
# @example
|
130
|
+
# get { halt [200, {}, "hello world"] }
|
131
|
+
#
|
132
|
+
# @api public
|
133
|
+
def get(path = nil)
|
134
|
+
request_method('GET', path) { yield }
|
135
|
+
end
|
136
|
+
|
137
|
+
# Respond to a POST request and yield the block.
|
138
|
+
#
|
139
|
+
# @example
|
140
|
+
# post { halt [200, {}, "hello world"] }
|
141
|
+
#
|
142
|
+
# @api public
|
143
|
+
def post(path = nil)
|
144
|
+
request_method('POST', path) { yield }
|
145
|
+
end
|
146
|
+
|
147
|
+
# Respond to a PUT request and yield the block.
|
148
|
+
#
|
149
|
+
# @example
|
150
|
+
# put { halt [200, {}, "hello world"] }
|
151
|
+
#
|
152
|
+
# @api public
|
153
|
+
def put(path = nil)
|
154
|
+
request_method('PUT', path) { yield }
|
155
|
+
end
|
156
|
+
|
157
|
+
# Respond to a DELETE request and yield the block.
|
158
|
+
#
|
159
|
+
# @example
|
160
|
+
# delete { halt [200, {}, "hello world"] }
|
161
|
+
#
|
162
|
+
# @api public
|
163
|
+
def delete(path = nil)
|
164
|
+
request_method('DELETE', path) { yield }
|
165
|
+
end
|
166
|
+
|
167
|
+
# Match only when the path has been completely consumed.
|
168
|
+
#
|
169
|
+
# @example
|
170
|
+
# delete { halt [200, {}, "hello world"] }
|
171
|
+
#
|
172
|
+
# @api public
|
173
|
+
def complete
|
174
|
+
with_path_part(env['PATH_INFO']) { yield } if env['PATH_INFO'] == '' || is_index_request
|
175
|
+
end
|
176
|
+
|
177
|
+
# Match variables within the query string.
|
178
|
+
#
|
179
|
+
# @param [Array, Hash] q
|
180
|
+
# Either an array or hash of things to match query string variables. If given
|
181
|
+
# an array, if you pass the values for each key as parameters to the block given.
|
182
|
+
# If given a hash, then every value must be able to #=== match each value in the query
|
183
|
+
# parameters for each key in the hash.
|
184
|
+
#
|
185
|
+
# @example
|
186
|
+
# query(:key => 'value') { halt [200, {}, "hello world"] }
|
187
|
+
#
|
188
|
+
# @example
|
189
|
+
# query(:key) { |val| halt [200, {}, "key is #{val}"] }
|
190
|
+
#
|
191
|
+
# @api public
|
192
|
+
def query(q, &blk)
|
193
|
+
case q
|
194
|
+
when Hash then q.any? {|k,v| !(v === request[k.to_s]) } ? return : yield
|
195
|
+
when Array then yield *q.map{|qk| request[qk.to_s] or return }
|
196
|
+
else query([q], &blk)
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
# Yield block if the query string matches.
|
201
|
+
#
|
202
|
+
# @param [String] qs
|
203
|
+
# The query string to match.
|
204
|
+
#
|
205
|
+
# @example
|
206
|
+
# path 'test' do
|
207
|
+
# query_string 'foo=bar' do
|
208
|
+
# halt [200, {}, 'matched']
|
209
|
+
# end
|
210
|
+
# end
|
211
|
+
# GET /test?foo=bar #=> 'matched'
|
212
|
+
#
|
213
|
+
# @api public
|
214
|
+
def query_string(qs)
|
215
|
+
yield if qs === env['QUERY_STRING']
|
216
|
+
end
|
217
|
+
|
218
|
+
private
|
219
|
+
def complex_variable(matcher = nil, transformer = nil, &blk)
|
220
|
+
warn "variable currently isn't taking any parameters" unless blk.arity > 0
|
221
|
+
if var_value = /^#{(matcher ? matcher.to_s : '\/([^\/]+)') * blk.arity}/.match(env['PATH_INFO'])
|
222
|
+
vars = var_value.to_a
|
223
|
+
with_path_part(vars.shift) { blk.call *vars.map{|v| transformer ? transformer[v[0, v.size]] : v[0, v.size]} }
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
def with_path_part(part)
|
228
|
+
old_path_info = env['PATH_INFO']
|
229
|
+
old_script_name = env['SCRIPT_NAME']
|
230
|
+
old_path_info[part.size, old_path_info.size - part.size]
|
231
|
+
script_part, remaining_part = old_path_info[0, part.size], old_path_info[part.size, old_path_info.size]
|
232
|
+
env['SCRIPT_NAME'] += script_part
|
233
|
+
env['PATH_INFO'] = remaining_part
|
234
|
+
yield script_part
|
235
|
+
env['PATH_INFO'] = old_path_info
|
236
|
+
env['SCRIPT_NAME'] = old_script_name
|
237
|
+
end
|
238
|
+
|
239
|
+
def request_method(method, path = nil)
|
240
|
+
path ? whole_path(path) { yield } : complete { yield } if env['REQUEST_METHOD'] == method
|
241
|
+
end
|
242
|
+
end
|
243
|
+
end
|
244
|
+
end
|
245
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require File.expand_path(File.dirname(__FILE__) + "/application/request_context")
|
2
|
+
require File.expand_path(File.dirname(__FILE__) + "/application/routing")
|
3
|
+
require File.expand_path(File.dirname(__FILE__) + "/application/responding")
|
4
|
+
require File.expand_path(File.dirname(__FILE__) + "/application/rack_interaction")
|
5
|
+
|
6
|
+
class Renee
|
7
|
+
class Core
|
8
|
+
# This is the main class used to do the respond to requests. {Routing} provides route helpers.
|
9
|
+
# {RequestContext} adds the RequestContext#call method to respond to Rack applications.
|
10
|
+
# {Responding} defines the method Responding#halt which stops processing within a {Renee::Application}.
|
11
|
+
# It also has methods to interpret arguments to #halt and redirection response helpers.
|
12
|
+
# {RackInteraction} adds methods for interacting with Rack.
|
13
|
+
class Application
|
14
|
+
include RequestContext
|
15
|
+
include Routing
|
16
|
+
include Responding
|
17
|
+
include RackInteraction
|
18
|
+
|
19
|
+
attr_reader :application_block, :settings
|
20
|
+
|
21
|
+
# @param [Proc] application_block The block that will be #instance_eval'd on each invocation to #call
|
22
|
+
def initialize(settings, &application_block)
|
23
|
+
@settings = settings
|
24
|
+
@application_block = application_block
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,78 @@
|
|
1
|
+
class Renee
|
2
|
+
class Core
|
3
|
+
# The response object for a Renee request. Inherits from the `Rack#Response` object.
|
4
|
+
class Response < Rack::Response
|
5
|
+
# Augment body to allow strings.
|
6
|
+
#
|
7
|
+
# @param [String] The contents for the response.
|
8
|
+
#
|
9
|
+
# @example
|
10
|
+
# res.body = "Hello"
|
11
|
+
#
|
12
|
+
# @api semipublic
|
13
|
+
def body=(value)
|
14
|
+
value = value.body while Rack::Response === value
|
15
|
+
@body = String === value ? [value.to_str] : value
|
16
|
+
end
|
17
|
+
|
18
|
+
# Alias status and body methods to allow redefinition
|
19
|
+
alias :status_attr :status
|
20
|
+
alias :status_attr= :status=
|
21
|
+
alias :body_attr :body
|
22
|
+
alias :body_attr= :body=
|
23
|
+
|
24
|
+
# Get or set the status of the response.
|
25
|
+
#
|
26
|
+
# @param [String] val The status code to return.
|
27
|
+
#
|
28
|
+
# @example
|
29
|
+
# res.status 400
|
30
|
+
# res.status => 400
|
31
|
+
#
|
32
|
+
# @api public
|
33
|
+
def status(val=nil)
|
34
|
+
val ? self.status_attr = val : self.status_attr
|
35
|
+
end
|
36
|
+
|
37
|
+
# Get or set the body of the response.
|
38
|
+
#
|
39
|
+
# @param [String] val The contents to return.
|
40
|
+
#
|
41
|
+
# @example
|
42
|
+
# res.body "hello"
|
43
|
+
# res.body => "hello"
|
44
|
+
#
|
45
|
+
# @api public
|
46
|
+
def body(val=nil)
|
47
|
+
val ? self.body_attr = val : self.body_attr
|
48
|
+
end
|
49
|
+
|
50
|
+
# Get or set the headers of the response.
|
51
|
+
#
|
52
|
+
# @param [Hash] attrs The contents to return.
|
53
|
+
#
|
54
|
+
# @example
|
55
|
+
# res.headers :foo => "bar"
|
56
|
+
# res.headers => { :foo => "bar" }
|
57
|
+
#
|
58
|
+
# @api public
|
59
|
+
def headers(attrs={})
|
60
|
+
attrs ? attrs.each { |k, v| self[k.to_s] = v } : self.header
|
61
|
+
end
|
62
|
+
|
63
|
+
# Finishs the response based on the accumulated options.
|
64
|
+
# Calculates the size of the body content length and removes headers for 1xx status codes.
|
65
|
+
def finish
|
66
|
+
if status.to_i / 100 == 1
|
67
|
+
headers.delete "Content-Length"
|
68
|
+
headers.delete "Content-Type"
|
69
|
+
elsif Array === body and not [204, 304].include?(status.to_i)
|
70
|
+
headers["Content-Length"] = body.inject(0) { |l, p| l + Rack::Utils.bytesize(p) }.to_s
|
71
|
+
end
|
72
|
+
|
73
|
+
status, headers, result = super
|
74
|
+
[status, headers, result]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,34 @@
|
|
1
|
+
class Renee
|
2
|
+
class Core
|
3
|
+
##
|
4
|
+
# Stores configuration settings for a particular Renee application.
|
5
|
+
# Powers the Renee setup block which is instance eval'ed into this object.
|
6
|
+
#
|
7
|
+
# @example
|
8
|
+
# Renee::Core.new { ... }.setup { views_path "./views" }
|
9
|
+
#
|
10
|
+
class Settings
|
11
|
+
attr_reader :includes
|
12
|
+
def initialize
|
13
|
+
@includes = []
|
14
|
+
end
|
15
|
+
|
16
|
+
# Get or sets the views_path for an application.
|
17
|
+
#
|
18
|
+
# @param [String] path The path to the view files.
|
19
|
+
#
|
20
|
+
# @example
|
21
|
+
# views_path("./views") => nil
|
22
|
+
# views_path => "./views"
|
23
|
+
#
|
24
|
+
# @api public
|
25
|
+
def views_path(path = nil)
|
26
|
+
path ? @views_path = path : @views_path
|
27
|
+
end
|
28
|
+
|
29
|
+
def include(mod)
|
30
|
+
includes << mod
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,109 @@
|
|
1
|
+
require 'uri'
|
2
|
+
|
3
|
+
class Renee
|
4
|
+
class Core
|
5
|
+
# URL generator for creating paths and URLs within your application.
|
6
|
+
module URLGeneration
|
7
|
+
|
8
|
+
# Registers new paths for generation.
|
9
|
+
# @param [Symbol] name The name of the path
|
10
|
+
# @param [String] pattern The pattern used for generation.
|
11
|
+
# @param [Hash, nil] defaults Any default values used for generation.
|
12
|
+
#
|
13
|
+
# @example
|
14
|
+
# renee.register(:path, "/my/:var/path")
|
15
|
+
# renee.path(:path, 123) # => "/my/123/path"
|
16
|
+
# renee.path(:path, :var => 'hey you') # => "/my/hey%20you/path"
|
17
|
+
def register(name, pattern, defaults = nil)
|
18
|
+
url_generators[name] = Generator.new("#{@generation_prefix}#{pattern}", defaults_for_generation(defaults))
|
19
|
+
end
|
20
|
+
|
21
|
+
# Allows the creation of generation contexts.
|
22
|
+
# @param [String] prefix The prefix to add to subsequent calls to #register.
|
23
|
+
# @param [Hash, nil] defaults The defaults to add to subsequent calls to #register.
|
24
|
+
# @see #register
|
25
|
+
#
|
26
|
+
# @example
|
27
|
+
# renee.prefix("/prefix") {
|
28
|
+
# renee.register(:prefix_path, "/path") # would register /prefix/path
|
29
|
+
# }
|
30
|
+
def prefix(prefix, defaults = nil, &blk)
|
31
|
+
generator = self
|
32
|
+
subgenerator = Class.new {
|
33
|
+
include URLGeneration
|
34
|
+
define_method(:url_generators) { generator.send(:url_generators) }
|
35
|
+
}.new
|
36
|
+
subgenerator.instance_variable_set(:@generation_prefix, "#{@generation_prefix}#{prefix}")
|
37
|
+
subgenerator.instance_variable_set(:@generation_defaults, defaults_for_generation(defaults))
|
38
|
+
if block_given?
|
39
|
+
old_prefix, old_defaults = @generation_prefix, @generation_defaults
|
40
|
+
@generation_prefix, @generation_defaults = "#{@generation_prefix}#{prefix}", defaults_for_generation(defaults)
|
41
|
+
subgenerator.instance_eval(&blk)
|
42
|
+
@generation_prefix, @generation_defaults = old_prefix, old_defaults
|
43
|
+
end
|
44
|
+
subgenerator
|
45
|
+
end
|
46
|
+
|
47
|
+
# Generates a path for a given name.
|
48
|
+
# @param [Symbol] name The name of the path
|
49
|
+
# @param [Object] args The values used to generate the path. Can be named with using :name => "value" or supplied
|
50
|
+
# in the order for which the variables were decalared in #register.
|
51
|
+
#
|
52
|
+
# @see #register
|
53
|
+
def path(name, *args)
|
54
|
+
generator = url_generators[name]
|
55
|
+
generator ? generator.path(*args) : raise("Generator for #{name} doesn't exist")
|
56
|
+
end
|
57
|
+
|
58
|
+
# Generates a url for a given name.
|
59
|
+
# @param (see #path)
|
60
|
+
# @see #path
|
61
|
+
def url(name, *args)
|
62
|
+
generator = url_generators[name]
|
63
|
+
generator ? generator.url(*args) : raise("Generator for #{name} doesn't exist")
|
64
|
+
end
|
65
|
+
|
66
|
+
private
|
67
|
+
def url_generators
|
68
|
+
@url_generators ||= {}
|
69
|
+
end
|
70
|
+
|
71
|
+
def defaults_for_generation(defaults)
|
72
|
+
@generation_defaults && defaults ? @generation_defaults.merge(defaults) : (defaults || @generation_defaults)
|
73
|
+
end
|
74
|
+
|
75
|
+
# Manages generating paths and urls for a given name.
|
76
|
+
# @private
|
77
|
+
class Generator
|
78
|
+
attr_reader :defaults
|
79
|
+
|
80
|
+
def initialize(template, defaults = nil)
|
81
|
+
@defaults = defaults
|
82
|
+
parsed_template = URI.parse(template)
|
83
|
+
@host = parsed_template.host
|
84
|
+
@template = parsed_template.path
|
85
|
+
@scheme = parsed_template.scheme
|
86
|
+
port = parsed_template.port
|
87
|
+
if !port.nil? and (@scheme.nil? or @scheme == "http" && port != '80' or @scheme == "https" && port != '443')
|
88
|
+
@port_part = ":#{port}"
|
89
|
+
end
|
90
|
+
end
|
91
|
+
|
92
|
+
def path(*args)
|
93
|
+
opts = args.last.is_a?(Hash) ? args.pop : nil
|
94
|
+
opts = opts ? defaults.merge(opts) : defaults.dup if defaults
|
95
|
+
path = @template.gsub(/:([a-zA-Z0-9_]+)/) { |name|
|
96
|
+
name = name[1, name.size - 1].to_sym
|
97
|
+
(opts && opts.delete(name)) || (defaults && defaults[name]) || args.shift || raise("variable #{name.inspect} not found")
|
98
|
+
}
|
99
|
+
URI.encode(opts.nil? || opts.empty? ? path : "#{path}?#{Rack::Utils.build_query(opts)}")
|
100
|
+
end
|
101
|
+
|
102
|
+
def url(*args)
|
103
|
+
raise "This URL cannot be generated as no host has been defined." if @host.nil?
|
104
|
+
"#{@scheme}://#{@host}#{@port_part}#{path(*args)}"
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
data/lib/renee-core.rb
ADDED
@@ -0,0 +1,64 @@
|
|
1
|
+
require 'rack'
|
2
|
+
require 'renee-core/version'
|
3
|
+
require 'renee-core/settings'
|
4
|
+
require 'renee-core/response'
|
5
|
+
require 'renee-core/application'
|
6
|
+
require 'renee-core/url_generation'
|
7
|
+
|
8
|
+
# Renee top-level constant
|
9
|
+
class Renee
|
10
|
+
# The top-level class for creating core application.
|
11
|
+
# For convience you can also used a method named #Renee
|
12
|
+
# for decalaring new instances.
|
13
|
+
#
|
14
|
+
# @example
|
15
|
+
# Renee::Core.new { path('/hello') { halt :ok } }
|
16
|
+
#
|
17
|
+
class Core
|
18
|
+
include URLGeneration
|
19
|
+
|
20
|
+
attr_reader :application_block, :settings
|
21
|
+
|
22
|
+
# @param [Proc] application_block The block of code that will be executed on each invocation of call #call.
|
23
|
+
# Each time #call is called, a new instance of {Renee::Core::Application} will
|
24
|
+
# be created. The block given will be #instance_eval 'd within
|
25
|
+
# the context of that new instance.
|
26
|
+
#
|
27
|
+
def initialize(&application_block)
|
28
|
+
@application_block = application_block
|
29
|
+
@settings = Settings.new
|
30
|
+
end
|
31
|
+
|
32
|
+
# This is a rack-compliant `Rack#call`.
|
33
|
+
#
|
34
|
+
# @param [Hash] env The environment hash.
|
35
|
+
#
|
36
|
+
# @return [Array] A rack compliant return.
|
37
|
+
#
|
38
|
+
# @see http://rack.rubyforge.org/doc/SPEC.html
|
39
|
+
#
|
40
|
+
def call(env)
|
41
|
+
Application.new(settings, &application_block).call(env)
|
42
|
+
end
|
43
|
+
alias_method :[], :call
|
44
|
+
|
45
|
+
##
|
46
|
+
# Configure settings for your Renee application. Accepts a settings file path
|
47
|
+
# or a block containing the configuration settings.
|
48
|
+
#
|
49
|
+
# @example
|
50
|
+
# Renee::Core.new { ... }.setup { views_path "./views" }
|
51
|
+
#
|
52
|
+
# @api public
|
53
|
+
def setup(path = nil, &blk)
|
54
|
+
raise "Must be either path or blk to configure settings" if path && blk
|
55
|
+
case path
|
56
|
+
when nil then settings.instance_eval(&blk)
|
57
|
+
when Settings then @settings = path
|
58
|
+
when String then File.exist?(path) ? settings.instance_eval(File.read(path), path, 1) : raise("The settings file #{path} does not exist")
|
59
|
+
else raise "Could not setup with #{path.inspect}"
|
60
|
+
end
|
61
|
+
self
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
data/renee-core.gemspec
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "renee-core/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "renee-core"
|
7
|
+
s.version = Renee::Core::VERSION
|
8
|
+
s.authors = ["Josh Hull", "Nathan Esquenazi", "Arthur Chiu"]
|
9
|
+
s.email = ["joshbuddy@gmail.com", "nesquena@gmail.com", "mr.arthur.chiu@gmail.com"]
|
10
|
+
s.homepage = ""
|
11
|
+
s.summary = %q{The super-friendly rack helpers.}
|
12
|
+
s.description = %q{The super-friendly rack helpers.}
|
13
|
+
|
14
|
+
s.rubyforge_project = "renee"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
s.add_runtime_dependency 'rack', "~> 1.3.0"
|
22
|
+
s.add_development_dependency 'minitest', "~> 2.6.1"
|
23
|
+
s.add_development_dependency 'bundler', "~> 1.0.10"
|
24
|
+
s.add_development_dependency "rack-test", ">= 0.5.0"
|
25
|
+
s.add_development_dependency "rake", "0.8.7"
|
26
|
+
end
|