Today, the ‘show’ page

July 19, 2007

Going to focus on the ‘show’ page today – the main page where an article is displayed along with all of its comments, stories and links. I already did an html mockup for this, so it should just be a case of plugging in the body of my mockup, and replacing all the hard-coded content with ruby code to generate the content.

I solved the mystery of why my methods in the model weren’t working. It seems that if you want to access the instance variables of an object you need to do it via ‘self’. Ie if you want the title you have to write


This seems weird to me – i’d have thought :title or @title would work. There are examples in the book i got yesterday (Agile web development with Rails) where in the model code they use :variable_name.

OK, reading the book some more, it seems like the situation is this. Attributes that live in the database aren’t really a part of the ruby model schema – they’re determined at runtime. So, we don’t have an instance variable called @title, because title could be removed from the database. However, at runtime we can look for title, and we do this with self.title. We can have instance variables that aren’t in the database, (but for example are derived from the database) and it’s probably these that the book examples are referencing.

I’d really like to read through this book, but i don’t have time (it’s pretty thick). Maybe i’ll start doing a couple of hours of the book in the morning and then the project in the afternoon.

Had an idea while watching aleks surf inside the iframe – i should have a button/link for ‘add this page to newspipe’ on the show page. I’d also like to change the ‘new page’ code so that the user only has to enter the link, and the title is picked up automatically from the page title.

OK – just did a few things and forgot to blog them:

Removed the datetime field from the form, since it’s generated automatically. This meant that i had to add a line to the controller ‘create’ action to set added_at to the current date and time. I was struggling with this yesterday for some reason but it’s pretty simple – i think i was missing out the to_s part:
@article.added_at =

Got the create page to automatically generate the title, if the user doesn’t enter a title themselves. It does this by using hpricot to find the title element, and then get the content.
@article.title = (Hpricot(open(@article.url))/”title”).first.inner_html

Problem: If the internet connection disappears, the action can’t retrive a title and the app crashes. I need to handle this more gracefully – maybe testing if it can be retrieved in the model before saving it to the database. BTW, “show”, because it puts the web page in an iframe, handles the lack of connection a bit better – it has the firefox “can’t find this page” window in the iframe but everything else works.

Added a bit of explanation text about this to the create page. It’s a bit unreliable at the moment, because some pages generate their title on the fly, so what i pull out is something like “HTML HR TAG”. I need some way to get the actual current title of a page. Asked on a forum.

Next, since the user can browse in the iframe on the show page, i want to add the option to the show page to add the current page to newspipe. I’m not sure of the best way to do this though: i think it would be to open another page with the create form on it, with the url filled in already. When the user submits, the form window closes, instead of taking them to the list page like with the “new article” page.

OK – got the user content in, with no stories, comments or links. Next step is to create the classes to go with the comments etc. Going to do comments first.

Following the exact same steps as with the blog app: generate model Comment, then add the relationship data to the Comment and Article class. Initially a post just has a body, it doesn’t have a user id yet. OK, comments are showing up fine, except that the style is wrong – that’s because i don’t have a stylesheet! Added format.css (copied over from my mockup page) into newspipe/public, and then told rails to look for it by adding it to the line in \views\layouts\newspipe.rhtml:

<%= stylesheet_link_tag ‘scaffold’ %>

so that the line now reads

<%= stylesheet_link_tag ‘scaffold’, ‘format’ %>

Next, i think i need to set up the User model. I’m going to follow this tutorial i found on the net (the book one’s not so good as it’s half way through and part of a massive tutorial and it’s hard coming in halfway through to see what’s a reference to something else in the tutorial app and what’s a standard rails command).

The tutorial uses a database migration to set the db up, instead of doing it by hand (as i’ve been doing) or by using an sql script (as the onlamp tutorial did). I had a slight problem with this – when i did the previous tables i did them by hand, ignoring the rails-generated create_comments.rb etc. But, when you migrate you can only run all of them, it seems, so i had to delete the ones for comments and articles (which feels kind of dirty).   You run the db creation script with

rake db:migrate

Just learnt a nice little titbit – instead of saying (for example)

if @article.comments != nil

you can use the built in method comments? which returns true if it isn’t nil. So the above could be

if @article.comments?

There’s also the method ‘nil’, so the above could again be rewritten as

if !@article.comments.nil?

This is probably more tidy in the reverse test, ie when you’re testing if it is nil rather than if it isn’t.

Hit a snag when working through the tutorial – it uses the rake stuff a lot, and because i’d set my db up by hand i was having problems. So, i set up create_db files for the articles and comments tables, deleted the old ones, and created them again using the rake. This worked, and of course had the side effect of emptying out all my tables. I added a couple of articles using the newspipe interface, which was a valuable test as i discovered that

a) a new article wasn’t being given any points when created (fixed that, all awarded 1 now. Ideally, it should test if an article is already there and if so then give it another point, but that will have to wait).

b) the above was breaking the sorting, since it uses points. Fixing a) fixed b) as well, but it did remind me that if two articles have the same points then it should sort by added_at. Fixed this:

<% for article in @articles.sort{ |a,b|
if b.points = a.points
b.added_at <=> a.added_at
b.points <=> a.points
end } %>

There was something strange with this though: if i say

return b.added_at <=> a.added_at

Then the page will display the result of this test and nothing else. Removing the returns makes it work fine. I don’t get this though – surely it’s returned anyway, out of the code block to the sort method?

Anyway – on with the user login stuff!

Hit another snag – got onto unit testing and a test is failing because one of the methods is calling a static method of a class called “Notifications”, which when it runs is complaining that there’s no such constant. No idea what this does, or where it is or anything. Goddammit. The only place its used is in the method to send someone a new password if they’ve forgotten their old one so i can ignore it for now. AH WAIT! Just read that the Notifications class will be done later. So this is TDD – write a test then write the code to pass the test. But only for one test, the rest pass. Anyway.

Next we make the controller for the user stuff, with this command: it looks like we can specify a list of method names and rails will create stubs for the methods.

ruby script/generate controller User signup login logout delete edit forgot_password

Not just methods! The words that follow ‘User’ also create a load of view pages! Handy. The delete and edit methods don’t seem to be necessary so i deleted them from the controller.

TBC tomorrow…


Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: