Peter Michaux wrote:> When I first watched it I thought a transcript would be nice since the
> video is sooooo freakin'' fast:)
Not a transcript of the soundtrack (Whoops!), but these are the steps
being demonstrated, with some notes in []:
In terminal session in ~/demos directory
$ rails brablog
$ cd brablog
$ ./script/server
[don''t really need ./ in front of any script/xxx commands]
copy URL to Safari, see Congrats page
In a new terminal session
$ cd demos/brablog
$ e .
[opens the directory in TextMate - ''mate'' is the usual
command]
$ ./script/generate controller
$ ./script/generate controller blog
Open app/controllers/blog_controller.rb in TextMate
browse http://0.0.0.0:3000/blog
...no action responded to index
In blog_controller.rb, add
def index
render :text => "Hello World!"
end
Refresh brower - see "Hello World!"
Remove "render :text" line from controller
Create new file index.rhtml in app/views/blog,
containing:
hello from the template
Refresh browser - see "hello from the template"
remove action method completely, refresh browser - still works
Edit config/database.yml
development:
adapter: mysql
database: blog_development
username: root
password:
test:
adapter: mysql
database: blog_test
username: root
password:
production:
development
In CocoaMySQL, connected as root@localhost,
create new database: blog_development
create new table: posts
(structure tab)
fields:
id int not null auto_increment primary key
title varchar(255)
[table type should be InnoDB]
Restart WEBrick in first terminal session
Back in second terminal,
$ ./script generate model
(see the help for this generator)
$ ./script/generate model Post
In TextMate, show app/models/post.rb
then edit blog_controller.rb, adding:
scaffold :post
Refresh browser - see Listing posts page
New post "Hello Brazil!"
Show
Edit
(don''t save)
In CocoaMySQL, add a field named ''body'' with type text.
(click off the row to save the change)
Refresh browser - see the body text area
Enter "Yes, yes, hello indeed!" and click Update
Edit (don''t save)
In CocoaMySQL, add a field name ''created_at'' with type
datetime.
(click off the row to save the change)
Refresh browser - see the date/time selectors - want to move them above
the body - return to CocoaMySQL, and drag the created_at field above the
body field.
Refresh browser. Change the seconds, click Update.
Back to list
New post (don''t enter anything yet)
In TextMate, in app/models/post.rb, add
validates_presence_of :title
in browser, click Create - see validation error
[I don''t see style on error summary; do see red border on field.]
Put in title: "Better fill it in, then!"
Put in body: "Aye, aye, sir"
click Create - ok
In terminal,
$ ./script/generate scaffold
(see help)
$ ./script/generate scaffold Post Blog
(answer ''a'' to the prompt about overwriting
blog_controller.rb)
Refresh the browser - still see list of posts.
In TextMate, show all the new methods in blog_controller.rb
Fold them all (shift-command-2 toggles folding at level 2)
Open app/views/blog/list.rhtml, and change it to:
<h1>My wonderful weblog</h1>
<% for post in @posts %>
<div>
<h2><%= link_to post.title, :action =>
''show'', :id => post %></h2>
<p><%= post.body %></p>
<p><small>
<%= post.created_at.to_s(:long)%>
(<%= link_to ''Edit'', :action =>
''edit'', :id => post %>)
</small></p>
</div>
<% end %>
<%= link_to ''New post'', :action =>
''new'' %>
[should escape user-entered text with h()]
Refresh the browser - looks good.
Show that the show and edit functionality is still the same.
New post,
title "Let''s just add a third, for good measure"
body "Oh yeah"
Create - see the list.
We want the latest post to be at the top.
[Note that the app is depending on order of records retrieved,
with no ORDER BY in the SQL]
In app/views/blog/list.rhtml change the for loop to be
<% for post in @posts.reverse %>
Refresh the browser
Edit the "Better fill it in, then!" post, changing the body
to "Aye, *aye*, _sir_"
click Edit
In app/views/blog/list.rhtml change
<p><%= post.body %></p>
to
<p><%= textilize(post.body) %></p>
Now we want to use the same formatting in show and in list...
In app/controllers/blog_controller.rb, edit the list method to be
def list
@posts = Post.find(:all)
end
[could put ordering by created_at here]
In app/views/blog/list.rhtml select the whole div within the for loop,
cut it, paste it into a new file app/views/blog/_post.rhtml, then save.
Back in app/views/blog/list.rhtml, replace the now-empty for loop by
<%= render :partial => "post", :collection => @posts.reverse
%>
Now edit app/views/blog/show.rhtml. Delete the for loop and
replace it with
<%= render :partial => "post", :object => @post %>
In the browser, show the "Better fill it in, then!" comment.
[Note - the partial includes show and edit links - don''t need
the other edit link at the bottom]
Now implement comments on posts:
In the terminal,
$ ./script/generate model Comment
In app/models/comment.rb, add
belongs_to :post
In app/models/post.rb, add
has_many :comments
In CocoaMySQL, create table ''comments'' with fields
id int auto_increment primary key
body text
post_id int
In the Contents tab, populate a row with post_id 1, and body
"Yes, I agree with the hello!"
In app/views/blog/show.rhtml, at the bottom, add
<% for comment in @post.comments %>
<%= comment.body %>
<hr/>
<% end %>
Browse to show this item, see that the comment is there, but it''s
displayed right after the Back link.
In app/views/blog/show.rhtml, after the Back link, add
<h2>Comments</h2>
Check in browser. Now we need to be able to add comments.
In app/views/blog/show.rhtml, at the bottom, add
<%= form_tag :action => ''comment'', :id => @post %>
<%= text_area "comment", "body" %><br/>
<%= submit_tag "Comment!"%>
</form>
Check that this displays in the browser, then come back and
wire it into the application:
In the controller, add
def comment
Post.find(params[:id]).comments.create(params[:comment])
flash[:notice] = "Added your comment."
redirect_to :action => "show", :id => params[:id]
end
Refresh the browser, then add a comment "Me too, me too!"
Go back to the list.
Now look at the statistics for this project: in the terminal
$ rake stats
Look at the log:
$ tail -f log/development.log
Show the log updating as a post is shown in the browser.
In CocoaMySQL, create database ''blog_test''.
In the terminal, Ctrl-C out of tail, then
$ rake test_units
See tests run, 2 tests, 2 assertions, 0 failures, 0 errors
Put in a real test: in test/unit/post_test.rb, add setup method
[was already there in movie, not in Rails 1.0]
def setup
@post = Post.find(1)
end
and replace the test_truth method with:
def test_adding_comment
@post.comments.create :body => "My new comment"
@post.reload
@assert_equal 1, @post.comments.size
end
$ rake test_units succeeds
Break the test, by comparing with 2 rather than 1 - see the test fail:
1) Failure:
test_adding_comments(PostTest) [./test/unit/post_test.rb:13]:
<2> expected but was
<1>.
Now look at the console:
$ ./script/console
Loading development environment
>> p = Post.find :first
=> #<Post:0x245d12c @attributes={"title"=>"Hello
Brazil!", "body"=>"Yes,
yes, hello indeed!", "id"=>"1",
"created_at"=>"2005-06-02 20:43:00"}>
>> p.title = "Hello Denmark!"
=> "Hello Denmark!"
>> p.save
=> true
Look at the list in the browser - see the change.
Back in the console:
>> p.comments.create :body => "Greeting to the cold north"
=> #<Comment:0x244813c @attributes={"body"=>"Greeting to
the cold
north", ...>
>> p.comments.create :body => "Greeting to the super, super cold
north"
=> #<Comment:0x243ee20 @attributes={"body"=>"Greeting to
the super,
super...>
>> p.comments
=> [#<Comment:0x2446af8 @attributes={"body"=>"Yes, I
agree with the
hello"...>]
Look at the list in the browser, show the Hello Denmark! post,
and see the comments.
Back in the console:
>> p.destroy
=> #<Post:0x229bbcc @attributes={"body"=>"Yes, >
[structure here is different from that in the movie]
Look at the list in the browser - the post has gone.
[But looking in CocoaMySQL, the comments haven''t.]
that''s it!
regards
Justin