Apotomo Goes Rubyconf
-
Upload
monad -
Category
Technology
-
view
1.480 -
download
0
Transcript of Apotomo Goes Rubyconf
Finally
living objects in your Rails UI
cells with interactive behaviourand statefulness
communicating through events
The name?
Apotomo
after this talk...
...i want you to be scared of Apotomo
What is Apotomo?
an awesome plugin for Rails
introducing stateful widgets
and a GUI-like development feeling for (awesome) Rails developer
it's all about...
...the Apotomo::StatefulWidget
keep in mind:
every Apotomo widget is basically a
cell on steroids
Any benefits?
from this stateful widget thing?
stateful
persistence
a persistent object, managing its states automatically
widget
reusable
reusable != throw-away code
widget
composable
arranging your UI with building blocks
widget
independent
where building blocks are not coupled to the outside world
widget
wrapping
connecting worlds, like JS and Ruby
widget
and... event-driven!
widgets talk about updates
Who's me?
My name
Nick Sutterer
from Germany
author of cells and Apotomo
I'm currently working on...
wickedornot.com
wickedornot.com
a mixture of blog/game/community
wickedornot.com
you upload productsand you can rate other users
wickedornot.com
you can comment stuff
wickedornot.com
you can upload picturesfor that product
wickedornot.com
interesting.
this is a Rails app
completely apotomo-driven
2 controller actions
~60 widgets
neatly arranged in a widget tree
let's look at the gallery
clickable thumbnail gallery
full-size image
upload form
how do we implement that?
Start: the WidgetTree
for defining your app UI
in app/apotomo/application_widget_tree.rb
an initial representation
you can change it during runtime
I start by adding a container widget
to implement my gallery I first add a cell widget as a container
it's somehow similar to rendering a cell
I keep adding fine-graind child widgetsto the container
each widget has some corresponding viewin the app
#cell
shortcut to create a ...Cell widget
you pass in
cell class
start state
widget id
What we just got
one big container widget
smaller child widgets
each widget implements a control in the gallery
wow, we just covered...
My widgets should be...
persistent
reusable
composable
independent
wrapping
and event-driven
meaning...
we can nest widgets
the parent widget takes care of its children
How do we plug in these widgets intothe actual application?
#act_as_widget
we're passing 'product_gallery'
meaning we're referencing to the gallery container
#act_as_widget
#act_as_widget
and render that widget to the app
and process its events
what we get is a nice, interactive gallery!
another composing examble would bethe tabs!
a nice tab panel, within rails!
it's all about adding tabs to the panel
and adding actual content widetsto the tabs
Tab and TabPanel are out-of-the-box widgetsand are shipped with Apotomo(just for your convenience)
next: statefulness?
example: the upload thing
it's a commonly used upload form
it is already added somewhere in the WidgetTree
somewhere in the WidgetTree...
we add that upload widget
and assign its start state to :new
a widget goes to its start state when it's rendered the first time
now we're going to look at theactual, concrete sourceof the upload widget
app/cells/product_image_cell.rb
we're creating a ProductImage object
returning nil
rendering the corresponding view new.html.erb
the new.html.erb looks like...
app/cells/product_image/new.html.erb
another brainless view
where the first line is important!
Apotomo view helper method
when submitted triggers an event
in other words...
...when submitting the form we are sending the upload widget to another state
:new:create
let's look at the next state
once again, the widget code
the state :create
we check the input
if valid
jump back to :new
else
display errors, stay in :create
either ways, the widget will automatically update its view on the screen
where did that @image come from?
we're using @image that was created in :new
it's simply there
the state is preserved!
:new:create
@image
@image
So, this is stateful
you don't have to restore your environment after requests
So, this is stateful
it feels as if there is no request at all
My widgets should be...
persistent
reusable
composable
independent
wrapping
and event-driven
so, this was an upload, but...
how do the fellow widgets know,there is a new image uploaded?
?
why not use an event?
when the upload was ok...
...we trigger an event
the upload widgets just triggered a newImage event
how can we catch that?
The answer: use an EventHandler!
adding EventHandlers I
can be set up in the ApplicationWidgetTree
can also be attached within widget states
adding EventHandlers II
#watch attaches a listener
watch out for newImage events
let's have a quick lookat the triggering process
the newImage event is triggered
it bubbles up
asking every widget on its way
are you interested in the newImage event triggered by 'upload'?
?
?
?
yes! the container widget is interested!
and it fires the EventHandler we just attached with #watch
the fired EventHandler will advise the thumbnails widget to update itself
a new thumbnail appears
and the newly uploaded picture appearsin full-screen
Great - although the upload widget didn't even knowthere is a thumbnail gallery...
it just updated a bunch of other widgets
My widgets should be...
persistent
reusable
composable
independent
wrapping
and event-driven
and now? reusability?
reusability sharing behaviour
between projects
reusability sharing behaviour
and
reusability sharing behaviour
within projects
for example
this is a widget forrating a product
we could reuse that widgetin an iPhonemobile version, too!
too bad,
this widget sits deeeeeep
in the WidgetTree
a mobile controller
again, we're referencing a widget in the widget treein #act_as_widget
we're extracting only a part of the app
to a controller action
have a look at the mobile controller
My widgets should be...
persistent
reusable
composable
independent
wrapping
and event-driven
Finally, some neat stuff!
Apotomo wraps YUI widgets
example: the DataTable in YUI
example: the DataTable in YUI
it's like one line of code
for rendering
and event-processing
just to show off how awesome Apotomo is...
I'm gonna embed the DataTable in my wickedornot.com app
by adding a new Tab
embedding the DataTable
let's have a brief lookat this cool MyDataTable widget
app/cells/my_data_table_cell.rb
all we gotta do...
inheriting from YUI::DataTable
adding columns
fill the data store with ...data
sorting?
paging?
works all out-of-the-box
My widgets should be...
persistent
reusable
composable
independent
wrapping
and event-driven
Come on, one more!
what about adding some observing widget?
watching for clicks in the DataTable?
this could look like...
add an observing widget
the implementation in the WidgetTree would be...
again, the #watch just means
watch out for a cellClick event!
if you see one, update the observer!
CLICK!
to summarize that
I added an observing widget, looking out for cellClick event
from the DataTable
I clicked a cell in the grid
this triggered an event,actually in Apotomo
so I processed a JS event
in Ruby
Enough!
There is more!
Caching
Caching
Testing
test just one widget
test whole tree branches
http://apotomo.de
samples
docs
http://github.org/apotonick/apotomo
#cells on freenode
...
Enough for today...
Enough for today...
are you scared of Apotomo?