There's a good video on building a simple app with Seaside (on Squeak Smalltalk) at this blog.
Here's the missing voice-over:
- Start your web server (SSKom startOn: 91.)
- Create a new category named "SeasideBlog"
- Change the generic class definition to declare BlogView a subclass of WAComponent. Accept.
- Define a class method canBeRoot, returning true. Accept. (I’m going to stop saying, “Accept.”
- Define and accept an instance method
renderContentOn: html
html text: 'Hello world!'
- Browse to your seaside/config site (http://localhost:91/seaside/config, ID=admin/seaside)
- Add an application entry point “seasideBlog”
- Set Root Component = BlogView and click Done
i. If you don’t see BlogView as a choice, you probably defined canBeRoot as an instance method. Oops!
-
- Click your new seasideBlog link and confirm that you see “Hello world!”
- Create a BlogPost class, subclassing Object, with instance variables title, body, and comments.
- I don’t know what a Magritte description is, but whenever it asks, I tell it to create them.
- Create a BlogComment class, subclassing Object, with instance variables name and comment.
- Select name, right-click/selection/create accessors biz simple
- Select comment, right-click/selection/create accessors biz simple
- In BlogComment’s class method descriptionName, change priority to 10.
- In BlogComment’s class method descriptionComment, change priority to 20, and change MAStringDescription to MAMemoDescription
- BlogPost, (instance): create accessors biz simple for the 3 instance variables.
- Remove the “comments:” method but not “comments” (without the colon)
- Select class, delete descriptionComments,
- Change priority on descriptionTitle to 10
- Change priority on descriptionBody to 20, and change MAStringDescription to MAMemoDescription
- Still on BlogPost, create a database method category, and create a class method
repository
^repository ifNil:[repository := OrderedCollection new]
-
- When you accept, it will whine about repository. Tell it to create an instance variable.
- Alphabetize your method categories
- Insert the following into BlogPost’s descriptionTitle, just before beRequired:
addCondition: [:value | (BlogPost repository contains: [:each | each title = value]) not ]
labelled: 'Post with that title already exists';
- Select instance and BlogView and renderContentOn and make it’s body look like:
renderContentOn: html BlogPost repository reversed do: [:eachPost | html div: [html heading: eachPost title level: 2; text: eachPost body. html div: [html bold: 'Comments'. eachPost comments do: [:eachComment | html heading: eachComment name level: 4; text: eachComment comment]]]]. html anchor on: #newPost of: self <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a method:</li></ol> newPost | post |post := self call: (BlogPost new asComponent addValidatedForm; yourself ). post ifNotNil: [BlogPost repository add: post] <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Back in your browser: <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh your browser and add a new post (making some sample mistakes along the way). Click Save.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Whoops! We have an error. Click the link for Debug and the debugger opens in Squeak.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">We can see where the problem is, so close the debugger and go to BlogPost’s comments method, and change the body to “ ^comments ifNil: [comments := OrderedCollection new]”</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh your browser and view your new post.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Try and create a posting with the same title. Can’t do that! Change the title and save it.</li></ol></li><li class="MsoNormal" style="margin: 0in 0in 0pt">Select BlogView, renderContentOn, and make it look like this:</li></ol> renderContentOn: html BlogPost repository reversed do: [:eachPost | html div: [html heading: eachPost title level: 2; text: eachPost body. html div: [html bold: 'Comments'. eachPost comments do: [:eachComment | html heading: eachComment name level: 4; text: eachComment comment]]. (html anchor) callback:[self addCommentTo: eachPost]; text: 'Add Comment']]. <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Back to your browser:<ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Refresh</li></ol></li><li class="MsoNormal" style="margin: 0in 0in 0pt">Create addCommentTo:</li></ol> <p style="margin: 0in 0in 0pt" class="MsoNormal">addCommentTo: aPost</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> | comment |</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> comment := self call: (BlogComment new asComponent addValidatedForm ; yourself).</p><p style="margin: 0in 0in 0pt" class="MsoNormal"> comment ifNotNil: [aPost comments add: comment]</p> <ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">Create a new method category named actions, and move addCommentTo and newPost into it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Back to your browser<ol style="margin-top: 0in"><li class="MsoNormal" style="margin: 0in 0in 0pt">New session</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a comment and save it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add a second comment and save it.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Add and save one final posting.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Turn halos on. Click on S for source.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">Click on configure and set it to deployment mode.</li><li class="MsoNormal" style="margin: 0in 0in 0pt">With a new session, no more development tools available.</li></ol></li></ol>