Monday, June 27, 2011

Session Counter in Rails

Since I've been working through Agile Web Development with Rails, I've felt less like blogging about what I'm doing. It's not that I don't find this book valuable, but I'm less excited about talking about my progress than when I'm working on a personal project. Still, I haven't been slacking in my coding.

I've had a lot of luck translating things I'm learning into methods that work with my other projects (mostly just Chorenivore) and this time through Agile Web Development, I'm doing all the extra stuff. Tonight I learned a method for displaying how many times a user has viewed the index page, as well as a way to reset the session counter and how to change how often it's displayed.

I'm guessing this is the same sort of thing that's used to track how often things are viewed online, right? With some editing, this method could be used on a photo blog to show how many views a particular photo has had, etc. You see how things are coming together?

I've also been using github extensively, mostly just to record what I've done and as a means of source control. Much like firing up the terminal and booting up webrick, I no longer have to think about how to commit changes and push to git. Memorization isn't learning, but it can definitely make learning easier.

Wednesday, June 22, 2011

Rails Validation Syntax

Tonight while working through Agile Web Development with Rails, I was finishing up Chapter 7 and doing some of the extra stuff at the end. One of the exercises was adding validation to the Product model that checks the length of product titles is at least 10 characters.

No big deal! I fired up Rails API and found what I was looking for.

validates_length_of :title, :minimum => 10, :message => 'must be at least 10 characters.'


Ahh, perfect! Plus, editing the default message is the second optional exercise. Easy enough. But wait, what's this?

The book had me write validation like so:

validates :price, :numericality => {:greater_than_or_equal_to => 0.01}, :message => 'must be a number.'


This is a slightly different syntax than the validation I found on the Rails API and I don't like it as much. First, it's not as immediately obvious what this validation is doing. Second, it just feels clunkier. So since I'd already written a validation method in a different syntax, I figured this would do the same thing and be in a more readable format:

validates_numericality_of :price, :greater_than_or_equal_to => 0.01, :message => 'must be a number.'


And what do you know? It works! Is there anything I should be aware of when writing validation like this? Any ideas why Agile Web Development with Rails wrote it the other way? Personal preference of the programmer, perhaps? I'm assuming this is a standard way of writing validation, both because it's the same syntax I found on the Rails API, and because it's more readable. (It's also 5 characters shorter, but who's counting? A piece of Javascript I found online, that's who!)

Ahh, feels good to be making progress. I got hung up for a bit writing tests in the last chapter, until I realized I'd added a stray period and it was holding everything up. Anyone else try running test:unites by mistake? I've probably done it 3 or 5 times in the last 18 hours.

Sunday, June 19, 2011

Creating a new application with an older version of Rails

This weekend, I've been working through Agile Web Development with Rails, but I ran into a problem. The book is using Rails version 3.0.5, and I've been updated to Rails 3.1.0.rc2. Some things have been changed from Rails 3.0 to Rails 3.1. Most of these appear to be small, easy to work with changes such as moving images and stylesheets from /public to /assets, but Jquery is the new default javascript library for Rails and this is where I ran into trouble.

First off, I noticed the CSS wasn't working exactly as it did the first time I went through Agile Web Development with Rails. Mostly some minor issues that I was able to work with, and this wasn't that big a deal, since styling is best left until later. But the book deals with some styling up front, so this issue threw a red flag.

Next up, I noticed my :destroy method wasn't working. I ran into this issue a couple weeks ago with Chorenivore, and it was a matter of configuring Jquery. So I tried the fix that worked for me before, but I'm not sure why it wasn't working with a Rails 3.1 app. Is there more configuration needed? I generated the code with a scaffold command, so I'm not sure why it wasn't working by default.

At any rate, whether this is a bug (doubtful, even though this is a beta version of Rails 3.1) or I just didn't configure everything correctly, I decided the best solution for now is to create a new application using the same version used in Agile Web Development with Rails.

So the command for creating a new application with a previous version of Rails is easy enough:

rails _3.0.5_ new depot

In this case, I want to use Rails 3.0.5 and my project is named depot, so that's all there is to it! I think the gemfile may need to be edited as well, but so far I haven't run into any issues.

Rails is a framework that is updated and changed regularly, so I know in the long term I'll want to stay current with new versions. But for now, it's more important for me to keep learning and reinforcing what I already know, so using an older version of Rails is the way to go.

Saturday, June 18, 2011

Applying Tutorial Methods to My Own Rails Projects

So even though I picked Agile Web Development with Rails back up the other day (after about 2 months away from it) I decided to start the entire book over again. I don't typically like doing this, but I felt my reasoning was sound. For one thing, going back through building the shopping cart application would make more sense to me now, since I'm thinking about how Rails applications work and not just making sure I'm following the tutorial correctly so I don't get errors. For another, I was pretty sure I could find some techniques I could apply to my personal projects. Lastly, the first time around I skipped all the optional coding at the end of every section and this time I'm going to do it. I'm more interested in learning new ideas than in making this one specific application work correctly.

On this last part I was correct. I just went through the beginning part, which walks me through generating a scaffold for the project, then some styling to spruce the code up a bit and I already found a couple of ideas I want to apply to Chorenivore.

This is something I need to be doing every time I'm doing a tutorial or looking at code. What can I do with this? How does this apply to my projects?

Something funny I noticed this morning: back when I was learning CSS, I had a hard time understanding what a class was. And now with Rails, it's something I don't even think about. I don't know if I've just seen it often enough that I get it now, or if Rails has so many other things that are more complex that it just doesn't register. Probably a mixture of both, I'm guessing!

I felt a bit lazier this week, because I feel like Chorenivore is about as done as it's going to be for now and I didn't feel like digging back into Agile Web Development with Rails. What do you guys do to stay motivated when you're between projects like this? Does that even happen to more experienced Rails developers?

Oh and one last thing. Eli emailed me asking what happened to my old blog. I didn't realize switching from rubymeltdown.blogspot.com to codeitlikeyoustoleit.blogspot.com would DESTROY all my followers, so I put another blog up on rubymeltdown.blogspot.com, redirecting people to this blog. That should take care of that problem!

Tuesday, June 14, 2011

Using Rails console to add a user to a database

It became apparent to me last week that pretty soon I'd need to go back and finish working on Depot, the shopping cart application I was building by following along with Agile Web Development with Rails. I got off track a while back because I'd forgotten to create a user, then continued on with the guide until I got to a point that I needed to log in. Uh oh!

Unfortunately, what I didn't realize is that the very next page after I'd left off walked me through using Rails console to add a user. Still, it's not like I've been lax in the two months since I looked at this program, right?

So now I'm back on track. Right now I'm working on translation to different languages based on location. Interesting, though I don't know how practical this will be. My current plan is to finish up this book, mostly because I'm kind of sick of hopping around between projects. Then again, when is a project ever really done? Hopefully inspirato will strike between now and then and I'll either think of something new to do with Chorenivore, get back to work on Manticore, or create another app! I actually might go back and do more work with Ruby itself. I've been on that Rails tip for a while now.

Remember when I said I think more about what the code is doing when I follow a guide now? Completely true. While backtracking through Agile Web Development with Rails, trying to figure out where I'd left off, I found myself thinking about the code as I worked. Digging around in the deep, smelly guts of a Rails application isn't as intimidating as it once was. Sometimes I feel like I'm progressing really slowly, while other times I'm amazed at how far I've come in the nearly 5 months I've been working with Ruby on Rails.

Bruce Lee said "A man must constantly exceed his level." Does anyone else read that and immediately apply it to Rails?

Constantly leveling up.

Sunday, June 12, 2011

Fixing the delete method in Jquery

Here's a little problem I ran into the other day. I've switched to Jquery from Prototype, and while I was initially able to get Javascript working with Jquery, my :delete method stopped working. Rather than destroying the thing it was called to destroy, it redirected me to the show page.

After a few google searches, I found this is a fairly common problem. However, none of the solutions I found fixed my problem entirely, but a combination of suggestions DID fix the problem.

I'd installed the jquery gem, as suggested here but the problem was in the javascript_includ_tag in the header of my application.html.erb file.

At first I had <%= javascript_include_tag :defaults %>, which I assumed would work since Jquery was the new default Javascript library after installing the gem, but I had to edit it like so:

<%= javascript_include_tag :defaults, 'jquery_ujs' %>

Bingo! Once again, my :delete method works, and my flash[:notice] script is working, too.

Now for a little question.

You may recall my previous question about passing multiple values to a hidden_field. David showed me this code:

  def status
    finished? ? 'finished' : 'unfinished'
  end
end


This goes in the Task model and defines these two statuses. However, I don't know how to call them and mark a Task as finished or unfinished then have that change updated in the view.

Here's the code I've got now:

<%= form_for(task) do |f| %>
  <%= f.hidden_field :finished, :value => !task.finished %>
  <div class="actions">
    <% if task.finished %>
      <%= image_submit_tag 'finished.png' %>
    <% else %>
      <%= image_submit_tag 'unfinished.png' %>
  <% end %>


Basically, I want it to work this way: A new Task is defined as unfinished by default, a user can mark a task as finished by clicking on 'unfinished.png', or mark it as unfinished again by clicking on 'finished.png'. This change should mark the Task with that status, either 'finished' or 'unfinished.'

Will I need to update the table for Task and add this as a field? Or can this information be stored in the database just by using the hidden_field? I want to be able to manipulate Tasks based on whether they're marked as finished or unfinished later.

I didn't do much coding this weekend, but it definitely felt good to sit down and fix my Jquery problem after thinking about it most of the day today.

Thursday, June 9, 2011

Working with Jquery in Rails

Still working on Chorenivore. After getting some help from Matt and David, I'm using some jquery for handling flash :notice messages. At first, I just wanted to make it so the :notice would fade away after a few seconds.

I initially tried this with some Prototype code David showed me, but couldn't get it to work for one reason or another. After a bit more digging (and prodding from both David and Matt) I decided I should just switch over to Jquery. Everything I've read says it's got a much wider development base than Prototype, and Rails 3.1 will be using it as the default javascript library, anyway. Might as well get used to it now!

Switching to Jquery from Prototype proved a bit tricky. Good thing I don't have tons and tons of code that had to be converted, huh? Here's a page I found that helped me:

Switching from Prototype to Jquery

Easy enough! This didn't take long to find (third page on a google search, but that's an eternity by today's standards) so I'm hoping it might help others out.

Anyway, back to Chorenivore! Here's the Jquery script Matt showed me that I modified and ended up using:

setTimeout(function() {
$('#flash_notice').fadeOut('slow');}, 800
);


I'm not super familiar with Javascript, but a couple of things made sense. 'slow' refers to how quickly the message fades away, and 800 refers to how long it stays on the screen. '#flash_notice' refers to every flash[:notice] and this could just as easily be applied to flash[:error] or flash[:alert]. It's funny how becoming familiar with one coding language makes others easier to read and manipulate.

After I got this script running, I decided I didn't want my flash:notice running across the top of the application. I pulled that code out of application.html.erb, threw it into index.html.erb, slapped a div on it and called it macaroni! Problem solved. It feels AWESOME to mark things off the functionality and features checklist I made for Chorenivore.

Now, how about a couple of questions? You ready?

Here's the code I've got for updating whether a task is finished or not.

<%= form_for(task) do |f| %>
  <%= f.hidden_field :finished, :value => !task.finished %>
  <div class="actions">
    <% if task.finished %>
      <%= image_submit_tag 'finished.png' %>
    <% else %>
      <%= image_submit_tag 'unfinished.png' %>
  <% end %>


Is there a way to pass multiple values to a hidden_field? Right now, I can define a task as finished, but there's no definition for being unfinished. It's just displaying the unfinished button if a task is not marked as finished. I'd like to do this so I can define custom flash :notice messages for when a task is marked as finished from unfinished and vice versa.

I had lunch with Eli today and it's always great to talk to programmers about programming. I find the fact that I've signed up for a never ending stream of headaches, frustrations and triumphs oddly comforting. This is that coding crack I've heard so much about, right?