happy 0.1.0.pre21 → 0.1.0.pre22
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +16 -76
- data/example/config.ru +8 -8
- data/lib/happy/controller/rackable.rb +1 -1
- data/lib/happy/controller/routing.rb +3 -3
- data/lib/happy/extras/resources.rb +8 -8
- data/lib/happy/version.rb +1 -1
- data/spec/controller/actions_spec.rb +6 -6
- data/spec/controller/cascadable_spec.rb +2 -2
- data/spec/controller/routing_spec.rb +13 -13
- data/spec/controller_spec.rb +6 -6
- metadata +20 -20
data/README.md
CHANGED
@@ -6,105 +6,45 @@
|
|
6
6
|
|
7
7
|
Happy is a toolkit for developing web applications using Ruby. Inspired by both Sinatra and Rails, it sits somewhere in the middle, trying to offer the super-light-weight attitude and flexibility of Sinatra, the comfort and power of Rails, and adding a big chunk of extensibility and modularity that any lover of object-oriented application design will enjoy.
|
8
8
|
|
9
|
-
Furthermore, the way Happy handles incoming requests is vastly different from how most of the other frameworks do it, offering a new, extremely flexible and
|
9
|
+
Furthermore, the way Happy handles incoming requests is vastly different from how most of the other frameworks do it, offering a new, extremely flexible and suspiciously fun way of building your application.
|
10
10
|
|
11
|
-
|
11
|
+
## Installing
|
12
12
|
|
13
|
-
|
13
|
+
Happy is available as a RubyGem, so just install it through `gem install happy` (or add it to your project's `Gemfile`. You know the drill.)
|
14
14
|
|
15
|
-
```ruby
|
16
|
-
# config.ru
|
17
|
-
require 'happy'
|
18
15
|
|
19
|
-
Happy.route do
|
20
|
-
'Hello world'
|
21
|
-
end
|
22
16
|
|
23
|
-
|
24
|
-
```
|
17
|
+
## Tutorial: The Basics
|
25
18
|
|
26
|
-
|
19
|
+
### Hello world
|
27
20
|
|
28
|
-
|
29
|
-
# config.ru
|
30
|
-
require 'happy'
|
21
|
+
TODO
|
31
22
|
|
32
|
-
|
33
|
-
# Set a default layout for all responses!
|
34
|
-
layout 'application.erb'
|
23
|
+
### Dealing with paths
|
35
24
|
|
36
|
-
|
37
|
-
path 'hello' do
|
38
|
-
# Let's use a different layout here.
|
39
|
-
layout 'hello_layout.erb'
|
25
|
+
TODO
|
40
26
|
|
41
|
-
|
42
|
-
path :name do
|
43
|
-
# Just return a string to happily render it!
|
44
|
-
"Hello, #{params['name']}"!
|
45
|
-
end
|
27
|
+
### Rendering templates
|
46
28
|
|
47
|
-
|
48
|
-
end
|
29
|
+
TODO
|
49
30
|
|
50
|
-
# Now let's do something a little bit more exciting!
|
51
|
-
#
|
52
|
-
# How about passing control to another controller? In this instance,
|
53
|
-
# we're invoking an instance of ResourceMounter, a controller class
|
54
|
-
# that serves a model resource RESTful-Rails-style. We'll save a
|
55
|
-
# reference to the controller for later.
|
56
31
|
|
57
|
-
articles = ResourceMounter.new(:class => Article)
|
58
|
-
articles.perform
|
59
32
|
|
60
|
-
|
33
|
+
## Tutorial: Working with Controllers
|
61
34
|
|
62
|
-
|
63
|
-
# some crazy stuff here, including only defining specific paths
|
64
|
-
# when certain conditions are given. Just write Ruby! :)
|
65
|
-
|
66
|
-
if context.user_is_admin?
|
67
|
-
path 'delete_everything' do
|
68
|
-
Article.delete_all
|
35
|
+
### Invoking another controller
|
69
36
|
|
70
|
-
|
71
|
-
# variables to it?
|
72
|
-
render 'admin_message.erb',
|
73
|
-
:message => 'You just deleted everything. Grats!'
|
74
|
-
end
|
75
|
-
end
|
37
|
+
TODO
|
76
38
|
|
77
|
-
|
78
|
-
# the user must by trying to access the root URL. How about a redirect
|
79
|
-
# to the URL of the previously invoked controller?
|
80
|
-
|
81
|
-
redirect! articles.root_url
|
82
|
-
end
|
39
|
+
### Setting controller options
|
83
40
|
|
84
|
-
|
85
|
-
```
|
41
|
+
TODO
|
86
42
|
|
87
43
|
|
88
|
-
### The Basic Building Blocks
|
89
44
|
|
90
|
-
Each and every web application built with Happy revolves around two core building blocks: the **context** and one or more **controllers**.
|
91
45
|
|
92
|
-
The **context** is a wrapper around the request currently being handled by your application. It holds information about the request itself, the response being rendered, and any piece of application logic that's scoped to individual requests (like authentication or authorization related code.) Happy doesn't have view helpers (like Rails); instead, view templates are rendered within the scope of the current context.
|
93
|
-
|
94
|
-
**Controllers** are building blocks that mostly deal with routing and acting on request URLs. Unlike controllers in Rails, instead of deciding on what controller to run depending on the requested URL, each request is immediately passed to a **root controller** which then decides how to continue. Controllers can serve content, parse the URL for paths, or even pass on control over the request to a different controller.
|
95
|
-
|
96
|
-
Controllers are the magic behind Happy; they're essentially **re-useable, self-contained, easily testable** web application classes that can be mounted at any URL you require. They can be as simple as serving a single response or as complex as a complete admin backend or blog engine. And finally, Happy Controllers are also **Rack applications**, so you can even use them anywhere you can mount Rack apps!
|
97
|
-
|
98
|
-
|
99
|
-
### More Happy Features
|
100
|
-
|
101
|
-
In addition to its fun and flexible approach to writing web applications, Happy boasts the following features, among others:
|
102
|
-
|
103
|
-
* Optional run-time permission management provided by [Allowance](https://github.com/hmans/allowance).
|
104
|
-
* A set of Happy Controllers making you super-productive, from serving static files to minifying JavaScript assets or even serving complete RESTful resources.
|
105
|
-
* A set of view helpers including [simple_form](https://github.com/plataformatec/simple_form) inspired forms on auto-pilot, with full support for translations and localization through [I18n](https://github.com/svenfuchs/i18n).
|
106
|
-
* Happy _loves_ Rack. You can mount Rack Middleware as well as pass control to another Rack application, just like that. Or use Happy Controllers from within other applications -- they're just Rack apps. And, of course, serve your Happy application through any Rack-compliant Rack server.
|
107
46
|
|
47
|
+
# Additional Information
|
108
48
|
|
109
49
|
## Current Status
|
110
50
|
|
data/example/config.ru
CHANGED
@@ -17,7 +17,7 @@ class TestApp < Happy::Controller
|
|
17
17
|
#
|
18
18
|
# This method can be as simple or complex as you like. In this example
|
19
19
|
# application, it wraps around a couple of annotated Happy examples.
|
20
|
-
# Usually, you'd use the #path method to specify code to be executed if
|
20
|
+
# Usually, you'd use the #path? method to specify code to be executed if
|
21
21
|
# a certain path was requested; in this app, we're using a custom #example
|
22
22
|
# method, that does the same thing but also records the example in a hash
|
23
23
|
# so we can generated a "table of contents" in index.erb.
|
@@ -38,8 +38,8 @@ class TestApp < Happy::Controller
|
|
38
38
|
end
|
39
39
|
|
40
40
|
example 'Path parameters' do
|
41
|
-
path 'hello' do
|
42
|
-
path :name do
|
41
|
+
path? 'hello' do
|
42
|
+
path? :name do
|
43
43
|
"Hello, #{params['name']}!"
|
44
44
|
end
|
45
45
|
end
|
@@ -48,7 +48,7 @@ class TestApp < Happy::Controller
|
|
48
48
|
end
|
49
49
|
|
50
50
|
example 'Inline path parameters' do
|
51
|
-
path 'hello-:name' do
|
51
|
+
path? 'hello-:name' do
|
52
52
|
"Hello, #{params['name']}!"
|
53
53
|
end
|
54
54
|
|
@@ -59,7 +59,7 @@ class TestApp < Happy::Controller
|
|
59
59
|
# set up permissions ;-)
|
60
60
|
can.dance!
|
61
61
|
|
62
|
-
path 'dance' do
|
62
|
+
path? 'dance' do
|
63
63
|
if can.dance?
|
64
64
|
"You can dance."
|
65
65
|
else
|
@@ -71,10 +71,10 @@ class TestApp < Happy::Controller
|
|
71
71
|
end
|
72
72
|
|
73
73
|
example 'Layouts' do
|
74
|
-
path 'with-layout' do
|
74
|
+
path? 'with-layout' do
|
75
75
|
layout 'layout.erb'
|
76
76
|
|
77
|
-
path 'changed-my-mind' do
|
77
|
+
path? 'changed-my-mind' do
|
78
78
|
layout false
|
79
79
|
"This should render without a layout."
|
80
80
|
end
|
@@ -120,7 +120,7 @@ class TestApp < Happy::Controller
|
|
120
120
|
examples[name] = path_name
|
121
121
|
|
122
122
|
# Create a path containing the example's code block
|
123
|
-
path(path_name, &blk)
|
123
|
+
path?(path_name, &blk)
|
124
124
|
end
|
125
125
|
end
|
126
126
|
|
@@ -7,7 +7,7 @@ module Happy
|
|
7
7
|
Regexp.compile('^'+path.gsub(/\)/, ')?').gsub(/\//, '\/').gsub(/\./, '\.').gsub(/:(\w+)/, '(.+)')+'$')
|
8
8
|
end
|
9
9
|
|
10
|
-
def path(*args, &blk)
|
10
|
+
def path?(*args, &blk)
|
11
11
|
options = (args.pop if args.last.is_a?(Hash)) || {}
|
12
12
|
args = [nil] if args.empty?
|
13
13
|
|
@@ -40,9 +40,9 @@ module Happy
|
|
40
40
|
end
|
41
41
|
|
42
42
|
[:get, :post, :put, :delete].each do |method|
|
43
|
-
define_method(method) do |*args, &blk|
|
43
|
+
define_method("#{method}?") do |*args, &blk|
|
44
44
|
args.last.is_a?(Hash) ? args.last.merge(:method => method) : args.push(:method => method)
|
45
|
-
path(*args, &blk)
|
45
|
+
path?(*args, &blk)
|
46
46
|
end
|
47
47
|
end
|
48
48
|
end
|
@@ -95,17 +95,17 @@ module Happy
|
|
95
95
|
options[:singular_name] ||= options[:class].to_s.tableize.singularize
|
96
96
|
options[:plural_name] ||= options[:class].to_s.tableize.pluralize
|
97
97
|
|
98
|
-
path options[:plural_name] do
|
99
|
-
get('new') { do_new }
|
98
|
+
path? options[:plural_name] do
|
99
|
+
get?('new') { do_new }
|
100
100
|
|
101
|
-
path :id do
|
102
|
-
get { do_show }
|
103
|
-
post { do_update }
|
104
|
-
get('edit') { do_edit }
|
101
|
+
path? :id do
|
102
|
+
get? { do_show }
|
103
|
+
post? { do_update }
|
104
|
+
get?('edit') { do_edit }
|
105
105
|
end
|
106
106
|
|
107
|
-
post { do_create }
|
108
|
-
get { do_index }
|
107
|
+
post? { do_create }
|
108
|
+
get? { do_index }
|
109
109
|
end
|
110
110
|
end
|
111
111
|
end
|
data/lib/happy/version.rb
CHANGED
@@ -7,10 +7,10 @@ module Happy
|
|
7
7
|
describe '#serve!' do
|
8
8
|
def app
|
9
9
|
build_controller do
|
10
|
-
path('simple') { serve! "Simple response" }
|
11
|
-
path('with_headers') { serve! "body { color: red }", :content_type => 'text/css' }
|
12
|
-
path('with_status') { serve! "Not Allowed", :status => 401 }
|
13
|
-
path('with_layout') { serve! "content", :layout => 'layout.erb' }
|
10
|
+
path?('simple') { serve! "Simple response" }
|
11
|
+
path?('with_headers') { serve! "body { color: red }", :content_type => 'text/css' }
|
12
|
+
path?('with_status') { serve! "Not Allowed", :status => 401 }
|
13
|
+
path?('with_layout') { serve! "content", :layout => 'layout.erb' }
|
14
14
|
end
|
15
15
|
end
|
16
16
|
|
@@ -45,7 +45,7 @@ module Happy
|
|
45
45
|
def app
|
46
46
|
Happy.route do
|
47
47
|
serve! "This should not render"
|
48
|
-
path 'test' do
|
48
|
+
path? 'test' do
|
49
49
|
serve! "But this should render"
|
50
50
|
end
|
51
51
|
end
|
@@ -80,7 +80,7 @@ module Happy
|
|
80
80
|
Happy.route do
|
81
81
|
redirect! "http://mans.de"
|
82
82
|
|
83
|
-
path 'test' do
|
83
|
+
path? 'test' do
|
84
84
|
redirect! "http://schnitzelpress.org"
|
85
85
|
end
|
86
86
|
end
|
@@ -5,17 +5,17 @@ module Happy
|
|
5
5
|
describe '#path' do
|
6
6
|
subject do
|
7
7
|
Happy.route do
|
8
|
-
path('foo') { serve! 'bar' }
|
9
|
-
path('one', 'two') { serve! 'onetwo' }
|
10
|
-
path('hello') do
|
11
|
-
path(:name) { serve! "Hello #{params['name']}" }
|
8
|
+
path?('foo') { serve! 'bar' }
|
9
|
+
path?('one', 'two') { serve! 'onetwo' }
|
10
|
+
path?('hello') do
|
11
|
+
path?(:name) { serve! "Hello #{params['name']}" }
|
12
12
|
serve! "Please provide a name."
|
13
13
|
end
|
14
|
-
path('number-:num') { serve! "num = #{params['num']}" }
|
15
|
-
path('return-value') { 'moo?' }
|
16
|
-
path('resource') do
|
17
|
-
get { 'GET resource' }
|
18
|
-
post { 'POST resource' }
|
14
|
+
path?('number-:num') { serve! "num = #{params['num']}" }
|
15
|
+
path?('return-value') { 'moo?' }
|
16
|
+
path?('resource') do
|
17
|
+
get? { 'GET resource' }
|
18
|
+
post? { 'POST resource' }
|
19
19
|
end
|
20
20
|
serve! "root"
|
21
21
|
end
|
@@ -62,12 +62,12 @@ module Happy
|
|
62
62
|
end
|
63
63
|
|
64
64
|
%w(get post put delete).each do |what|
|
65
|
-
describe "##{what}" do
|
65
|
+
describe "##{what}?" do
|
66
66
|
subject { Controller.new }
|
67
67
|
|
68
|
-
it "merely invokes #path with the :method => :#{what} option" do
|
69
|
-
subject.should_receive(:path).with('path', :method => what.to_sym)
|
70
|
-
subject.send(what, 'path')
|
68
|
+
it "merely invokes #path? with the :method => :#{what} option" do
|
69
|
+
subject.should_receive(:path?).with('path', :method => what.to_sym)
|
70
|
+
subject.send("#{what}?", 'path')
|
71
71
|
end
|
72
72
|
end
|
73
73
|
end
|
data/spec/controller_spec.rb
CHANGED
@@ -22,8 +22,8 @@ module Happy
|
|
22
22
|
it "returns the current URL" do
|
23
23
|
def app
|
24
24
|
build_controller do
|
25
|
-
path 'foo' do
|
26
|
-
path 'bar' do
|
25
|
+
path? 'foo' do
|
26
|
+
path? 'bar' do
|
27
27
|
"My URL is #{current_url}"
|
28
28
|
end
|
29
29
|
|
@@ -42,7 +42,7 @@ module Happy
|
|
42
42
|
it "appends extra paths to the URL if provided" do
|
43
43
|
def app
|
44
44
|
build_controller do
|
45
|
-
path 'foo' do
|
45
|
+
path? 'foo' do
|
46
46
|
current_url('bar', 'moo')
|
47
47
|
end
|
48
48
|
end
|
@@ -56,7 +56,7 @@ module Happy
|
|
56
56
|
it "returns the controller's root URL" do
|
57
57
|
def app
|
58
58
|
root_url_printer = build_controller do
|
59
|
-
path 'bar' do
|
59
|
+
path? 'bar' do
|
60
60
|
"My root URL is still #{root_url}"
|
61
61
|
end
|
62
62
|
|
@@ -64,7 +64,7 @@ module Happy
|
|
64
64
|
end
|
65
65
|
|
66
66
|
build_controller do
|
67
|
-
path 'foo' do
|
67
|
+
path? 'foo' do
|
68
68
|
run root_url_printer
|
69
69
|
end
|
70
70
|
|
@@ -84,7 +84,7 @@ module Happy
|
|
84
84
|
end
|
85
85
|
|
86
86
|
build_controller do
|
87
|
-
path 'foo' do
|
87
|
+
path? 'foo' do
|
88
88
|
run some_controller
|
89
89
|
end
|
90
90
|
end
|
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.pre22
|
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-13 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70226632793780 !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: *70226632793780
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rack
|
27
|
-
requirement: &
|
27
|
+
requirement: &70226632793280 !ruby/object:Gem::Requirement
|
28
28
|
none: false
|
29
29
|
requirements:
|
30
30
|
- - ~>
|
@@ -32,10 +32,10 @@ dependencies:
|
|
32
32
|
version: '1.4'
|
33
33
|
type: :runtime
|
34
34
|
prerelease: false
|
35
|
-
version_requirements: *
|
35
|
+
version_requirements: *70226632793280
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: happy-helpers
|
38
|
-
requirement: &
|
38
|
+
requirement: &70226632792820 !ruby/object:Gem::Requirement
|
39
39
|
none: false
|
40
40
|
requirements:
|
41
41
|
- - ~>
|
@@ -43,10 +43,10 @@ dependencies:
|
|
43
43
|
version: 0.1.0.pre11
|
44
44
|
type: :runtime
|
45
45
|
prerelease: false
|
46
|
-
version_requirements: *
|
46
|
+
version_requirements: *70226632792820
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: allowance
|
49
|
-
requirement: &
|
49
|
+
requirement: &70226632792360 !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: *70226632792360
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rake
|
60
|
-
requirement: &
|
60
|
+
requirement: &70226632791980 !ruby/object:Gem::Requirement
|
61
61
|
none: false
|
62
62
|
requirements:
|
63
63
|
- - ! '>='
|
@@ -65,10 +65,10 @@ dependencies:
|
|
65
65
|
version: '0'
|
66
66
|
type: :development
|
67
67
|
prerelease: false
|
68
|
-
version_requirements: *
|
68
|
+
version_requirements: *70226632791980
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &70226632791440 !ruby/object:Gem::Requirement
|
72
72
|
none: false
|
73
73
|
requirements:
|
74
74
|
- - ~>
|
@@ -76,10 +76,10 @@ dependencies:
|
|
76
76
|
version: '2.8'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
|
-
version_requirements: *
|
79
|
+
version_requirements: *70226632791440
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec-html-matchers
|
82
|
-
requirement: &
|
82
|
+
requirement: &70226632791020 !ruby/object:Gem::Requirement
|
83
83
|
none: false
|
84
84
|
requirements:
|
85
85
|
- - ! '>='
|
@@ -87,10 +87,10 @@ dependencies:
|
|
87
87
|
version: '0'
|
88
88
|
type: :development
|
89
89
|
prerelease: false
|
90
|
-
version_requirements: *
|
90
|
+
version_requirements: *70226632791020
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rack-test
|
93
|
-
requirement: &
|
93
|
+
requirement: &70226632790560 !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: *70226632790560
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: watchr
|
104
|
-
requirement: &
|
104
|
+
requirement: &70226632790140 !ruby/object:Gem::Requirement
|
105
105
|
none: false
|
106
106
|
requirements:
|
107
107
|
- - ! '>='
|
@@ -109,7 +109,7 @@ dependencies:
|
|
109
109
|
version: '0'
|
110
110
|
type: :development
|
111
111
|
prerelease: false
|
112
|
-
version_requirements: *
|
112
|
+
version_requirements: *70226632790140
|
113
113
|
description: A happy little toolkit for writing web applications.
|
114
114
|
email:
|
115
115
|
- hendrik@mans.de
|