Make a Blog with Hobo: Theming

Posted by Tyler Lesmann on September 03, 2010 15:25
Tags: DRYML, Hobo, Tutorial
0 Comments

It took me awhile to figure out how Hobo’s theming engine works. It’s not hard to create and use a new theme if you know the caveats.

We’ll start by using hobo’s default theme, clean, as a template. Go into RAILS_ROOT/app/views/taglibs/themes. You will see a directory called clean. Inside this directory is a single file called clean.dryml. You’ll want to pick a name for your theme. For this example, my new theme will be called red. Create a new directory called red and copy clean/clean.dryml to red/red.dryml.

We do not need to make changes to red.dryml for it to work properly. This file is where you will define tags, cards, and forms specific to your theme. If you need to pull in some more javascript and css, this would be the place to do it.

Next, we need go to RAILS_ROOT/public/hobothemes. Again you will see a clean directory. Copy this directory to a new one, red. Go to stylesheets within the red directory. Rename clean.css to red.css. Now we have the media assets for our new theme all set up. So how do we use this new theme?

Open RAILS_ROOT/app/views/taglibs/application.dryml. You’ll see a tag early on called set-theme. Just change that to point to red.

<set-theme name="red"/>

If you are running your server, then restart now. Hobo will not load the new theme correctly otherwise. Now your blog its own theme!

Make a Blog with Hobo: Lifecycles

Posted by Tyler Lesmann on September 03, 2010 15:23
Tags: DRYML, Hobo, Tutorial
0 Comments

Sometimes we may want to not publish our blog entries to the world. They might need a little work, which we plan on doing later. So our entries need two states: published and drafted. Hobo’s lifecycles make this not too much of a chore.

First, let’s open app/models/entry.rb and define our lifecycle. These lines can go right after where we’ve defined our relations.

lifecycle do
  state :drafted, :default => true
  state :published

  transition :publish, {:drafted => :published}, :available_to => :user
  transition :unpublish, {:published => :drafted}, :available_to => :user
end

We’ve defined our two states. Our entries will default to the drafted state. There are also two transitions. Transitions define how our entry can change states. A entry can become drafted only when it is in the published state. The opposite is also true. Only the user, or author in this case, can change states. Now let’s migrate!

$ script/generate hobo_migration

States are now engaged, but we cannot change between them. We need to add some buttons. Hobo provides the extremely helpful <transition-buttons/> tag to accomplish this. Open app/views/taglibs/application.dryml and add this tag to our entry-info tag like so.

<def tag="entry-info">
  <div>
    Posted on <view:created-at/>
  </div>
  <div>
    Tags: <view:tags/>
  </div>
  <transition-buttons/>
</def>

You now have Publish and Unpublish buttons. The assortment of buttons depends on the transitions available to your current user. So we have our states and we can change between them. Now we just need to do something with those states. Let’s change the view permissions in app/models/entry.rb.

def view_permitted?(field)
  acting_user.administrator? or state == 'published'
end

Now an entry is viewable if the user is an adminstrator or if the entry is in a published state.

Make a Blog with Hobo: Commenting

Posted by Tyler Lesmann on February 18, 2010 00:35
Tags: DRYML, Hobo, Tutorial
0 Comments

It would be nice to allow our readers to leave a little feedback, so in this edition we’ll do just that. This should give you insight into how Hobo can present one-to-many relationships. Create a very simple model with the following:

$ script/generate hobo_model_resource comment body:text

Nothing you haven’t seen. Open app/models/comment.rb and alter it to be like this:

class Comment < ActiveRecord::Base

  hobo_model # Don't put anything above this

  fields do
    body :text
    timestamps
  end

  belongs_to :user, :creator => true
  belongs_to :entry

  # --- Permissions --- #

  def create_permitted?
    acting_user.signed_up?
  end

  def update_permitted?
    acting_user.administrator?
  end

  def destroy_permitted?
    acting_user.administrator?
  end

  def view_permitted?(field)
    true
  end

end

A few changes to note here. We’ve added two relations, one to the User model and another to the Entry model. The :creator flag automatically sets the user if one is not given. You should also note the change to the permissions. Any user that has signed up will be able to create new comments. Let’s add the relations to the Entry model. Put these lines after the fields in app/models/entry.rb:

belongs_to :user, :creator => true
has_many :comments, :dependent => :destroy

The relation to comments has been made and now each entry will have an author. Now for the User model. Add these lines to app/models/user.rb after the fields:

has_many :entries
has_many :comments

Go ahead and run a hobo_migration to apply the changes to the database.

$ script/generate hobo_migration

If you take a look at the blog now, you’ll find a very awkward setup. Comments can only be created from the Comments tab. Comments aren’t connected to entries in an obvious way. Let’s change that. First, open up app/viewhints/entry_hints.rb and add this before the final end:

children :comments

Comments related to an entry are now shown on the entry’s show page. Let’s make it so users can add comments from there as well. Open app/controllers/comments_controller.rb and change it to be like this:

class CommentsController < ApplicationController

  hobo_model_controller

  auto_actions :destroy
  auto_actions_for :entry, [:create]

end

The auto_actions are now limited to destroy, which will allow the administrators to easily remove comments. The auto_actions_for is very convenient. That one line allows users to make comments from the show page of an entry. Take a look. One problem you should notice is that the user relation is accessible. Users would be able to leave comments as anyone on the site. That’s no good. Open app/views/taglibs/application.dryml and append this to the end of it:

<extend tag="card" for="Comment">
  <old-card merge>
    <body:>
      <div>
        On <view:created_at/>, <a:user/> said:
      </div>
      <view:body/>
    </body:>
  </old-card>
</extend>

<extend tag="form" for="Comment">
  <old-form merge>
    <field-list: fields="body" without-body-label/>
  </old-form>
</extend>

We’ve made a prettier card for comments and the form has been trimmed to only display a field for body. Of course, that’s not enough to stop users from spoofing comments. Open app/controllers/comments_controller.rb and add this before the final end:

def create_for_entry
  # Remove user spoofing
  # Hobo should make this easier
  params["comment"].delete("user_id")
  hobo_create
end

Yep. Hobo allows you customize how controllers on related pages work. All that we’ve done is removed user_id from the params. Hobo will instead relate the comment to the creator as we defined earlier. You might consider doing something similar to this for entries as well. Since comments are related to users and entries are now related to users, let’s make the user show page more interesting. Create a new file at app/viewhints/user_hints.rb and add this content:

class UserHints < Hobo::ViewHints
  children :entries, :comments
end

The user show page now features entries and comments authored by the user. Your extra credit on this lesson is to make the card for Entry more presentable.

Entries by Tag