Apotomo Goes Rubyconf

download Apotomo Goes Rubyconf

If you can't read please download the document

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?