Finally living objects  in your Rails UI
cells with interactive behaviour and  statefulness
communicating through events
The name?
Apotomo
 
after this talk...
...i want you to be scared of Apotomo
What is Apotomo? <ul><li>an awesome plugin for Rails </li></ul><ul><li>introducing stateful widgets </li></ul><ul><li>and ...
it's all about...
<ul><ul><li>...the Apotomo::StatefulWidget </li></ul></ul>
<ul><ul><li>keep in mind: </li></ul></ul><ul><ul><li>every Apotomo widget is basically a  </li></ul></ul><ul><ul><li>cell ...
Any benefits? from this “stateful widget” thing?
“ stateful ” <ul><ul><li>persistence </li></ul></ul><ul><ul><li>a persistent object, managing its states automatically </l...
“ widget “ <ul><ul><li>reusable </li></ul></ul><ul><ul><li>reusable != throw-away code </li></ul></ul>
“ widget “ <ul><ul><li>composable </li></ul></ul><ul><ul><li>arranging your UI with  building blocks </li></ul></ul>
“ widget “ <ul><ul><li>independent </li></ul></ul><ul><ul><li>where building blocks are not coupled to the outside world <...
“ widget “ <ul><ul><li>wrapping </li></ul></ul><ul><ul><li>connecting worlds, like JS and Ruby </li></ul></ul>
“ widget “ <ul><ul><li>and... event-driven! </li></ul></ul><ul><ul><li>widgets talk about updates </li></ul></ul>
Who's me? <ul><li>My name </li></ul><ul><li>Nick Sutterer </li></ul><ul><li>from Germany </li></ul><ul><li>author of cells...
I'm currently working on... wickedornot.com
wickedornot.com
a mixture of blog/game/community
wickedornot.com
you upload products and you can rate other users
wickedornot.com
you can comment stuff
wickedornot.com
you can upload pictures for that product
wickedornot.com
“interesting.”
<ul><li>this is a Rails app </li></ul><ul><li>completely apotomo-driven </li></ul><ul><li>2 controller actions </li></ul><...
let's look at the gallery
 
<ul><li>clickable thumbnail gallery </li></ul>
<ul><li>full-size image </li></ul>
<ul><li>upload form </li></ul>
how do we implement that?
Start : the WidgetTree <ul><li>for defining your app UI </li></ul><ul><li>in  app/apotomo/application_widget_tree.rb </li>...
I start by adding a container widget
 
 
 
I keep adding fine-graind child widgets to the container
 
 
 
 
each widget has some corresponding view in the app
#cell <ul><li>shortcut  to create a ...Cell widget </li></ul><ul><li>you pass in </li></ul><ul><ul><li>cell class </li></u...
What we just got <ul><li>one big container widget </li></ul><ul><li>smaller child widgets </li></ul><ul><li>each widget im...
wow, we just covered...
My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>indep...
meaning... <ul><li>we can  nest  widgets </li></ul><ul><li>the parent widget takes care of its children </li></ul>
How do we plug in these widgets into the actual application?
#act_as_widget <ul><li>we're passing 'product_gallery' </li></ul>
meaning we're referencing to the gallery container
#act_as_widget
#act_as_widget
<ul><ul><li>and render that widget to the app </li></ul></ul>
and process its events
what we get is a nice, interactive gallery!
 
another composing examble would be the tabs!
a nice tab panel, within rails!
it's all about adding tabs to the panel
 
 
and adding actual content widets to the tabs
 
Tab  and  TabPanel  are out-of-the-box widgets and 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... <ul><li>we add that upload widget </li></ul><ul><li>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 the actual, concrete source of the upload widget
app/cells/product_image_cell.rb <ul><li>we're creating a ProductImage object </li></ul><ul><li>returning  nil </li></ul><u...
the  new.html.erb  looks like...
app/cells/product_image/new.html.erb <ul><li>another brainless view </li></ul><ul><li>where the first line is important! <...
<ul><li>Apotomo view helper method </li></ul><ul><li>when submitted triggers an event </li></ul>
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 <ul><li>we check the input </li></ul><ul><li>if valid </li></ul><ul><ul><li>jump back to  :new </li></u...
either ways, the widget will automatically update its view on the screen
where did that  @image  come from?
<ul><li>we're using  @image  that was created in :new </li></ul><ul><li>it's simply there </li></ul>
the state is preserved! @image @image :new :create
So, this is  stateful <ul><ul><li>you don't have to restore your environment after requests </li></ul></ul>
So, this is  stateful <ul><ul><li>it feels as if there is no request at all </li></ul></ul>
My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>indep...
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
<ul><ul><li>the upload widgets just triggered a  newImage  event </li></ul></ul>
<ul><ul><li>how can we catch that? </li></ul></ul>
The answer: use an  EventHandler !
adding EventHandlers I <ul><li>can be set up in the ApplicationWidgetTree </li></ul><ul><li>can also be attached within wi...
adding EventHandlers II <ul><li>#watch attaches a listener </li></ul><ul><li>“watch out for  newImage  events” </li></ul>
let's have a  quick  look at the  triggering  process
the  newImage  event is triggered
it bubbles up <ul><ul><li>asking every widget on its way </li></ul></ul><ul><ul><li>“are you interested in the  newImage  ...
?
?
<ul><ul><li>yes! the container widget is interested! </li></ul></ul>?
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 appears in full-screen
 
Great - although the  upload  widget  didn't even know there  is  a thumbnail gallery...
it just updated  a bunch  of other widgets
My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>indep...
and now?  reusability ?
reusability – sharing behaviour <ul><ul><li>between  projects </li></ul></ul>
reusability – sharing behaviour <ul><ul><li>and </li></ul></ul>
reusability – sharing behaviour <ul><ul><li>within  projects </li></ul></ul>
for example
 
 
this is a widget for rating  a product
we could  reuse  that widget in an iPhone mobile version, too!
<ul><ul><li>too bad, </li></ul></ul><ul><ul><li>this widget sits  deeeeeep </li></ul></ul><ul><ul><li>in the WidgetTree </...
 
a mobile controller
again, we're referencing a widget  in the widget tree in  #act_as_widget
 
 
<ul><ul><li>we're   extracting  only  a part  of the app  </li></ul></ul><ul><ul><li>to a controller action </li></ul></ul>
have a look at the mobile controller
 
My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>indep...
Finally, some neat stuff!
Apotomo  wraps  YUI widgets
example: the  DataTable  in  YUI
example: the  DataTable  in  YUI <ul><li>it's like one line of code </li></ul><ul><ul><li>for rendering </li></ul></ul><ul...
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 look at 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
<ul><ul><li>sorting? </li></ul></ul>
paging?
works all out-of-the-box
My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>indep...
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
<ul><ul><li>I added an observing widget, looking out for  cellClick  event </li></ul></ul><ul><ul><li>from the  DataTable ...
I clicked a cell in the grid
this triggered an event, actually in  Apotomo
<ul><li>so I processed a JS event </li></ul>in  Ruby
Enough!
There is more!
Caching
Caching
Testing <ul><li>test just one widget </li></ul><ul><li>test whole tree branches </li></ul>
<ul><li>http://apotomo.de </li></ul><ul><ul><li>samples </li></ul></ul><ul><ul><li>docs </li></ul></ul><ul><li>http://gith...
Enough for today...
Enough for today... are you scared of Apotomo?
Upcoming SlideShare
Loading in...5
×

Apotomo Goes Rubyconf

1,263

Published on

Talk about Apotomo (stateful widget components) by Mike Pence and Nick Sutterer at RubyConf 2008. See http://apotomo.de for more info.

Published in: Technology
1 Comment
0 Likes
Statistics
Notes
  • Hi Nick Sutterer,

    I want my money back for the project you did not finish! As you agreed - you wanted to stop the project and to pay back some of the money I gave you believing your words and believing in your skills. Don’t deceive me again -
    you owe me more than 1500 Euro that you offered to pay back in December 2009. So far I received no payments - therefore I want to remind you to put your money where your mouth is.

    Be a man and pay your debt.

    Best regards,

    Your creditor and former sponsor
       Reply 
    Are you sure you want to  Yes  No
    Your message goes here
  • Be the first to like this

No Downloads
Views
Total Views
1,263
On Slideshare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
21
Comments
1
Likes
0
Embeds 0
No embeds

No notes for slide
  • Apotomo Goes Rubyconf

    1. 1. Finally living objects in your Rails UI
    2. 2. cells with interactive behaviour and statefulness
    3. 3. communicating through events
    4. 4. The name?
    5. 5. Apotomo
    6. 7. after this talk...
    7. 8. ...i want you to be scared of Apotomo
    8. 9. What is Apotomo? <ul><li>an awesome plugin for Rails </li></ul><ul><li>introducing stateful widgets </li></ul><ul><li>and a GUI-like development feeling for (awesome) Rails developer </li></ul>
    9. 10. it's all about...
    10. 11. <ul><ul><li>...the Apotomo::StatefulWidget </li></ul></ul>
    11. 12. <ul><ul><li>keep in mind: </li></ul></ul><ul><ul><li>every Apotomo widget is basically a </li></ul></ul><ul><ul><li>cell on steroids </li></ul></ul>
    12. 13. Any benefits? from this “stateful widget” thing?
    13. 14. “ stateful ” <ul><ul><li>persistence </li></ul></ul><ul><ul><li>a persistent object, managing its states automatically </li></ul></ul>
    14. 15. “ widget “ <ul><ul><li>reusable </li></ul></ul><ul><ul><li>reusable != throw-away code </li></ul></ul>
    15. 16. “ widget “ <ul><ul><li>composable </li></ul></ul><ul><ul><li>arranging your UI with building blocks </li></ul></ul>
    16. 17. “ widget “ <ul><ul><li>independent </li></ul></ul><ul><ul><li>where building blocks are not coupled to the outside world </li></ul></ul>
    17. 18. “ widget “ <ul><ul><li>wrapping </li></ul></ul><ul><ul><li>connecting worlds, like JS and Ruby </li></ul></ul>
    18. 19. “ widget “ <ul><ul><li>and... event-driven! </li></ul></ul><ul><ul><li>widgets talk about updates </li></ul></ul>
    19. 20. Who's me? <ul><li>My name </li></ul><ul><li>Nick Sutterer </li></ul><ul><li>from Germany </li></ul><ul><li>author of cells and Apotomo </li></ul>
    20. 21. I'm currently working on... wickedornot.com
    21. 22. wickedornot.com
    22. 23. a mixture of blog/game/community
    23. 24. wickedornot.com
    24. 25. you upload products and you can rate other users
    25. 26. wickedornot.com
    26. 27. you can comment stuff
    27. 28. wickedornot.com
    28. 29. you can upload pictures for that product
    29. 30. wickedornot.com
    30. 31. “interesting.”
    31. 32. <ul><li>this is a Rails app </li></ul><ul><li>completely apotomo-driven </li></ul><ul><li>2 controller actions </li></ul><ul><li>~60 widgets </li></ul><ul><li>neatly arranged in a widget tree </li></ul>
    32. 33. let's look at the gallery
    33. 35. <ul><li>clickable thumbnail gallery </li></ul>
    34. 36. <ul><li>full-size image </li></ul>
    35. 37. <ul><li>upload form </li></ul>
    36. 38. how do we implement that?
    37. 39. Start : the WidgetTree <ul><li>for defining your app UI </li></ul><ul><li>in app/apotomo/application_widget_tree.rb </li></ul><ul><li>an initial representation </li></ul><ul><ul><li>you can change it during runtime </li></ul></ul>
    38. 40. I start by adding a container widget
    39. 44. I keep adding fine-graind child widgets to the container
    40. 49. each widget has some corresponding view in the app
    41. 50. #cell <ul><li>shortcut to create a ...Cell widget </li></ul><ul><li>you pass in </li></ul><ul><ul><li>cell class </li></ul></ul><ul><ul><li>start state </li></ul></ul><ul><ul><li>widget id </li></ul></ul>
    42. 51. What we just got <ul><li>one big container widget </li></ul><ul><li>smaller child widgets </li></ul><ul><li>each widget implements a control in the gallery </li></ul>
    43. 52. wow, we just covered...
    44. 53. My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>independent </li></ul><ul><li>wrapping </li></ul><ul><li>and event-driven </li></ul>
    45. 54. meaning... <ul><li>we can nest widgets </li></ul><ul><li>the parent widget takes care of its children </li></ul>
    46. 55. How do we plug in these widgets into the actual application?
    47. 56. #act_as_widget <ul><li>we're passing 'product_gallery' </li></ul>
    48. 57. meaning we're referencing to the gallery container
    49. 58. #act_as_widget
    50. 59. #act_as_widget
    51. 60. <ul><ul><li>and render that widget to the app </li></ul></ul>
    52. 61. and process its events
    53. 62. what we get is a nice, interactive gallery!
    54. 64. another composing examble would be the tabs!
    55. 65. a nice tab panel, within rails!
    56. 66. it's all about adding tabs to the panel
    57. 69. and adding actual content widets to the tabs
    58. 71. Tab and TabPanel are out-of-the-box widgets and are shipped with Apotomo (just for your convenience)
    59. 72. next: statefulness ?
    60. 73. example: the upload thing
    61. 74. it's a commonly used upload form
    62. 76. it is already added somewhere in the WidgetTree
    63. 77. somewhere in the WidgetTree... <ul><li>we add that upload widget </li></ul><ul><li>and assign its “start state” to :new </li></ul>
    64. 78. a widget goes to its start state when it's rendered the first time
    65. 79. now we're going to look at the actual, concrete source of the upload widget
    66. 80. app/cells/product_image_cell.rb <ul><li>we're creating a ProductImage object </li></ul><ul><li>returning nil </li></ul><ul><li>rendering the corresponding view new.html.erb </li></ul>
    67. 81. the new.html.erb looks like...
    68. 82. app/cells/product_image/new.html.erb <ul><li>another brainless view </li></ul><ul><li>where the first line is important! </li></ul>
    69. 83. <ul><li>Apotomo view helper method </li></ul><ul><li>when submitted triggers an event </li></ul>
    70. 84. in other words...
    71. 85. ...when submitting the form we are sending the upload widget to another state
    72. 86. :new :create
    73. 87. let's look at the next state
    74. 88. once again, the widget code
    75. 89. the state :create <ul><li>we check the input </li></ul><ul><li>if valid </li></ul><ul><ul><li>jump back to :new </li></ul></ul><ul><li>else </li></ul><ul><ul><li>display errors, stay in :create </li></ul></ul>
    76. 90. either ways, the widget will automatically update its view on the screen
    77. 91. where did that @image come from?
    78. 92. <ul><li>we're using @image that was created in :new </li></ul><ul><li>it's simply there </li></ul>
    79. 93. the state is preserved! @image @image :new :create
    80. 94. So, this is stateful <ul><ul><li>you don't have to restore your environment after requests </li></ul></ul>
    81. 95. So, this is stateful <ul><ul><li>it feels as if there is no request at all </li></ul></ul>
    82. 96. My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>independent </li></ul><ul><li>wrapping </li></ul><ul><li>and event-driven </li></ul>
    83. 97. so, this was an upload, but...
    84. 98. how do the fellow widgets know, there is a new image uploaded?
    85. 99. ?
    86. 100. why not use an event?
    87. 101. when the upload was ok...
    88. 102. ...we trigger an event
    89. 103. <ul><ul><li>the upload widgets just triggered a newImage event </li></ul></ul>
    90. 104. <ul><ul><li>how can we catch that? </li></ul></ul>
    91. 105. The answer: use an EventHandler !
    92. 106. adding EventHandlers I <ul><li>can be set up in the ApplicationWidgetTree </li></ul><ul><li>can also be attached within widget states </li></ul>
    93. 107. adding EventHandlers II <ul><li>#watch attaches a listener </li></ul><ul><li>“watch out for newImage events” </li></ul>
    94. 108. let's have a quick look at the triggering process
    95. 109. the newImage event is triggered
    96. 110. it bubbles up <ul><ul><li>asking every widget on its way </li></ul></ul><ul><ul><li>“are you interested in the newImage event triggered by 'upload'? </li></ul></ul>
    97. 111. ?
    98. 112. ?
    99. 113. <ul><ul><li>yes! the container widget is interested! </li></ul></ul>?
    100. 114. and it fires the EventHandler we just attached with #watch
    101. 115. the fired EventHandler will advise the thumbnails widget to update itself
    102. 116. a new thumbnail appears
    103. 118. and the newly uploaded picture appears in full-screen
    104. 120. Great - although the upload widget didn't even know there is a thumbnail gallery...
    105. 121. it just updated a bunch of other widgets
    106. 122. My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>independent </li></ul><ul><li>wrapping </li></ul><ul><li>and event-driven </li></ul>
    107. 123. and now? reusability ?
    108. 124. reusability – sharing behaviour <ul><ul><li>between projects </li></ul></ul>
    109. 125. reusability – sharing behaviour <ul><ul><li>and </li></ul></ul>
    110. 126. reusability – sharing behaviour <ul><ul><li>within projects </li></ul></ul>
    111. 127. for example
    112. 130. this is a widget for rating a product
    113. 131. we could reuse that widget in an iPhone mobile version, too!
    114. 132. <ul><ul><li>too bad, </li></ul></ul><ul><ul><li>this widget sits deeeeeep </li></ul></ul><ul><ul><li>in the WidgetTree </li></ul></ul>
    115. 134. a mobile controller
    116. 135. again, we're referencing a widget in the widget tree in #act_as_widget
    117. 138. <ul><ul><li>we're extracting only a part of the app </li></ul></ul><ul><ul><li>to a controller action </li></ul></ul>
    118. 139. have a look at the mobile controller
    119. 141. My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>independent </li></ul><ul><li>wrapping </li></ul><ul><li>and event-driven </li></ul>
    120. 142. Finally, some neat stuff!
    121. 143. Apotomo wraps YUI widgets
    122. 144. example: the DataTable in YUI
    123. 145. example: the DataTable in YUI <ul><li>it's like one line of code </li></ul><ul><ul><li>for rendering </li></ul></ul><ul><ul><li>and event-processing </li></ul></ul>
    124. 146. just to show off how awesome Apotomo is...
    125. 147. I'm gonna embed the DataTable in my wickedornot.com app
    126. 148. by adding a new Tab
    127. 149. embedding the DataTable
    128. 153. let's have a brief look at this cool MyDataTable widget
    129. 154. app/cells/my_data_table_cell.rb
    130. 155. all we gotta do...
    131. 156. inheriting from YUI::DataTable
    132. 157. adding columns
    133. 158. fill the data store with ...data
    134. 159. <ul><ul><li>sorting? </li></ul></ul>
    135. 160. paging?
    136. 161. works all out-of-the-box
    137. 162. My widgets should be... <ul><li>persistent </li></ul><ul><li>reusable </li></ul><ul><li>composable </li></ul><ul><li>independent </li></ul><ul><li>wrapping </li></ul><ul><li>and event-driven </li></ul>
    138. 163. Come on, one more!
    139. 164. what about adding some observing widget?
    140. 165. watching for clicks in the DataTable ?
    141. 166. this could look like...
    142. 167. add an observing widget
    143. 168. the implementation in the WidgetTree would be...
    144. 172. again, the #watch just means
    145. 173. “watch out for a cellClick event!”
    146. 174. “if you see one, update the observer!”
    147. 175. CLICK!
    148. 177. to summarize that
    149. 178. <ul><ul><li>I added an observing widget, looking out for cellClick event </li></ul></ul><ul><ul><li>from the DataTable </li></ul></ul>
    150. 179. I clicked a cell in the grid
    151. 180. this triggered an event, actually in Apotomo
    152. 181. <ul><li>so I processed a JS event </li></ul>in Ruby
    153. 182. Enough!
    154. 183. There is more!
    155. 184. Caching
    156. 185. Caching
    157. 186. Testing <ul><li>test just one widget </li></ul><ul><li>test whole tree branches </li></ul>
    158. 187. <ul><li>http://apotomo.de </li></ul><ul><ul><li>samples </li></ul></ul><ul><ul><li>docs </li></ul></ul><ul><li>http://github.org/apotonick/apotomo </li></ul><ul><li>#cells on freenode </li></ul><ul><li>... </li></ul>
    159. 188. Enough for today...
    160. 189. Enough for today... are you scared of Apotomo?
    1. A particular slide catching your eye?

      Clipping is a handy way to collect important slides you want to go back to later.

    ×