Tuesday, May 24, 2011

Boolean behavior

So I finally found a (pretty good) tutorial to build the To-Do list application. This one is still a couple years out of date, but I was able to figure out how to do most of what it describes.

This tutorial also mentions the nifty-generators gem, which just applies some basic CSS so you don't just end up with the standard black and white view. It's neat, but I'll still end up doing most of my own styling on more finished applications. (CSS is, after all, my first love)

However, I ran into a problem when trying to get rails to generate a nifty-layout. The solution was to manually add nifty-generators to the gemfile list. Easy enough!

So I ended up with three columns: name:string, description:text and finished:boolean. I've never used a boolean field before, and I did not find the standard issue true/false states satisfactory. Another google search gave me the code to edit this to a more user-friendly yes/no.

This was simply a matter of updating the view. I went from this:

<p>
  <b>Finished:</b>
  <%= @task.finished? %>
</p>


To this:

<p>
  <b>Finished:</b>
  <%= @task.finished? ? 'Yes' : 'No' %>
</p>


Aww shit, who is the dude so rad he uses a ternary operator? (Side note: I should probably brush up some more on my Ruby. But Rails is SO HOT right now!) I also updated this in the edit file, mostly for consistency.

However, I still want to be able to check or uncheck a task as "Finished," and have that change reflected in the database and displayed on the view, as well. I'm sure this is easy enough to do, but I haven't found quite what I'm looking for yet. I haven't been able to convert the old code the tutorial provides into code that makes more sense to me yet.

I also added some validation to the Tasks model. First, a task must at least have a name, right? Description should be optional, so I won't require that. How much description does "Take out the trash" really need? I also think a task is unique, so I am validating for that, as well. I also figured it makes sense for the name and description to have character limits, mostly to keep the view tidier. And here's my Task model:

class Task < ActiveRecord::Base   validates_presence_of :name   validates_uniqueness_of :name   validates_length_of :name, :maximum=>30
  validates_length_of :description, :maximum=>100
end

And that's about it. I spent about an hour working on this, of which about 15 minutes was generating working code, 15 minutes was googling for more information and 30 minutes was spent trying to figure out how to get that boolean field to behave.

4 comments:

  1. Sounding like real programming over there, you are getting fast! :)

    You might even break out the yes/no stuff into a helper

    def yes_no(value)
    value ? 'Yes' : 'No'
    end

    Or even more abstract:

    def yes_no(value, yes = 'Yes', no = 'No')
    value ? yes : no
    end

    yes_no(true) # => Yes
    yes_no(false) # => No
    yes_no(true, 'aww yeah', 'heckynaw') # => 'aww yeah'

    Not entirely sure what you mean by "uncheck a task as finished and have it reflected in the database" since it presumably would use the same method you used to mark it as done.

    Probably dangerous to unique tasks since perhaps you had a task for Take out the trash last week that you completed, and need to do it again this week!

    ReplyDelete
  2. Yeah, I think taking a break from larger scale projects has been good for me. I really do think I'm getting the hang of Rails now.

    Helpers are something I'm going to need to do some work with so I can understand them. Might look into that tomorrow!

    What I mean by "uncheck a task..." is for users to be able to mark a task as finished from the View and have that update. As it stands, my view just shows Task, Description and Completed? with no way to change the status of Completed? I have an idea of what I need to do, but haven't spent much time trying to hammer this out.

    I might need to rethink unique tasks. I could set up repeating tasks, but making tasks non-unique is definitely an easier and more flexible way of doing things. I don't have a sound reason for making it unique, anyway.

    ReplyDelete
  3. So you want to be able to make a completed task incomplete and vice versa? Then you need a form.

    <% form_for @task do |f| %>
    <%= f.check_box :finished %>
    <%= f.submit 'Save' %>
    <% end %>

    ReplyDelete
  4. @David I have a form that creates a new task. Would this code go into that form, or is it a new form? If it's a new form, what's the correct way to call it?

    I put the code you posted into the task form, but it only shows up when creating a new task or editing a task. I want to have this in the view, maybe with a flash that says "Task marked as finished" etc.

    I tried making a new form called _finished, with the code you posted and then calling it from the Task view, but that didn't work.

    ReplyDelete