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?

Tuesday, June 7, 2011

Styling flash notices in Rails

So I've made some pretty good progress with Chorenivore the last couple of days. Last night I dug into CSS to clean up the view, mostly making sure that my <:th>'s and my <td>'s were lined up. It's kind of hard not to go nuts obsessing over padding and font size and palette choices. Save that for later, dummy! Work on your functionality first.

So sure, I have some questions.

Here's some code from my Tasks controller in Chorenivore:

respond_to do |format|
  if @task.update_attributes(params[:task])
    format.html { redirect_to(tasks_path, :notice => 'Task was successfully updated.') }
    format.xml { head :ok }
    format.html { render :action => "edit" }
    format.xml { render :xml => @task.errors, :status => :unprocessable_entity }

The problem is whenever a Task is updated (or created, or destroyed, etc) the :notice hangs around until the page is reloaded. I'd like to be able to make it disappear after a couple of seconds and style it using CSS. Back when I was working through Agile Web Development with Rails, I created a way to make this notice fade away after a few seconds using Ajax. The problem is, I haven't been able to duplicate it in Chorenivore.

A few questions about this:

First, is this :notice the same between methods? Is the :notice for creating a Task the same :notice for editing a Task? I'm sure there's a way to make this uniform.

Second, how do I do this? Is Ajax the best way? Should I use Javascript? I don't think reloading the entire page is the best way to handle this, and to my understanding Ajax doesn't reload the entire page.

I've seen a lot of references to flash[notice], is this the same thing as :notice, from the code I posted? Also, what does "flash" refer to in this instance? Does it mean Rails is FLASHING a notice, or that it's a notice Rails stores in the flash because it doesn't need to save it after it displays it? Could it be both? Or something else entirely?

Any recommended reading for understanding and working with Ajax/Javascript in Rails? I've read through the API and it's good for reference, but tutorials are my main jam. I'll look around for some on my own as well, but I figured some of you guys would know of some special favorites.

It's also becoming increasingly clear the time is right for me to go back to Agile Web Development with Rails, since I'm definitely thinking about things tutorials are having me do in a different way. Now it's more "What can I do with this?" and less "Am I getting the syntax exactly right so Rails won't complain and barf up a string of errors?"

One last thing: I've been really into Github, and while I feel I'm not using it as efficiently as I could, I really like being able to document and store my code as it progresses. I've been uploading new versions of Chorenivore every time I solve a problem or make an update. I don't know if that's how most Rails programmers use it, but it definitely adds to my feeling of accomplishment once I run that git push command.

Sunday, June 5, 2011

Rendering a different view using partials

Remember yesterday when I was talking about having a good day followed by a bad day with Rails? Looks like today is going to be a good day!

Something I've been wanting to do with Chorenivore is change the view so it only displays the information for a task (Done, Task, Description, Created) if there actually IS a task. Otherwise, this information shouldn't be displayed, right?

This morning I woke up with the idea of creating a couple of partials and then rendering them with an if else statement. So right away I got started. I broke out the code displayed in the view into 'yestask', then creating a partial called 'notask' that didn't display anything but a method for creating a new task.

Here's what I tried at first:

<% if @task.blank? %>
<%= render 'notask' %>
<% else %>
<%= render 'yestask' %>
<% end %>

This code doesn't throw an error, but it doesn't do what I want. In this case, it bypasses 'yestask' altogether and only renders 'notask'. I dug around in Tasks controller and realized I should be writing the code like so:

<% if @tasks.blank? %>
<%= render 'notask' %>
<% else %>
<%= render 'yestask' %>
<% end %>

I get why this version works, because it's checking if there are any instances of @task. I'm still not sure why just calling @task.blank? didn't work. Is it because @task is a method, while @tasks is defined in the controller as Task.all?

Definitely feels good to make some progress, even if I'm not 100% sure about why the method I tried first didn't work.

Another general question: Is using partials in this way a good practice? I kind of feel like I understand partials pretty well, so every problem appears to be something that can be solved with partials. There's a metaphor buried in there somewhere.