happy 0.1.0.pre24 → 0.1.0.pre25
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/README.md +10 -38
- data/example/config.ru +41 -0
- data/lib/happy/extras/action_controller.rb +41 -0
- data/lib/happy/extras/active_model_resource_controller.rb +99 -0
- data/lib/happy/extras/resource_controller.rb +21 -0
- data/lib/happy/version.rb +1 -1
- metadata +22 -20
- data/lib/happy/extras/resources.rb +0 -112
data/README.md
CHANGED
@@ -12,47 +12,19 @@ Furthermore, the way Happy handles incoming requests is vastly different from ho
|
|
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
|
+
## Usage
|
15
16
|
|
17
|
+
* The Happy Book of Happy (work in progress)
|
18
|
+
* [Reference Documentation](http://rdoc.info/github/hmans/happy/master/)
|
16
19
|
|
17
|
-
##
|
20
|
+
## Reporting Bugs & Contributing
|
18
21
|
|
19
|
-
|
22
|
+
* [Issues on Github](https://github.com/hmans/happy/issues)
|
20
23
|
|
21
|
-
|
24
|
+
I am trying to keep Happy's code base as sane (and small) as possible. If you
|
25
|
+
want to contribute code, _please_ talk to me _before_ writing a patch or submitting
|
26
|
+
a pull request! Thank you.
|
22
27
|
|
23
|
-
|
28
|
+
## Authors & Contributors
|
24
29
|
|
25
|
-
|
26
|
-
|
27
|
-
### Rendering templates
|
28
|
-
|
29
|
-
TODO
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
## Tutorial: Working with Controllers
|
34
|
-
|
35
|
-
### Invoking another controller
|
36
|
-
|
37
|
-
TODO
|
38
|
-
|
39
|
-
### Setting controller options
|
40
|
-
|
41
|
-
TODO
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
# Additional Information
|
48
|
-
|
49
|
-
## Current Status
|
50
|
-
|
51
|
-
Happy is being extracted from a web application that I've been working on. I'm trying to get a first, hopefully somewhat stable release out of the door some time during June 2012.
|
52
|
-
|
53
|
-
FWIW, here's a list of important things still missing right now:
|
54
|
-
|
55
|
-
* Better logging.
|
56
|
-
* Improved view engine compatibility.
|
57
|
-
|
58
|
-
Hendrik Mans, hendrik@mans.de
|
30
|
+
* [Hendrik Mans](mailto:hendrik@mans.de)
|
data/example/config.ru
CHANGED
@@ -4,6 +4,8 @@ lib_path = File.expand_path("#{File.dirname(__FILE__)}/../lib")
|
|
4
4
|
$LOAD_PATH.unshift lib_path unless $LOAD_PATH.include?(lib_path)
|
5
5
|
|
6
6
|
require 'happy'
|
7
|
+
require 'happy/extras/action_controller'
|
8
|
+
require 'happy/extras/resource_controller'
|
7
9
|
|
8
10
|
# Controllers are the core building blocks of Happy applications.
|
9
11
|
# They're also just Rack apps, so in any Happy app, you will
|
@@ -110,6 +112,14 @@ class TestApp < Happy::Controller
|
|
110
112
|
null.foobar
|
111
113
|
end
|
112
114
|
|
115
|
+
example 'ActionController' do
|
116
|
+
run ActionTest
|
117
|
+
end
|
118
|
+
|
119
|
+
example 'ResourceController' do
|
120
|
+
run ResourceTest
|
121
|
+
end
|
122
|
+
|
113
123
|
render 'index.erb'
|
114
124
|
end
|
115
125
|
|
@@ -124,4 +134,35 @@ class TestApp < Happy::Controller
|
|
124
134
|
end
|
125
135
|
end
|
126
136
|
|
137
|
+
class ActionTest < Happy::Extras::ActionController
|
138
|
+
def foo
|
139
|
+
if params['id']
|
140
|
+
"You called foo with ID #{params['id']}!"
|
141
|
+
else
|
142
|
+
"You called foo without an ID."
|
143
|
+
end
|
144
|
+
end
|
145
|
+
|
146
|
+
def bar
|
147
|
+
"The bar is open!"
|
148
|
+
end
|
149
|
+
|
150
|
+
def index
|
151
|
+
%{
|
152
|
+
This is the index method.
|
153
|
+
Try #{link_to 'foo', current_url('foo')}
|
154
|
+
(#{link_to 'with an ID', current_url('foo', '123')})
|
155
|
+
or #{link_to 'bar', current_url('bar')}!
|
156
|
+
}
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
class ResourceTest < Happy::Extras::ResourceController
|
161
|
+
%w{index show new create edit update destroy}.each do |action|
|
162
|
+
define_method action do
|
163
|
+
"You called #{action}!"
|
164
|
+
end
|
165
|
+
end
|
166
|
+
end
|
167
|
+
|
127
168
|
run TestApp
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Happy
|
2
|
+
module Extras
|
3
|
+
|
4
|
+
# A Rails-like controller that dispatches to individual actions
|
5
|
+
# named in the URL.
|
6
|
+
#
|
7
|
+
# The controller's root URL will call the `index` method, any sub-path
|
8
|
+
# will call the method by that name. If a third path is provided, it
|
9
|
+
# will be assigned to params['id'].
|
10
|
+
#
|
11
|
+
# / # index
|
12
|
+
# /foo # foo
|
13
|
+
# /foo/123 # foo (with params['id'] set to 123)
|
14
|
+
#
|
15
|
+
class ActionController < Happy::Controller
|
16
|
+
def route
|
17
|
+
on :action do
|
18
|
+
on :id do
|
19
|
+
dispatch_to_method params['action']
|
20
|
+
end
|
21
|
+
|
22
|
+
dispatch_to_method params['action']
|
23
|
+
end
|
24
|
+
|
25
|
+
index
|
26
|
+
end
|
27
|
+
|
28
|
+
protected
|
29
|
+
|
30
|
+
def dispatch_to_method(name)
|
31
|
+
# Only dispatch to public methods
|
32
|
+
if public_methods(false).include?(name.to_sym)
|
33
|
+
send name
|
34
|
+
else
|
35
|
+
raise Errors::NotFound
|
36
|
+
end
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'happy/extras/resource_controller'
|
2
|
+
|
3
|
+
module Happy
|
4
|
+
module Extras
|
5
|
+
|
6
|
+
class ActiveModelResourceController < Happy::Extras::ResourceController
|
7
|
+
def root_url
|
8
|
+
super(options[:plural_name])
|
9
|
+
end
|
10
|
+
|
11
|
+
def render_resource_template(name)
|
12
|
+
render "#{options[:plural_name]}/#{name}.html.haml"
|
13
|
+
end
|
14
|
+
|
15
|
+
def resource
|
16
|
+
options[:class]
|
17
|
+
end
|
18
|
+
|
19
|
+
def resource_with_permission_scope(*args)
|
20
|
+
permissions.scoped_model(*args, options[:class])
|
21
|
+
end
|
22
|
+
|
23
|
+
def require_permission!(*args)
|
24
|
+
raise "not allowed" unless permissions.can?(*args, options[:class])
|
25
|
+
end
|
26
|
+
|
27
|
+
def set_plural_variable(v)
|
28
|
+
instance_variable_set "@#{options[:plural_name]}", v
|
29
|
+
end
|
30
|
+
|
31
|
+
def plural_variable
|
32
|
+
instance_variable_get "@#{options[:plural_name]}"
|
33
|
+
end
|
34
|
+
|
35
|
+
def set_singular_variable(v)
|
36
|
+
instance_variable_set "@#{options[:singular_name]}", v
|
37
|
+
end
|
38
|
+
|
39
|
+
def singular_variable
|
40
|
+
instance_variable_get "@#{options[:singular_name]}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def index
|
44
|
+
require_permission! :index
|
45
|
+
set_plural_variable resource_with_permission_scope(:index).all
|
46
|
+
render_resource_template 'index'
|
47
|
+
end
|
48
|
+
|
49
|
+
def show
|
50
|
+
require_permission! :show
|
51
|
+
set_singular_variable resource_with_permission_scope(:show).find(params['id'])
|
52
|
+
render_resource_template 'show'
|
53
|
+
end
|
54
|
+
|
55
|
+
def new
|
56
|
+
require_permission! :new
|
57
|
+
set_singular_variable resource_with_permission_scope(:new).new(params[options[:singular_name]], :as => options[:role])
|
58
|
+
render_resource_template 'new'
|
59
|
+
end
|
60
|
+
|
61
|
+
def create
|
62
|
+
require_permission! :create
|
63
|
+
set_singular_variable resource_with_permission_scope(:create).new(params[options[:singular_name]], :as => options[:role])
|
64
|
+
|
65
|
+
if singular_variable.save
|
66
|
+
redirect! singular_variable
|
67
|
+
else
|
68
|
+
render_resource_template 'new'
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def edit
|
73
|
+
require_permission! :edit
|
74
|
+
set_singular_variable resource_with_permission_scope(:edit).find(params['id'])
|
75
|
+
render_resource_template 'edit'
|
76
|
+
end
|
77
|
+
|
78
|
+
def update
|
79
|
+
require_permission! :update
|
80
|
+
set_singular_variable resource_with_permission_scope(:update).find(params['id'])
|
81
|
+
singular_variable.assign_attributes params[options[:singular_name]], :as => options[:role]
|
82
|
+
|
83
|
+
if singular_variable.save
|
84
|
+
redirect! singular_variable
|
85
|
+
else
|
86
|
+
render_resource_template 'edit'
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
def route
|
91
|
+
options[:singular_name] ||= options[:class].to_s.tableize.singularize
|
92
|
+
options[:plural_name] ||= options[:class].to_s.tableize.pluralize
|
93
|
+
|
94
|
+
super
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module Happy
|
2
|
+
module Extras
|
3
|
+
|
4
|
+
class ResourceController < Happy::Controller
|
5
|
+
def route
|
6
|
+
on_get('new') { new }
|
7
|
+
|
8
|
+
on :id do
|
9
|
+
on_get { show }
|
10
|
+
on_post { update }
|
11
|
+
on_delete { destroy }
|
12
|
+
on_get('edit') { edit }
|
13
|
+
end
|
14
|
+
|
15
|
+
on_post { create }
|
16
|
+
on_get { index }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
data/lib/happy/version.rb
CHANGED
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.pre25
|
5
5
|
prerelease: 6
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -13,7 +13,7 @@ date: 2012-06-15 00:00:00.000000000 Z
|
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activesupport
|
16
|
-
requirement: &
|
16
|
+
requirement: &70205965488560 !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: *70205965488560
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
26
|
name: rack
|
27
|
-
requirement: &
|
27
|
+
requirement: &70205965488060 !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: *70205965488060
|
36
36
|
- !ruby/object:Gem::Dependency
|
37
37
|
name: happy-helpers
|
38
|
-
requirement: &
|
38
|
+
requirement: &70205965487600 !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: *70205965487600
|
47
47
|
- !ruby/object:Gem::Dependency
|
48
48
|
name: allowance
|
49
|
-
requirement: &
|
49
|
+
requirement: &70205965487140 !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: *70205965487140
|
58
58
|
- !ruby/object:Gem::Dependency
|
59
59
|
name: rake
|
60
|
-
requirement: &
|
60
|
+
requirement: &70205965486760 !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: *70205965486760
|
69
69
|
- !ruby/object:Gem::Dependency
|
70
70
|
name: rspec
|
71
|
-
requirement: &
|
71
|
+
requirement: &70205965502600 !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: *70205965502600
|
80
80
|
- !ruby/object:Gem::Dependency
|
81
81
|
name: rspec-html-matchers
|
82
|
-
requirement: &
|
82
|
+
requirement: &70205965502180 !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: *70205965502180
|
91
91
|
- !ruby/object:Gem::Dependency
|
92
92
|
name: rack-test
|
93
|
-
requirement: &
|
93
|
+
requirement: &70205965501720 !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: *70205965501720
|
102
102
|
- !ruby/object:Gem::Dependency
|
103
103
|
name: watchr
|
104
|
-
requirement: &
|
104
|
+
requirement: &70205965501300 !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: *70205965501300
|
113
113
|
description: A happy little toolkit for writing web applications.
|
114
114
|
email:
|
115
115
|
- hendrik@mans.de
|
@@ -140,8 +140,10 @@ files:
|
|
140
140
|
- lib/happy/controller/rackable.rb
|
141
141
|
- lib/happy/controller/routing.rb
|
142
142
|
- lib/happy/errors.rb
|
143
|
+
- lib/happy/extras/action_controller.rb
|
144
|
+
- lib/happy/extras/active_model_resource_controller.rb
|
143
145
|
- lib/happy/extras/code_reloader.rb
|
144
|
-
- lib/happy/extras/
|
146
|
+
- lib/happy/extras/resource_controller.rb
|
145
147
|
- lib/happy/extras/scriptable.rb
|
146
148
|
- lib/happy/extras/static.rb
|
147
149
|
- lib/happy/files/error.erb
|
@@ -1,112 +0,0 @@
|
|
1
|
-
module Happy
|
2
|
-
module Extras
|
3
|
-
module Resources
|
4
|
-
def resource(klass, options = {}, &blk)
|
5
|
-
run ResourceMounter, options.merge(:class => klass), &blk
|
6
|
-
end
|
7
|
-
|
8
|
-
class ResourceMounter < Happy::Controller
|
9
|
-
def root_url
|
10
|
-
super(options[:plural_name])
|
11
|
-
end
|
12
|
-
|
13
|
-
def render_resource_template(name)
|
14
|
-
render "#{options[:plural_name]}/#{name}.html.haml"
|
15
|
-
end
|
16
|
-
|
17
|
-
def resource
|
18
|
-
options[:class]
|
19
|
-
end
|
20
|
-
|
21
|
-
def resource_with_permission_scope(*args)
|
22
|
-
permissions.scoped_model(*args, options[:class])
|
23
|
-
end
|
24
|
-
|
25
|
-
def require_permission!(*args)
|
26
|
-
raise "not allowed" unless permissions.can?(*args, options[:class])
|
27
|
-
end
|
28
|
-
|
29
|
-
def set_plural_variable(v)
|
30
|
-
instance_variable_set "@#{options[:plural_name]}", v
|
31
|
-
end
|
32
|
-
|
33
|
-
def plural_variable
|
34
|
-
instance_variable_get "@#{options[:plural_name]}"
|
35
|
-
end
|
36
|
-
|
37
|
-
def set_singular_variable(v)
|
38
|
-
instance_variable_set "@#{options[:singular_name]}", v
|
39
|
-
end
|
40
|
-
|
41
|
-
def singular_variable
|
42
|
-
instance_variable_get "@#{options[:singular_name]}"
|
43
|
-
end
|
44
|
-
|
45
|
-
def do_index
|
46
|
-
require_permission! :index
|
47
|
-
set_plural_variable resource_with_permission_scope(:index).all
|
48
|
-
render_resource_template 'index'
|
49
|
-
end
|
50
|
-
|
51
|
-
def do_show
|
52
|
-
require_permission! :show
|
53
|
-
set_singular_variable resource_with_permission_scope(:show).find(params['id'])
|
54
|
-
render_resource_template 'show'
|
55
|
-
end
|
56
|
-
|
57
|
-
def do_new
|
58
|
-
require_permission! :new
|
59
|
-
set_singular_variable resource_with_permission_scope(:new).new(params[options[:singular_name]], :as => options[:role])
|
60
|
-
render_resource_template 'new'
|
61
|
-
end
|
62
|
-
|
63
|
-
def do_create
|
64
|
-
require_permission! :create
|
65
|
-
set_singular_variable resource_with_permission_scope(:create).new(params[options[:singular_name]], :as => options[:role])
|
66
|
-
|
67
|
-
if singular_variable.save
|
68
|
-
redirect! singular_variable
|
69
|
-
else
|
70
|
-
render_resource_template 'new'
|
71
|
-
end
|
72
|
-
end
|
73
|
-
|
74
|
-
def do_edit
|
75
|
-
require_permission! :edit
|
76
|
-
set_singular_variable resource_with_permission_scope(:edit).find(params['id'])
|
77
|
-
render_resource_template 'edit'
|
78
|
-
end
|
79
|
-
|
80
|
-
def do_update
|
81
|
-
require_permission! :update
|
82
|
-
set_singular_variable resource_with_permission_scope(:update).find(params['id'])
|
83
|
-
singular_variable.assign_attributes params[options[:singular_name]], :as => options[:role]
|
84
|
-
|
85
|
-
if singular_variable.save
|
86
|
-
redirect! singular_variable
|
87
|
-
else
|
88
|
-
render_resource_template 'edit'
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
def route
|
93
|
-
options[:singular_name] ||= options[:class].to_s.tableize.singularize
|
94
|
-
options[:plural_name] ||= options[:class].to_s.tableize.pluralize
|
95
|
-
|
96
|
-
on options[:plural_name] do
|
97
|
-
on_get('new') { do_new }
|
98
|
-
|
99
|
-
on :id do
|
100
|
-
on_get { do_show }
|
101
|
-
on_post { do_update }
|
102
|
-
on_get('edit') { do_edit }
|
103
|
-
end
|
104
|
-
|
105
|
-
on_post { do_create }
|
106
|
-
on_get { do_index }
|
107
|
-
end
|
108
|
-
end
|
109
|
-
end
|
110
|
-
end
|
111
|
-
end
|
112
|
-
end
|