happy 0.1.0.pre19 → 0.1.0.pre20
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.
- data/example/config.ru +105 -0
- data/example/views/index.erb +7 -0
- data/example/views/layout.erb +3 -0
- data/happy.gemspec +1 -1
- data/lib/happy.rb +1 -16
- data/lib/happy/controller.rb +37 -24
- data/lib/happy/controller/actions.rb +7 -8
- data/lib/happy/controller/cascadable.rb +17 -0
- data/lib/happy/{context → controller}/helpers.rb +1 -1
- data/lib/happy/controller/permissions.rb +17 -0
- data/lib/happy/controller/rackable.rb +8 -6
- data/lib/happy/controller/routing.rb +3 -3
- data/lib/happy/errors.rb +1 -3
- data/lib/happy/extras/resources.rb +4 -6
- data/lib/happy/extras/scriptable.rb +0 -1
- data/lib/happy/files/error.erb +3 -3
- data/lib/happy/response.rb +10 -0
- data/lib/happy/version.rb +1 -1
- data/spec/controller/actions_spec.rb +4 -4
- data/spec/controller/cascadable_spec.rb +43 -0
- data/spec/controller_spec.rb +6 -6
- metadata +32 -26
- data/lib/happy/context.rb +0 -88
- data/lib/happy/extras/permissions.rb +0 -32
data/example/config.ru
ADDED
@@ -0,0 +1,105 @@
|
|
1
|
+
lib_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
2
|
+
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
|
3
|
+
|
4
|
+
require 'happy'
|
5
|
+
require 'cgi'
|
6
|
+
|
7
|
+
class TestApp < Happy::Controller
|
8
|
+
def examples; @examples ||= {}; end
|
9
|
+
|
10
|
+
def example(name, path_name = nil, &blk)
|
11
|
+
path_name ||= name.parameterize
|
12
|
+
examples[name] = path_name
|
13
|
+
|
14
|
+
# Create a path containing the example's code block
|
15
|
+
path(path_name, &blk)
|
16
|
+
end
|
17
|
+
|
18
|
+
def route
|
19
|
+
example 'Returning just a string' do
|
20
|
+
"I'm just a string!"
|
21
|
+
end
|
22
|
+
|
23
|
+
example 'Explicit responses' do
|
24
|
+
serve! "I was served through #serve!"
|
25
|
+
serve! "I'm not being served, since the above call to #serve! halted processing."
|
26
|
+
end
|
27
|
+
|
28
|
+
example 'Path parameters' do
|
29
|
+
path 'hello' do
|
30
|
+
path :name do
|
31
|
+
"Hello, #{params['name']}!"
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
"Try #{link_to 'this', current_url('hello', 'hendrik')}!"
|
36
|
+
end
|
37
|
+
|
38
|
+
example 'Inline path parameters' do
|
39
|
+
path 'hello-:name' do
|
40
|
+
"Hello, #{params['name']}!"
|
41
|
+
end
|
42
|
+
|
43
|
+
"Try #{link_to 'this', current_url('hello-hendrik')}!"
|
44
|
+
end
|
45
|
+
|
46
|
+
example 'Permissions' do
|
47
|
+
# set up permissions ;-)
|
48
|
+
can.dance!
|
49
|
+
|
50
|
+
path 'dance' do
|
51
|
+
if can.dance?
|
52
|
+
"You can dance."
|
53
|
+
else
|
54
|
+
"You can not dance."
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
"Can you #{link_to 'dance', current_url('dance')}?"
|
59
|
+
end
|
60
|
+
|
61
|
+
example 'Layouts' do
|
62
|
+
path 'with-layout' do
|
63
|
+
layout 'layout.erb'
|
64
|
+
|
65
|
+
path 'changed-my-mind' do
|
66
|
+
layout false
|
67
|
+
"This should render without a layout."
|
68
|
+
end
|
69
|
+
|
70
|
+
"This should render with a layout."
|
71
|
+
end
|
72
|
+
|
73
|
+
"This should render without a layout."
|
74
|
+
end
|
75
|
+
|
76
|
+
example 'Invoking other controllers' do
|
77
|
+
# creata new controller on the fly
|
78
|
+
c = Happy.route do
|
79
|
+
"Controller wrapping works, yay!"
|
80
|
+
end
|
81
|
+
|
82
|
+
# pass control over the request to that controller
|
83
|
+
run c
|
84
|
+
end
|
85
|
+
|
86
|
+
example 'Invoking Rack apps' do
|
87
|
+
# define a Rack app
|
88
|
+
rackapp = lambda { |env| [200, {'Content-type' => 'text/html'}, ["It works!"]] }
|
89
|
+
|
90
|
+
# pass control over the request to the Rack application
|
91
|
+
run rackapp
|
92
|
+
end
|
93
|
+
|
94
|
+
example 'Errors' do
|
95
|
+
null = Happy::Controller.new
|
96
|
+
|
97
|
+
# Trigger an error. This should display a nice error page.
|
98
|
+
null.foobar
|
99
|
+
end
|
100
|
+
|
101
|
+
render 'index.erb'
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
run TestApp
|
data/happy.gemspec
CHANGED
@@ -17,7 +17,7 @@ Gem::Specification.new do |gem|
|
|
17
17
|
|
18
18
|
gem.add_dependency 'activesupport', '~> 3.1'
|
19
19
|
gem.add_dependency 'rack', '~> 1.4'
|
20
|
-
gem.add_dependency 'happy-helpers', '~> 0.1.0.
|
20
|
+
gem.add_dependency 'happy-helpers', '~> 0.1.0.pre11'
|
21
21
|
gem.add_dependency 'allowance', '>= 0.1.1'
|
22
22
|
|
23
23
|
gem.add_dependency 'happy-cli', '>= 0.1.0.pre1'
|
data/lib/happy.rb
CHANGED
@@ -1,7 +1,6 @@
|
|
1
1
|
require 'rack'
|
2
2
|
require 'happy/version'
|
3
3
|
require 'happy/errors'
|
4
|
-
require 'happy/context'
|
5
4
|
require 'happy/controller'
|
6
5
|
|
7
6
|
module Happy
|
@@ -13,22 +12,8 @@ module Happy
|
|
13
12
|
# its routing block.
|
14
13
|
#
|
15
14
|
def self.route(&blk)
|
16
|
-
|
15
|
+
Class.new(Happy::Controller).tap do |klass|
|
17
16
|
klass.send(:define_method, :route, &blk)
|
18
17
|
end
|
19
18
|
end
|
20
|
-
|
21
|
-
# Run the provided block against Happy::Context. Use this to add new
|
22
|
-
# methods to the request context class.
|
23
|
-
#
|
24
|
-
def self.context(&blk)
|
25
|
-
Context.class_exec(&blk)
|
26
|
-
end
|
27
|
-
|
28
|
-
def self.call(env)
|
29
|
-
@last_controller_class_created.try(:call, env) or raise "Please use Happy.route to define some routes."
|
30
|
-
end
|
31
19
|
end
|
32
|
-
|
33
|
-
__END__
|
34
|
-
yooooooo!
|
data/lib/happy/controller.rb
CHANGED
@@ -1,7 +1,13 @@
|
|
1
|
+
require 'happy/request'
|
2
|
+
require 'happy/response'
|
3
|
+
|
4
|
+
require 'happy/controller/helpers'
|
1
5
|
require 'happy/controller/routing'
|
2
6
|
require 'happy/controller/actions'
|
3
7
|
require 'happy/controller/rackable'
|
4
8
|
require 'happy/controller/configurable'
|
9
|
+
require 'happy/controller/cascadable'
|
10
|
+
require 'happy/controller/permissions'
|
5
11
|
|
6
12
|
module Happy
|
7
13
|
# Base class for Happy controllers. A controller's primary job is to act
|
@@ -14,13 +20,11 @@ module Happy
|
|
14
20
|
include Actions
|
15
21
|
include Rackable
|
16
22
|
include Configurable
|
23
|
+
include Cascadable
|
24
|
+
include Permissions
|
25
|
+
include Helpers
|
17
26
|
|
18
|
-
attr_reader :options, :env, :
|
19
|
-
|
20
|
-
delegate :request, :response, :params, :session,
|
21
|
-
:previous_path, :remaining_path,
|
22
|
-
:render, :url_for,
|
23
|
-
:to => :context
|
27
|
+
attr_reader :options, :env, :unprocessed_path, :processed_path
|
24
28
|
|
25
29
|
# Creates a new instance of {Controller}. When a block is provided,
|
26
30
|
# it is run against the new instance, allowing custom controller classes
|
@@ -31,45 +35,54 @@ module Happy
|
|
31
35
|
# @param options [Hash]
|
32
36
|
# Controller options.
|
33
37
|
#
|
34
|
-
def initialize(
|
35
|
-
|
38
|
+
def initialize(env_or_parent = {}, options = {}, &blk)
|
39
|
+
if env_or_parent.is_a?(Happy::Controller)
|
40
|
+
@parent_controller = env_or_parent
|
41
|
+
@env = @parent_controller.env
|
42
|
+
@unprocessed_path = env_or_parent.unprocessed_path
|
43
|
+
@processed_path = env_or_parent.processed_path
|
44
|
+
else
|
45
|
+
@env = env_or_parent
|
46
|
+
@unprocessed_path = request.path.split('/').reject {|s| s.blank? }
|
47
|
+
@processed_path = []
|
48
|
+
end
|
49
|
+
|
36
50
|
@options = options
|
37
51
|
|
38
52
|
# Save a copy of the current path as this controller's root path.
|
39
|
-
@
|
53
|
+
@root_url = processed_path.join('/')
|
40
54
|
|
41
55
|
# Execute block against this instance, allowing the controller to
|
42
56
|
# provide a DSL for configuration.
|
43
57
|
instance_exec(&blk) if blk
|
44
58
|
end
|
45
59
|
|
46
|
-
|
47
|
-
|
48
|
-
# Run this controller, performing its routing logic.
|
49
|
-
#
|
50
|
-
def perform
|
51
|
-
context.with_controller(self) do
|
52
|
-
route
|
53
|
-
end
|
60
|
+
def request
|
61
|
+
@env['happy.request'] ||= Happy::Request.new(@env)
|
54
62
|
end
|
55
63
|
|
56
|
-
def
|
57
|
-
|
64
|
+
def response
|
65
|
+
@env['happy.response'] ||= Happy::Response.new
|
58
66
|
end
|
59
67
|
|
60
|
-
|
68
|
+
protected
|
61
69
|
|
62
|
-
def
|
63
|
-
url_for(
|
70
|
+
def root_url(*extras)
|
71
|
+
url_for(@root_url, extras)
|
64
72
|
end
|
65
73
|
|
66
|
-
|
67
|
-
|
74
|
+
private
|
75
|
+
|
76
|
+
def current_url(*extras)
|
77
|
+
url_for(processed_path, extras)
|
68
78
|
end
|
69
79
|
|
70
80
|
def route
|
71
81
|
# override this in subclasses
|
72
82
|
end
|
73
83
|
|
84
|
+
def params; request.params; end
|
85
|
+
def session; request.session; end
|
86
|
+
|
74
87
|
end
|
75
88
|
end
|
@@ -8,7 +8,7 @@ module Happy
|
|
8
8
|
|
9
9
|
# Mix in default options
|
10
10
|
options = {
|
11
|
-
:layout =>
|
11
|
+
:layout => response.layout
|
12
12
|
}.merge(options)
|
13
13
|
|
14
14
|
# Add status code from options
|
@@ -31,9 +31,9 @@ module Happy
|
|
31
31
|
end
|
32
32
|
end
|
33
33
|
|
34
|
-
def halt!(message = :done)
|
34
|
+
def halt!(message = :done, what = nil)
|
35
35
|
only_if_path_matches do
|
36
|
-
throw message
|
36
|
+
throw message, what || response
|
37
37
|
end
|
38
38
|
end
|
39
39
|
|
@@ -46,7 +46,7 @@ module Happy
|
|
46
46
|
end
|
47
47
|
|
48
48
|
def layout(name)
|
49
|
-
|
49
|
+
response.layout = name
|
50
50
|
end
|
51
51
|
|
52
52
|
def content_type(type)
|
@@ -79,11 +79,10 @@ module Happy
|
|
79
79
|
def run(thing, options = {}, &blk)
|
80
80
|
if thing.is_a?(Class) && thing.ancestors.include?(Happy::Controller)
|
81
81
|
# Happy controllers!
|
82
|
-
thing.new(
|
82
|
+
thing.new(self, options, &blk).route
|
83
83
|
elsif thing.respond_to?(:call)
|
84
84
|
# Rack apps!
|
85
|
-
|
86
|
-
throw :done
|
85
|
+
throw :done, thing.call(request.env)
|
87
86
|
elsif thing.respond_to?(:to_s)
|
88
87
|
thing.to_s
|
89
88
|
else
|
@@ -99,7 +98,7 @@ module Happy
|
|
99
98
|
# is not the path the user requested.)
|
100
99
|
#
|
101
100
|
def only_if_path_matches
|
102
|
-
yield if
|
101
|
+
yield if unprocessed_path.empty?
|
103
102
|
end
|
104
103
|
end
|
105
104
|
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Happy
|
2
|
+
class Controller
|
3
|
+
module Cascadable
|
4
|
+
def method_missing(name, *args, &blk)
|
5
|
+
if @parent_controller && @parent_controller.respond_to?(name)
|
6
|
+
@parent_controller.send(name, *args, &blk)
|
7
|
+
else
|
8
|
+
super
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def respond_to?(name)
|
13
|
+
super || @parent_controller.try(:respond_to?, name)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
require 'allowance'
|
2
|
+
|
3
|
+
module Happy
|
4
|
+
class Controller
|
5
|
+
module Permissions
|
6
|
+
def permissions(&blk)
|
7
|
+
(@env['happy.permissions'] ||= Allowance::Permissions.new).tap do |p|
|
8
|
+
if blk
|
9
|
+
blk.arity == 0 ? p.instance_exec(&blk) : blk.call(p)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
alias_method :can, :permissions
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -4,19 +4,21 @@ module Happy
|
|
4
4
|
extend ActiveSupport::Concern
|
5
5
|
|
6
6
|
def handle_request
|
7
|
-
catch :done do
|
8
|
-
serve!(
|
7
|
+
r = catch :done do
|
8
|
+
serve!(route) or raise Errors::NotFound
|
9
9
|
end
|
10
10
|
|
11
|
-
response
|
11
|
+
r ||response
|
12
|
+
|
12
13
|
rescue Errors::NotFound => e
|
13
|
-
html = Errors.html e,
|
14
|
+
html = Errors.html e, self,
|
14
15
|
:title => "Path not found",
|
15
16
|
:message => '',
|
16
|
-
:friendly_message => "You performed a <strong>#{
|
17
|
+
:friendly_message => "You performed a <strong>#{request.request_method}</strong> request on <strong>#{request.path}</strong>, but your application did not know how to handle this request."
|
17
18
|
[404, {'Content-type' => 'text/html'}, [html]]
|
19
|
+
|
18
20
|
rescue ::Exception => e
|
19
|
-
html = Errors.html e,
|
21
|
+
html = Errors.html e, self
|
20
22
|
[500, {'Content-type' => 'text/html'}, [html]]
|
21
23
|
end
|
22
24
|
|
@@ -16,13 +16,13 @@ module Happy
|
|
16
16
|
if name.present?
|
17
17
|
# convert symbols to ":foo" type string
|
18
18
|
name = ":#{name}" if name.is_a?(Symbol)
|
19
|
-
path_match = path_to_regexp(name).match(
|
19
|
+
path_match = path_to_regexp(name).match(unprocessed_path.first)
|
20
20
|
end
|
21
21
|
|
22
22
|
# Match the request method, if specified
|
23
23
|
method_matched = [nil, request.request_method.downcase.to_sym].include?(options[:method])
|
24
24
|
|
25
|
-
path_matched = (path_match || (name.nil? &&
|
25
|
+
path_matched = (path_match || (name.nil? && unprocessed_path.empty?))
|
26
26
|
|
27
27
|
# Only do something here if method and requested path both match
|
28
28
|
if path_matched && method_matched
|
@@ -31,7 +31,7 @@ module Happy
|
|
31
31
|
name.scan(/:(\w+)/).flatten.each do |var|
|
32
32
|
request.params[var] = path_match.captures.shift
|
33
33
|
end
|
34
|
-
|
34
|
+
processed_path << unprocessed_path.shift
|
35
35
|
end
|
36
36
|
|
37
37
|
serve!(instance_exec(&blk)) or raise Errors::NotFound
|
data/lib/happy/errors.rb
CHANGED
@@ -18,15 +18,13 @@ module Happy
|
|
18
18
|
# Friendly error message to be displayed below title and message.
|
19
19
|
# If left blank, will be generated from the exception message.
|
20
20
|
#
|
21
|
-
def self.html(exception,
|
21
|
+
def self.html(exception, controller, options = {})
|
22
22
|
options = {
|
23
23
|
:title => exception.class.to_s,
|
24
24
|
:message => exception.message,
|
25
25
|
:friendly_message => nil
|
26
26
|
}.merge(options)
|
27
27
|
|
28
|
-
context = env['happy.context']
|
29
|
-
|
30
28
|
# Load and cache error template.
|
31
29
|
@html = begin
|
32
30
|
File.read(File.expand_path(File.join(__FILE__, '../files/error.erb')))
|
@@ -1,5 +1,3 @@
|
|
1
|
-
require 'happy/extras/permissions'
|
2
|
-
|
3
1
|
module Happy
|
4
2
|
module Extras
|
5
3
|
module Resources
|
@@ -31,19 +29,19 @@ module Happy
|
|
31
29
|
end
|
32
30
|
|
33
31
|
def set_plural_variable(v)
|
34
|
-
|
32
|
+
instance_variable_set "@#{options[:plural_name]}", v
|
35
33
|
end
|
36
34
|
|
37
35
|
def plural_variable
|
38
|
-
|
36
|
+
instance_variable_get "@#{options[:plural_name]}"
|
39
37
|
end
|
40
38
|
|
41
39
|
def set_singular_variable(v)
|
42
|
-
|
40
|
+
instance_variable_set "@#{options[:singular_name]}", v
|
43
41
|
end
|
44
42
|
|
45
43
|
def singular_variable
|
46
|
-
|
44
|
+
instance_variable_get "@#{options[:singular_name]}"
|
47
45
|
end
|
48
46
|
|
49
47
|
def do_index
|
data/lib/happy/files/error.erb
CHANGED
@@ -110,17 +110,17 @@
|
|
110
110
|
|
111
111
|
<h2>Request Parameters:</h2>
|
112
112
|
<div class="output params">
|
113
|
-
<%= h
|
113
|
+
<%= h controller.request.params.inspect %>
|
114
114
|
</div>
|
115
115
|
|
116
116
|
<h2>Session:</h2>
|
117
117
|
<div class="output session">
|
118
|
-
<%= h
|
118
|
+
<%= h controller.request.session.inspect %>
|
119
119
|
</div>
|
120
120
|
|
121
121
|
<h2>Environment:</h2>
|
122
122
|
<div class="output env">
|
123
|
-
<%= h env %>
|
123
|
+
<%= h controller.env %>
|
124
124
|
</div>
|
125
125
|
|
126
126
|
<p>
|
data/lib/happy/version.rb
CHANGED
@@ -28,7 +28,7 @@ module Happy
|
|
28
28
|
|
29
29
|
it "uses the layout provided through the :layout option" do
|
30
30
|
instance = Controller.new
|
31
|
-
instance.
|
31
|
+
instance.should_receive(:render).with('layout.erb')
|
32
32
|
|
33
33
|
catch(:done) { instance.serve! "content", :layout => 'layout.erb' }
|
34
34
|
end
|
@@ -138,12 +138,12 @@ module Happy
|
|
138
138
|
|
139
139
|
describe '#header' do
|
140
140
|
it "sets the specified header in the response" do
|
141
|
-
subject.send(:
|
141
|
+
subject.send(:response).should_receive(:[]=).with('Content-type', 'text/css')
|
142
142
|
subject.header 'Content-type', 'text/css'
|
143
143
|
end
|
144
144
|
|
145
145
|
it "also accepts the header name as a symbol" do
|
146
|
-
subject.send(:
|
146
|
+
subject.send(:response).should_receive(:[]=).with('Content-type', 'text/css')
|
147
147
|
subject.header :content_type, 'text/css'
|
148
148
|
end
|
149
149
|
end
|
@@ -157,7 +157,7 @@ module Happy
|
|
157
157
|
|
158
158
|
describe '#layout' do
|
159
159
|
it "sets the layout to be used by the current context" do
|
160
|
-
subject.send(:
|
160
|
+
subject.send(:response).should_receive(:layout=).with('layout.erb')
|
161
161
|
subject.layout 'layout.erb'
|
162
162
|
end
|
163
163
|
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
module Happy
|
4
|
+
describe Controller::Cascadable do
|
5
|
+
|
6
|
+
describe '#method_missing' do
|
7
|
+
it "passes on all method calls to a parent if there is one" do
|
8
|
+
class Inner < Controller
|
9
|
+
def route
|
10
|
+
path 'one' do
|
11
|
+
some_helper
|
12
|
+
end
|
13
|
+
|
14
|
+
path 'two' do
|
15
|
+
some_unknown_helper
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
class Middle < Controller
|
21
|
+
def route
|
22
|
+
run Inner
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
class Outer < Controller
|
27
|
+
def some_helper; 'some_information'; end
|
28
|
+
def route
|
29
|
+
run Middle
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
def app
|
34
|
+
Outer
|
35
|
+
end
|
36
|
+
|
37
|
+
response_for { get '/one' }.body.should == 'some_information'
|
38
|
+
response_for { get '/two' }.status.should == 500
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
end
|
data/spec/controller_spec.rb
CHANGED
@@ -18,19 +18,19 @@ module Happy
|
|
18
18
|
last_response.body.should == 'it works'
|
19
19
|
end
|
20
20
|
|
21
|
-
describe '#
|
21
|
+
describe '#current_url' do
|
22
22
|
it "returns the current URL" do
|
23
23
|
def app
|
24
24
|
build_controller do
|
25
25
|
path 'foo' do
|
26
26
|
path 'bar' do
|
27
|
-
"My URL is #{
|
27
|
+
"My URL is #{current_url}"
|
28
28
|
end
|
29
29
|
|
30
|
-
"My URL is #{
|
30
|
+
"My URL is #{current_url}"
|
31
31
|
end
|
32
32
|
|
33
|
-
"My URL is #{
|
33
|
+
"My URL is #{current_url}"
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
@@ -43,12 +43,12 @@ module Happy
|
|
43
43
|
def app
|
44
44
|
build_controller do
|
45
45
|
path 'foo' do
|
46
|
-
|
46
|
+
current_url('bar', 'moo')
|
47
47
|
end
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
|
-
response_for { get '/foo' }.body.should == "/foo/bar"
|
51
|
+
response_for { get '/foo' }.body.should == "/foo/bar/moo"
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: happy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.0.
|
4
|
+
version: 0.1.0.pre20
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,11 +9,11 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-06-
|
12
|
+
date: 2012-06-12 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70246363046260 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ~>
|
@@ -21,10 +21,10 @@ dependencies:
|
|
21
21
|
version: '3.1'
|
22
22
|
type: :runtime
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70246363046260
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rack
|
27
|
-
requirement: &
|
27
|
+
requirement: &70246363043080 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,21 +32,21 @@ dependencies:
|
|
32
32
|
version: '1.4'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70246363043080
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: happy-helpers
|
38
|
-
requirement: &
|
38
|
+
requirement: &70246363042320 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
42
42
|
- !ruby/object:Gem::Version
|
43
|
-
version: 0.1.0.
|
43
|
+
version: 0.1.0.pre11
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70246363042320
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: allowance
|
49
|
-
requirement: &
|
49
|
+
requirement: &70246363058000 !ruby/object:Gem::Requirement
|
50
50
|
none: false
|
51
51
|
requirements:
|
52
52
|
- - ! '>='
|
@@ -54,10 +54,10 @@ dependencies:
|
|
54
54
|
version: 0.1.1
|
55
55
|
type: :runtime
|
56
56
|
prerelease: false
|
57
|
-
version_requirements: *
|
57
|
+
version_requirements: *70246363058000
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: happy-cli
|
60
|
-
requirement: &
|
60
|
+
requirement: &70246363056880 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: 0.1.0.pre1
|
66
66
|
type: :runtime
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70246363056880
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rake
|
71
|
-
requirement: &
|
71
|
+
requirement: &70246363056380 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ! '>='
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70246363056380
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec
|
82
|
-
requirement: &
|
82
|
+
requirement: &70246363055680 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ~>
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '2.8'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70246363055680
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rspec-html-matchers
|
93
|
-
requirement: &
|
93
|
+
requirement: &70246363054880 !ruby/object:Gem::Requirement
|
94
94
|
none: false
|
95
95
|
requirements:
|
96
96
|
- - ! '>='
|
@@ -98,10 +98,10 @@ dependencies:
|
|
98
98
|
version: '0'
|
99
99
|
type: :development
|
100
100
|
prerelease: false
|
101
|
-
version_requirements: *
|
101
|
+
version_requirements: *70246363054880
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: rack-test
|
104
|
-
requirement: &
|
104
|
+
requirement: &70246363054000 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,10 +109,10 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70246363054000
|
113
113
|
- !ruby/object:Gem::Dependency
|
114
114
|
name: watchr
|
115
|
-
requirement: &
|
115
|
+
requirement: &70246363053540 !ruby/object:Gem::Requirement
|
116
116
|
none: false
|
117
117
|
requirements:
|
118
118
|
- - ! '>='
|
@@ -120,7 +120,7 @@ dependencies:
|
|
120
120
|
version: '0'
|
121
121
|
type: :development
|
122
122
|
prerelease: false
|
123
|
-
version_requirements: *
|
123
|
+
version_requirements: *70246363053540
|
124
124
|
description: A happy little toolkit for writing web applications.
|
125
125
|
email:
|
126
126
|
- hendrik@mans.de
|
@@ -137,25 +137,30 @@ files:
|
|
137
137
|
- LICENSE
|
138
138
|
- README.md
|
139
139
|
- Rakefile
|
140
|
+
- example/config.ru
|
141
|
+
- example/views/index.erb
|
142
|
+
- example/views/layout.erb
|
140
143
|
- happy.gemspec
|
141
144
|
- lib/happy.rb
|
142
|
-
- lib/happy/context.rb
|
143
|
-
- lib/happy/context/helpers.rb
|
144
145
|
- lib/happy/controller.rb
|
145
146
|
- lib/happy/controller/actions.rb
|
147
|
+
- lib/happy/controller/cascadable.rb
|
146
148
|
- lib/happy/controller/configurable.rb
|
149
|
+
- lib/happy/controller/helpers.rb
|
150
|
+
- lib/happy/controller/permissions.rb
|
147
151
|
- lib/happy/controller/rackable.rb
|
148
152
|
- lib/happy/controller/routing.rb
|
149
153
|
- lib/happy/errors.rb
|
150
154
|
- lib/happy/extras/code_reloader.rb
|
151
|
-
- lib/happy/extras/permissions.rb
|
152
155
|
- lib/happy/extras/resources.rb
|
153
156
|
- lib/happy/extras/scriptable.rb
|
154
157
|
- lib/happy/extras/static.rb
|
155
158
|
- lib/happy/files/error.erb
|
156
159
|
- lib/happy/request.rb
|
160
|
+
- lib/happy/response.rb
|
157
161
|
- lib/happy/version.rb
|
158
162
|
- spec/controller/actions_spec.rb
|
163
|
+
- spec/controller/cascadable_spec.rb
|
159
164
|
- spec/controller/routing_spec.rb
|
160
165
|
- spec/controller_spec.rb
|
161
166
|
- spec/happy_spec.rb
|
@@ -186,6 +191,7 @@ specification_version: 3
|
|
186
191
|
summary: A happy little toolkit for writing web applications.
|
187
192
|
test_files:
|
188
193
|
- spec/controller/actions_spec.rb
|
194
|
+
- spec/controller/cascadable_spec.rb
|
189
195
|
- spec/controller/routing_spec.rb
|
190
196
|
- spec/controller_spec.rb
|
191
197
|
- spec/happy_spec.rb
|
data/lib/happy/context.rb
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
require 'happy/request'
|
2
|
-
require 'happy/context/helpers'
|
3
|
-
|
4
|
-
module Happy
|
5
|
-
# Represents the current request and its respective application state.
|
6
|
-
# Not only does this class wrap around both the incoming {#request} and the
|
7
|
-
# generated {#response}, but it is also used as the scope for all templates
|
8
|
-
# rendered through {#render_template}.
|
9
|
-
#
|
10
|
-
# (In case you're wondering, a particular request's instance of #{Context} is
|
11
|
-
# created from the Rack environment by #{Controller#context} when first accessed.)
|
12
|
-
#
|
13
|
-
# == View Helpers
|
14
|
-
#
|
15
|
-
# If you're coming from other web frameworks and looking for the right place
|
16
|
-
# to add "view helpers", this is it, since all templates being rendered use
|
17
|
-
# the request's instance of {Context} as their scope.
|
18
|
-
#
|
19
|
-
# The most convenient way of extending this class is through #{Happy.context}.
|
20
|
-
#
|
21
|
-
# Happy.context do
|
22
|
-
# def some_helper
|
23
|
-
# "I'm a view helper!"
|
24
|
-
# end
|
25
|
-
# end
|
26
|
-
#
|
27
|
-
# In addition to view helpers, the context is the place to add methods
|
28
|
-
# dealing with the current request scope, eg. methods like 'current_user'.
|
29
|
-
#
|
30
|
-
class Context
|
31
|
-
include Helpers
|
32
|
-
|
33
|
-
# Instance of {Happy::Request} representing the current HTTP request.
|
34
|
-
attr_reader :request
|
35
|
-
|
36
|
-
# The Rack::Response instance being used to compose the response.
|
37
|
-
attr_accessor :response
|
38
|
-
|
39
|
-
# The current layout template to be used when rendering the response.
|
40
|
-
attr_accessor :layout
|
41
|
-
|
42
|
-
# Array containing path parts that are yet to be handled.
|
43
|
-
attr_reader :remaining_path
|
44
|
-
|
45
|
-
# Array of path parts that have been handled so far.
|
46
|
-
attr_reader :previous_path
|
47
|
-
|
48
|
-
delegate :params, :session, :to => :request
|
49
|
-
|
50
|
-
# Initializes a new {Context} instance from a Rack environment hash.
|
51
|
-
#
|
52
|
-
# @param [Hash] env Rack environment hash
|
53
|
-
#
|
54
|
-
def initialize(env)
|
55
|
-
@request = Happy::Request.new(env)
|
56
|
-
@response = Rack::Response.new
|
57
|
-
|
58
|
-
@remaining_path = @request.path.split('/').reject {|s| s.blank? }
|
59
|
-
@previous_path = []
|
60
|
-
@layout = nil
|
61
|
-
@controller = nil
|
62
|
-
end
|
63
|
-
|
64
|
-
# @note
|
65
|
-
# This method is mostly used internally by Happy. You will not need
|
66
|
-
# to call it from your own controllers or applications.
|
67
|
-
#
|
68
|
-
# Execute the provided block, but register the provided {Controller}
|
69
|
-
# instance as the controller currently handling the request. Call this
|
70
|
-
# whenever you're passing control from one controller to another.
|
71
|
-
#
|
72
|
-
# @param [Controller] new_controller The {Controller} instance to set as the current controller
|
73
|
-
# @return Results of provided block.
|
74
|
-
#
|
75
|
-
def with_controller(new_controller)
|
76
|
-
# remember previous controller
|
77
|
-
old_controller = @controller
|
78
|
-
@controller = new_controller
|
79
|
-
|
80
|
-
# execute block
|
81
|
-
yield if block_given?
|
82
|
-
ensure
|
83
|
-
# switch back to previous controller
|
84
|
-
@controller = old_controller
|
85
|
-
end
|
86
|
-
|
87
|
-
end
|
88
|
-
end
|
@@ -1,32 +0,0 @@
|
|
1
|
-
require 'allowance'
|
2
|
-
|
3
|
-
module Happy
|
4
|
-
module Extras
|
5
|
-
module Permissions
|
6
|
-
module ContextExtensions
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
def permissions(&blk)
|
10
|
-
(@permissions ||= Allowance::Permissions.new).tap do |p|
|
11
|
-
if blk
|
12
|
-
blk.arity == 0 ? p.instance_exec(&blk) : blk.call(p)
|
13
|
-
end
|
14
|
-
end
|
15
|
-
end
|
16
|
-
|
17
|
-
alias_method :can, :permissions
|
18
|
-
end
|
19
|
-
|
20
|
-
module ControllerExtensions
|
21
|
-
extend ActiveSupport::Concern
|
22
|
-
|
23
|
-
included do
|
24
|
-
delegate :permissions, :can, :to => :context
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
28
|
-
end
|
29
|
-
end
|
30
|
-
|
31
|
-
Happy::Context.send(:include, Happy::Extras::Permissions::ContextExtensions)
|
32
|
-
Happy::Controller.send(:include, Happy::Extras::Permissions::ControllerExtensions)
|