In this part of the tutorial, we’ll make it so the interface and presentation of the blog are not so clumsy.
First thing to do is remove the body_html field from the Entry form. Open app/views/taglibs/application.dryml and add the following:
<extend tag="form" for="Entry">
<old-form merge>
<field-list: fields="name, body_markdown"/>
</old-form>
</extend>
DRYML is powerful, but very complex. It takes a bit of time to understand it. The part that makes the changes is the <field-list: fields="name, body_markdown"/>. The <old-form merge> tells Hobo to only merge the changes I describe into the existing form. So how do I know what the existing form looks like? It took me a while to figure this out because it isn’t in Hobo’s documentation at the time of this post. If you look near the top of app/views/taglibs/application.dryml, you’ll see these lines:
<include src="taglibs/auto/rapid/cards"/>
<include src="taglibs/auto/rapid/pages"/>
<include src="taglibs/auto/rapid/forms"/>
Every time the server is booted, Hobo automatically creates three files for us, based on our model and controller. These are located in app/views/taglibs/auto/rapid/. If you open up the forms.dryml in this directory, then you’ll see the form automatically created for Entry. It looks something like this:
<def tag="form" for="Entry">
<form merge param="default">
<error-messages param/>
<field-list fields="name, body_markdown, body_html" param/>
<div param="actions">
<submit label="#{ht 'entries.actions.save', :default=>['Save']}" param/>
<or-cancel param="cancel"/>
</div>
</form>
</def>
Notice the <field-list>? Any element with a param attribute can be accessed later by appending a colon to the tag name, like we did with field-list:. Pretty slick, right? Let’s add some helpful text to the form for those who don’t know markdown by heart. Let’s also change the label of the name field to be Title and body_markdown to be Body. We do this in a file called app/viewhints/entry_hints.rb. Make the file resemble this:
class EntryHints < Hobo::ViewHints
field_names :name => "Title", :body_markdown => "Body"
field_help :body_markdown => '
Supports markdown formatting<br/>
*emphasized* = <em>emphasized</em><br />
**strong** = <strong>strong</strong><br />
[Developer\'s Blog](http://hobo.tylerlesmann.com/) =
<a href="http://hobo.tylerlesmann.com/">Developer\'s Blog</a><br />
Go <a href="http://daringfireball.net/projects/markdown/syntax">here</a>
for more information.'
end
Pretty easy when you know where to put it. Let’s alter how our posts are displayed in a list. The abbreviated version of any model instance, like an Entry, is known as a card in Hobo. Let’s have the card for Entry display the created_at date. Open up app/views/taglibs/application.dryml again and append this content:
<extend tag="card" for="Entry">
<old-card merge>
<body:>
Posted on <view:created-at/>
</body:>
</old-card>
</extend>
Looks a bit similar to the form we changed earlier. Here we are replacing the body of the card. The <view:created-at/> element will do a few things for us. Depending on the field type, the content will be escaped. It also will format the field for us, like here with the created_at datetime field. Also, make note that all underscores in fields become hyphens in DRYML. You might notice a lot of content in ending up in this application.dryml. You should consider using includes to organize it, like those used by the automatically generated tags, cards, and forms. One last thing to do. Let’s change the way the Entry is viewed. Readers don’t need to see the body_markdown field or the field labels. They only need the HTML version of the post. Create a new file at app/views/entries/show.dryml with the following content:
<show-page>
<append-content-header:>
Posted on <view:created-at/>
</append-content-header:>
<field-list: replace>
<view:body_html/>
</field-list:>
</show-page>
Getting an idea of how DRYML works? Since body_html is an html field, it will not be escaped. See the <append-content-header:>? Hobo, like Rails and Ruby, has loads of magic. By slapping append- or prepend- in front of the tag, we can add content within that element. You can replace a tag and its content by adding the replace attribute, like here with the <field-list: replace>. It’s starting to come together.
Next up is tagging support.