apotomo 1.2.3 → 1.2.4
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/.gitignore +7 -3
- data/.travis.yml +6 -8
- data/CHANGES.textile +9 -5
- data/README.md +211 -0
- data/apotomo.gemspec +4 -4
- data/config/routes.rb +1 -1
- data/gemfiles/Gemfile.rails3-0 +6 -0
- data/gemfiles/Gemfile.rails3-1 +6 -0
- data/gemfiles/Gemfile.rails3-2 +6 -0
- data/gemfiles/Gemfile.rails4-0 +6 -0
- data/lib/apotomo/javascript_generator.rb +3 -3
- data/lib/apotomo/test_case.rb +14 -8
- data/lib/apotomo/version.rb +1 -1
- data/lib/apotomo/widget/javascript_methods.rb +3 -3
- data/lib/apotomo/widget/tree_node.rb +1 -1
- data/lib/apotomo/widget.rb +3 -3
- data/lib/generators/apotomo/widget_generator.rb +1 -1
- data/lib/generators/templates/view.slim +3 -4
- data/test/apotomo_test.rb +25 -14
- data/test/dummy/config/routes.rb +2 -57
- data/test/event_handler_test.rb +30 -60
- data/test/event_methods_test.rb +62 -62
- data/test/event_test.rb +11 -11
- data/test/invoke_event_handler_test.rb +59 -0
- data/test/javascript_generator_test.rb +57 -72
- data/test/rails/caching_test.rb +11 -11
- data/test/rails/controller_methods_test.rb +63 -57
- data/test/rails/rails_integration_test.rb +47 -47
- data/test/rails/view_helper_test.rb +31 -26
- data/test/rails/widget_generator_test.rb +16 -16
- data/test/render_test.rb +50 -50
- data/test/request_processor_test.rb +74 -74
- data/test/test_case_test.rb +45 -45
- data/test/test_helper.rb +14 -10
- data/test/tree_node_test.rb +5 -10
- data/test/widget_shortcuts_test.rb +25 -25
- data/test/widget_test.rb +82 -80
- metadata +73 -49
- data/README.rdoc +0 -205
- data/TODO +0 -36
- data/lib/apotomo/proc_event_handler.rb +0 -18
- data/test/onfire_integration_test.rb +0 -22
data/README.rdoc
DELETED
@@ -1,205 +0,0 @@
|
|
1
|
-
= Apotomo
|
2
|
-
|
3
|
-
<em>Web Components for Rails.</em>
|
4
|
-
|
5
|
-
{<img src="https://secure.travis-ci.org/apotonick/apotomo.png" />}[http://travis-ci.org/apotonick/apotomo]
|
6
|
-
|
7
|
-
== Overview
|
8
|
-
|
9
|
-
Do you need an <b>interactive user interface</b> for your Rails application? A cool Rich Client Application with dashboards, portlets and AJAX, Drag&Drop and jQuery?
|
10
|
-
|
11
|
-
Is your controller gettin' fat? And your partial-helper-AJAX pile is getting out of control?
|
12
|
-
|
13
|
-
Do you want a framework to make the implementation easier? <b>You want Apotomo.</b>
|
14
|
-
|
15
|
-
== Apotomo
|
16
|
-
|
17
|
-
Apotomo is based on {Cells}[http://github.com/apotonick/cells], the popular View Components framework for Rails.
|
18
|
-
|
19
|
-
It gives you widgets and encapsulation, bubbling events, AJAX page updates, rock-solid testing and more. Check out http://apotomo.de for a bunch of tutorials and a nice web 2.0 logo.
|
20
|
-
|
21
|
-
== Installation
|
22
|
-
|
23
|
-
Easy as hell.
|
24
|
-
|
25
|
-
=== Rails 3
|
26
|
-
|
27
|
-
gem install apotomo
|
28
|
-
|
29
|
-
=== Rails 2.3
|
30
|
-
|
31
|
-
gem install apotomo -v 0.1.4
|
32
|
-
|
33
|
-
Don't forget to load the gem in your app, either in your +Gemfile+ or +environment.rb+.
|
34
|
-
|
35
|
-
== Example!
|
36
|
-
|
37
|
-
A _shitty_ example is worse than a _shitty_ framework, so let's choose wisely...
|
38
|
-
|
39
|
-
Say you had a blog application. The page showing the post should have a comments block, with a list of comments and a form to post a new comment. Submitting should validate and send back the updated comments list, via AJAX.
|
40
|
-
|
41
|
-
Let's wrap that comments block in a widget.
|
42
|
-
|
43
|
-
== Generate
|
44
|
-
|
45
|
-
Go and generate a widget stub.
|
46
|
-
|
47
|
-
$ rails generate apotomo:widget Comments display write -e haml
|
48
|
-
create app/cells/
|
49
|
-
create app/cells/comments_widget
|
50
|
-
create app/cells/comments_widget.rb
|
51
|
-
create app/cells/comments_widget/display.html.haml
|
52
|
-
create app/cells/comments_widget/write.html.haml
|
53
|
-
create test/widgets/comments_widget_test.rb
|
54
|
-
|
55
|
-
Nothing special.
|
56
|
-
|
57
|
-
== Plug it in
|
58
|
-
|
59
|
-
You now tell your controller about the new widget.
|
60
|
-
|
61
|
-
class PostsController < ApplicationController
|
62
|
-
include Apotomo::Rails::ControllerMethods
|
63
|
-
|
64
|
-
has_widgets do |root|
|
65
|
-
root << widget(:comments, :post => @post)
|
66
|
-
end
|
67
|
-
|
68
|
-
This creates a widget instance called <tt>comments_widget</tt> from the class CommentsWidget. We pass the current post into the widget - the block is executed in controller instance context, that's were <tt>@post</tt> comes from. Handy, isn't it?
|
69
|
-
|
70
|
-
== Render the widget
|
71
|
-
|
72
|
-
Rendering usually happens in your controller view, <tt>views/posts/show.html.haml</tt>, for instance.
|
73
|
-
|
74
|
-
%h1 @post.title
|
75
|
-
|
76
|
-
%p
|
77
|
-
@post.body
|
78
|
-
|
79
|
-
%p
|
80
|
-
= render_widget :comments
|
81
|
-
|
82
|
-
== Write the widget
|
83
|
-
|
84
|
-
A widget is like a cell which is like a mini-controller.
|
85
|
-
|
86
|
-
class CommentsWidget < Apotomo::Widget
|
87
|
-
responds_to_event :post
|
88
|
-
|
89
|
-
def display(args)
|
90
|
-
@comments = args[:post].comments # the parameter from outside.
|
91
|
-
render
|
92
|
-
end
|
93
|
-
|
94
|
-
Having +display+ as the default state when rendering, this method collects comments to show and renders its view.
|
95
|
-
|
96
|
-
And look at line 2 - if encountering a <tt>:post</tt> event we invoke +#post+, which is simply another state. How cool is that?
|
97
|
-
|
98
|
-
def post(evt)
|
99
|
-
@comment = Comment.new(:post_id => evt[:post_id])
|
100
|
-
@comment.update_attributes evt[:comment] # a bit like params[].
|
101
|
-
|
102
|
-
update :state => :display
|
103
|
-
end
|
104
|
-
end
|
105
|
-
|
106
|
-
|
107
|
-
The event is processed with three steps in our widget:
|
108
|
-
|
109
|
-
* create the new comment
|
110
|
-
* re-render the +display+ state
|
111
|
-
* update itself on the page
|
112
|
-
|
113
|
-
Apotomo helps you focusing on your app and takes away the pain of <b>action dispatching</b> and <b>page updating</b>.
|
114
|
-
|
115
|
-
== Triggering events
|
116
|
-
|
117
|
-
So how and where is the <tt>:post</tt> event triggered?
|
118
|
-
|
119
|
-
Take a look at the widget's view <tt>display.html.haml</tt>.
|
120
|
-
= widget_div do
|
121
|
-
%ul
|
122
|
-
- for c in @comments
|
123
|
-
%li c.text
|
124
|
-
|
125
|
-
- form_for :comment, @comment, :url => url_for_event(:post), :remote => true do |f|
|
126
|
-
= f.error_messages
|
127
|
-
= f.text_field :text
|
128
|
-
|
129
|
-
= submit_tag "Don't be shy, comment!"
|
130
|
-
|
131
|
-
That's a lot of familiar view code, almost looks like a _partial_.
|
132
|
-
|
133
|
-
As soon as the form is submitted, the form gets serialized and sent using the standard Rails mechanisms. The interesting part here is the endpoint URL returned by #url_for_event as it will trigger an Apotomo event.
|
134
|
-
|
135
|
-
== Event processing
|
136
|
-
|
137
|
-
Now what happens when the event request is sent? Apotomo - again - does three things for you, it
|
138
|
-
|
139
|
-
* <b>accepts the request</b> on a special event route it adds to your app
|
140
|
-
* <b>triggers the event</b> in your ruby widget tree, which will invoke the +#post+ state in our comment widget
|
141
|
-
* <b>sends back</b> the page updates your widgets rendered
|
142
|
-
|
143
|
-
== JavaScript Agnosticism
|
144
|
-
|
145
|
-
In this example, we use jQuery for triggering. We could also use Prototype, RightJS, YUI, or a self-baked framework, that's up to you.
|
146
|
-
|
147
|
-
Also, updating the page is in your hands. Where Apotomo provides handy helpers as +#replace+, you could also <b>emit your own JavaScript</b>.
|
148
|
-
|
149
|
-
Look, +replace+ basically generates
|
150
|
-
|
151
|
-
$("comments").replaceWith(<the rendered view>);
|
152
|
-
|
153
|
-
If that's not what you want, do
|
154
|
-
|
155
|
-
def post(evt)
|
156
|
-
if evt[:comment][:text].explicit?
|
157
|
-
render :text => 'alert("Hey, you wanted to submit a pervert comment!");'
|
158
|
-
end
|
159
|
-
end
|
160
|
-
|
161
|
-
Apotomo doesn't depend on _any_ JS framework - you choose!
|
162
|
-
|
163
|
-
== Testing
|
164
|
-
|
165
|
-
Apotomo comes with its own test case and assertions to <b>build rock-solid web components</b>.
|
166
|
-
|
167
|
-
class CommentsWidgetTest < Apotomo::TestCase
|
168
|
-
has_widgets do |root|
|
169
|
-
root << widget(:comments, :post => @pervert_post)
|
170
|
-
end
|
171
|
-
|
172
|
-
def test_render
|
173
|
-
render_widget :comments
|
174
|
-
assert_select "li#me"
|
175
|
-
|
176
|
-
trigger :post, :comment => {:text => "Sex on the beach"}
|
177
|
-
assert_response 'alert("Hey, you wanted to submit a pervert comment!");'
|
178
|
-
end
|
179
|
-
end
|
180
|
-
|
181
|
-
You can render your widgets, spec the markup, trigger events and assert the event responses, so far. If you need more, let us know!
|
182
|
-
|
183
|
-
== More features
|
184
|
-
|
185
|
-
There's even more, too much for a simple README.
|
186
|
-
|
187
|
-
[Statefulness] Deriving your widget from +StatefulWidget+ gives you free statefulness.
|
188
|
-
[Composability] Widgets can range from small standalone components to nested widget trees like complex dashboards.
|
189
|
-
[Bubbling events] Events bubble up from their triggering source to root and thus can be observed, providing a way to implement loosely coupled, distributable components.
|
190
|
-
[Team-friendly] Widgets encourage encapsulation and help having different developers working on different components without getting out of bounds.
|
191
|
-
|
192
|
-
|
193
|
-
Give it a try- you will love the power and simplicity of real web components!
|
194
|
-
|
195
|
-
|
196
|
-
== Bugs, Community
|
197
|
-
Please visit http://apotomo.de, the official project page with <em>lots</em> of examples.
|
198
|
-
|
199
|
-
If you have questions, visit us in the IRC channel #cells at irc.freenode.org.
|
200
|
-
|
201
|
-
If you wanna be cool, subscribe to our feed[http://feeds.feedburner.com/Apotomo]!
|
202
|
-
|
203
|
-
|
204
|
-
== License
|
205
|
-
Copyright (c) 2007-2012 Nick Sutterer <apotonick@gmail.com> under the MIT License
|
data/TODO
DELETED
@@ -1,36 +0,0 @@
|
|
1
|
-
Testing
|
2
|
-
-------
|
3
|
-
- provide something like #assert_transition to test if FSM goes where we want
|
4
|
-
- assert_update/assert_execute, to assert which components are updated (e.g. after
|
5
|
-
event chain)
|
6
|
-
|
7
|
-
State Machine
|
8
|
-
-------------
|
9
|
-
- better debug-output for transitions
|
10
|
-
- make #transition_map friendly, maybe some more sophisticated DSL
|
11
|
-
|
12
|
-
Parameter
|
13
|
-
---------
|
14
|
-
- introduce #my_param or something similar so widgets can only access parameters really
|
15
|
-
addressed to them. or let #param do this per default.
|
16
|
-
|
17
|
-
Persistence
|
18
|
-
-----------
|
19
|
-
- only save id of ActiveRecords, to avoid big sessions (discuss whether this is necessary)
|
20
|
-
- provide session storage alternatives, like encoding in url or hidden field
|
21
|
-
- introduce a rake task to clear the frozen tree
|
22
|
-
|
23
|
-
Events
|
24
|
-
------
|
25
|
-
- only send back the newer EventHandler content when more than one event was triggered
|
26
|
-
and the content of an earlier EventHandler is overridden.
|
27
|
-
- provide scrambling of the event url, so users can not trigger events out of scope
|
28
|
-
- check if an EventHandler is executed in scope, meaning the triggering event was valid.
|
29
|
-
|
30
|
-
Apotobug
|
31
|
-
--------
|
32
|
-
- return exception reports as text, not HTML, for better reading in Firebug.
|
33
|
-
|
34
|
-
StatefulWidget
|
35
|
-
--------------
|
36
|
-
- provide an ordered list of rendered child views.
|
@@ -1,18 +0,0 @@
|
|
1
|
-
module Apotomo
|
2
|
-
class ProcEventHandler < EventHandler
|
3
|
-
attr_accessor :proc
|
4
|
-
|
5
|
-
def initialize(opts={})
|
6
|
-
@proc = opts.delete(:proc)
|
7
|
-
end
|
8
|
-
|
9
|
-
def process_event(event)
|
10
|
-
Rails.logger.debug "ProcEventHandler: calling #{@proc}"
|
11
|
-
#@proc.call(event)
|
12
|
-
event.source.controller.send(@proc, event)
|
13
|
-
nil ### DISCUSS: needed so that controller doesn't evaluate the "content".
|
14
|
-
end
|
15
|
-
|
16
|
-
def to_s; "ProcEventHandler:#{proc}"; end
|
17
|
-
end
|
18
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
require 'test_helper'
|
2
|
-
|
3
|
-
class OnfireIntegrationTest < Test::Unit::TestCase
|
4
|
-
include Apotomo::TestCaseMethods::TestController
|
5
|
-
|
6
|
-
context "including Onfire into the StatefulWidget it" do
|
7
|
-
setup do
|
8
|
-
@mum = mouse('mum')
|
9
|
-
@mum << mouse_mock(:kid)
|
10
|
-
@kid = @mum[:kid]
|
11
|
-
end
|
12
|
-
|
13
|
-
should "respond to #root" do
|
14
|
-
assert @mum.root?
|
15
|
-
assert ! @kid.root?
|
16
|
-
end
|
17
|
-
|
18
|
-
should "respond to #parent" do
|
19
|
-
assert_equal @mum, @kid.parent
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|