:::: MENU ::::

Fun with jqModal, flash, sending email and submission forms in Rails

As many of you may already know, Riding Resource has been up and running since January 1st, and we’re chugging right along. One thing we realized we wanted was to have people be able to send us their contact information to sign up for a mailing list.

Because we haven’t implemented anything like Constant Contact or Mailchimp, we just wanted a submission form to collect the information and receive it via email.  We didn’t want to require people to create an email themselves. Because we are anal retentive and want everything to look pretty, we also decided that it would be really nice to use modals to put the form in.

First step – using modals. Since Riding Resource already makes use of a good bit of jQuery and other jQuery plugins, I thought it would be rather easy to use a modal plugin for jQuery. Once such plugin happens to exist in jQmodal. Its usage is rather simple, but, in the case of Riding Resource, required a couple of tricks.

First, because of the way that Ruby on Rails works, I wanted to keep the modal for the submission form on the view for the action that would actually spawn the modal. Unfortunately, this caused a problem with Firefox 2 and the way the layers are handled. This was solved by using the “toTop” directive in the declaration of the modal. I also only wanted the modal to trigger when the links to sign up were clicked. This resulted in the following:

$('#mailing-modal').jqm({
  trigger: '.mailing',
  toTop: true
})

This brought up the modal just fine. But what to put in it? I had never built a contact form before, although I’ve obviously built some very complex forms. A quick Google search pointed me to this thread about just such a thing. A little bit of tweaking and I had built just the form I needed.

Unfortunately, I realized quickly that after the form was submitted, the user didn’t get any notification. Riding Resource had not had any need for Rails flash messages until this point, so what were we going to do with them? Since we were already using jqModal, why not continue in that trend? Popping up a friendly modal letting the user know their submission was received would surely do the trick. But this brought its own pitfall – how to make the modal only display when needed? The following snippet helped solve that problem:

$('#flashes').jqm({
  trigger: '#flashes'
});
<% if flash[:notice] || flash[:warning] || flash[:error] %>
  $('#flashes').jqmShow();
<% end %>

In this case, we are declaring that the #flashes div is a jqModal, and that it should only trigger on itself. This prevents it from popping up when other jqModal triggers are clicked (all modals will pop up by default). The second thing we did was force this modal to show only if the different flashes exist. The div for this looks like so:

<div id="flashes" class="jqmWindow">
  <%= display_standard_flashes %>
  <p><a href="#" class="jqmClose"><strong>Close</strong> X</a></p>
</div>

In case you’re wondering what display_standard_flashes is, it’s a handy helper that I happened to pick up from dZone here.

That’s pretty much all there was to it. While it took several hours to get all of this figured out, now that it’s done, it should be much easier to do submission forms using jqModal in the future.


Cleaning the sessions database store with a rake task in Rails

So, for one reason or another, I am using the built-in db store for sessions on the RidingResource site. I was about to embark on a path to utilizing sessions to help maintain the search selections across the site, and I noticed that the sessions database was full of… junk.

Rails is nice enough to provide us with a number of great built-in ways to handle sessions. Unfortunately, it is not nice enough to clean up after itself. I noticed that there is a built-in rake task (rake db:sessions:clear), but this actually just nukes the whole sessions table. Now, granted, I could run this as a cron at 4:00AM and it would probably not affect any users. But, I figured I should design a way to simply not affect any users regardless.

I found someone else who was trying to clean up session data and they figured out a MySQL query that works: DELETE FROM sessions WHERE updated_at < DATE_SUB(CURDATE(), INTERVAL 30 DAY); This will delete any sessions that haven’t been updated in 30 days. For our app, I decided that a 2-day interval is probably sufficient. The other cute benefit is that someone who comes back within two days will probably see their last search retained — that may or may not be desireable in the long run.

Since I had just written a rake task the other day to handle some stuff relating to paid advertisers and what not, I realized that I already had a tool that could (potentially) be used to process this MySQL query — rake. However, that required figuring out a way to run a MySQL query directly with rake.

Again, Rails to the rescue — it provides us with ActiveRecord::Base.connection.execute(sql). So, I created a rake task to do what was needed.

# clearing out sessions older than 2 days because we are using sessions to store
# search information to maintain the search preferences in the show action
desc "This task will delete sessions that have not been updated in 2 days."
task :clean_sessions => :environment do
  ActiveRecord::Base.connection.execute("DELETE FROM sessions WHERE updated_at < DATE_SUB(CURDATE(), INTERVAL 2 DAY);")
end

Combined with a cron job, this should work splendidly.


Actually handling blanking default form input values… in all browsers

The other day I wrote about needing to blank default values when text input fields gain focus in a form.  I had found a jQuery-based script that seemed to do the trick… or so I thought.

When RidingResource went beta, I was tailing the RoR logs and noticed that “ZIP” was getting sent as a value on form submission. After some further prodding, I realized that the jQuery form script I was using was not working in Internet Explorer. FireFox would have the default values not sent, but for some reason IE was not processing the jQuery in time and the default value in the text input was being sent along and wreaking havoc on the application.

I had to do some quick fixery to get it to work that way, but the search began for a better (read: functional) solution. Enter Jason Palmer and his jQuery Form Field Default Value plugin. Not to steal any of Jason’s thunder, but the plugin is elegant and doesn’t suffer any issues in Internet Explorer. You should give it a try.


Authenticating all controllers for your Rails application with restful_authentication

So while this might seem intuitive, I found it a little tricky. Preliminary Google searching didn’t reveal anything inherently obvious. However, robbrit on Freenode was able to lend me a hand and I got it figured out.

As you might expect, restful_authentication’s before_filter, :login_required, will direct you to the sessions controller if you are not logged in. So, I initially applied this before_filter to the entire application by placing it as the first line in app/controllers/application_controller.rb

class ApplicationController < ActionController::Base
  before_filter :login_required

Unfortunately, this had unintended consequences. Because this requires login for *all* controllers and *all* actions, we find that we are caught in an endless loop. The login route sends us to /sessions/new, but since we are not logged in, this action tries to again send us to login. Oops!

Rails is kind enough to allow for some exceptions and other fun with filters. So, I initially realized that we should probably add an exception for the “new” action, since that is where we are redirected for a login. We add this exception by re-iterating the before_filter in the app/controllers/sessions_controller.rb:

class SessionsController < ApplicationController
  before_filter :login_required, :except => :new

Unfortunately, this did not quite cut it entirely. Do not forget that the new action essentially just renders the login form. The create action is where all of the *real* work is done. But, since we did not except create, we end up in a login loop. We can fill out the form, press the “login” button, but when we reach the create action we are not logged in. This causes the filter to fire off and send us back to… you guessed it… the new action.

Adding an additional exception (and destroy, just in case) provides the results we are looking for:

class SessionsController < ApplicationController
  before_filter :login_required, :except => [:new, :create, :destroy]

Hopefully all of this stuff will work for you, too. This is just one way I found to authenticate all controllers with restful_authentication as I had a particular application that we wanted to lock down. The extra fun with this type of stuff is that you could put a before_filter on the signup actions. This would have the effect of only allowing a user with an existing account to create new users. This is useful for development lockdown to a certain extent.


T-Mobile G1 Better IMAP mail

So, after posting the other day about broken IMAP mail on the G1, it didn’t take long for a new solution to pop up. Enter the K-9 mail client — an “Android Mutt.”

I haven’t actually tried to see if K-9 fixes any of the folder syncing issues that I was having earlier.  However, what I have noticed is that K-9 handles message deletion much MUCH better. As in messages are actually marked for deletion IMAP style and they disappear from the mailbox.

Perhaps I’ll take some time over this Thanksgiving break to see if folder syncing works right. At least I know that the owners of the K-9 mail project will actually respond to bugs getting posted.

Unfortunately, there are a ton of bugs with the AOL client. I have filed many, but none have been reviewed so far. I’ve learned that the IM portion of Android is not open source, and that it was not written by Google. Hopefully there will be some momentum to get those issues fixed. Until then, however, the inability for the client to stay connected for long periods of time makes it essentially useless to me. Oh bother.


Railsy goodness — ToggleFormText and will_paginate

So, as some of you may know, I do a little Ruby on Rails coding on the side. The geek in me really is quite dominant, so I spend a lot of time in terminal with Vim pumping away at code.

Recently, in a project I’m working on with Ainsley, I’ve made use of Mislav’s will_paginate gem.  We had the folks over at Hustlewood design some truly awesome graphics, and then had the nice fellows at PSD2HTML cut up some HTML/CSS for us.

Well, needless to say, I then had to take that HTML/CSS and stitch it back into the RoR application that I was working on.  One of the issues I encountered was that Mislav’s plugin and the CSS that was provided were not playing nice together.

It took me a minute to figure out how to extend his gem, and I’m still not sure that I did it right.  I originally tried to extend the gem by putting some stuff into the lib area, but found that that didn’t work.  After poking around a bit, I found that re-defining the classes for will_paginate in environment.rb seemed to do the trick.  Here’s some of my modifications:

class WillPaginate::LinkRenderer
 
  def initialize
    @gap_marker = "<li>...</li>"
  end
 
  # Process it! This method returns the complete HTML string which contains
  # pagination links. Feel free to subclass LinkRenderer and change this
  # method as you see fit.
  def to_html
    links = @options[:page_links] ? windowed_links : []
    # previous/next buttons
    links.unshift page_link_or_span(@collection.previous_page, 'disabled prev_page', @options[:previous_label])
    links.push page_link_or_span(@collection.next_page, 'disabled next_page', @options[:next_label])
 
    html = "<ul>" + links.join(@options[:separator]) + "</ul>"
    @options[:container] ? @template.content_tag(:div, html, html_attributes) : html
  end
 
  protected
  def page_link(page, text, attributes = {})
    "<li>" + @template.link_to(text, url_for(page), attributes) + "</li>"
  end
 
  def page_span(page, text, attributes = {})
    "<li>" + @template.content_tag(:span, text, attributes) + "</li>"
  end
 
end

As you can see, I had to do a number of things.  Firstly, I had to re-define the gap_marker to be a list element.  By default, the gap marker is enclosed in a <span>, and that just wouldn’t work for me.  Secondly, I also had to re-define the page_link and page_span methods.  These methods are used as part of the output generation, but were simply generating <a> links. I had to make will_paginate output everything encapsulated in <li> elements, and I also had to force what would normally be spit out as a <span> to also be spit out as a <li> element.

I still need to do some tweaking here with the previous/next, but I think I may simply just modify the CSS at this point (it may be easier).

EDIT: This does *NOT* work in Internet Explorer. Please check here for more information! EDIT

I had a few fields in a form that I also wanted to play with. I know you’ve all seen those nice forms where you click into a text field that has some default values, and the values magically disappear. If you click away, and haven’t typed anything, the defaults magically re-appear. I originally found a few jQuery scripts that seemed to do the trick for one field, but I had two that needed modification, and I also wanted to not send the default values along with the form submission. Enter ToggleFormText, a jQuery plugin. This does exactly what I described.

It uses the “title” attribute of the <input> tag instead of the <value>. Through the magic of jQuery, any <input> with a definition for “title” has its value updated. Clicking in a field (giving it focus) causes the value to be erased. Clicking the submit button causes any fields with their value still equal to the title to be blanked out again. It’s quite delicious.

I really only had to do a couple of simple things:

In my application.rhtml layout:

javascript_include_tag "jquery-1.2.6.min", "jquery.toggleformat"

In my view, I simply modified my text field output:

text_field_tag "searchName", params[:searchName], :title => "NAME", :maxlength => 50
text_field_tag :zip, params[:zip], :title => "ZIP", :maxlength => 5

That was it! The wonderful plugin took care of the rest.

jQuery allows you to do some really powerful stuff with Javascript, so you should certainly check it out if you’re doing any kind of modern-era web design.

That’s all I’ve got for today. A departure from my normal tech bloggery, but at least it’s something interesting to someone out there.


G1 fail?

So the display stopped working on my T-Mobile G1 today.  I’m on hold with T-Mobile right now waiting for a representative.  The screen is powered on, the LED is blinking, the phone is making noises and vibrating like everything is working in the background but it’s blank.

Let’s see what happens.


Refresh IMAP folders in Android (G1) email application

*EDIT* I had filed a bug for this on the Android issue tracker.  It is bug #1096 Shortly after filing this, I did find a workaround.  I have edited below to reflect the changes.

*EDIT* I tried this in a different account and it didn’t work… but I’ll keep trying it to see if it ever does work.  The solution might just be to re-create the accounts. *EDIT*

As I started to add my IMAP email accounts, I noticed that there were folders I didn’t care for.  I didn’t need them, so I nuked them from the webmail interface for the accounts as I couldn’t find any way to delete folders within the Android email application.  To my dismay, I discovered that the Android email application does not appear to refresh IMAP folders frequently (ever).

I found a solution to this issue, though.

  1. Go to the account list in the email application.  You can get there from inside an email account by pressing “menu” and then “accounts”.
  2. Press “menu”
  3. Press “refresh”

You’ll find that the email application reaches out to your IMAP server again and will refresh the folder lists.

It appears that the email application keeps its own “trash” folder, in addition to the one that may already exist on your IMAP account.  But I’ll figure out something about that in a bit.  According to many reports, the delete function doesn’t work right even with this alternate trash folder.  There is an email client called “K9” available in the marketplace that supposedly fixes this issue, but I’ve also heard from an Android developer that it was not implemented “right.”

Generally speaking, if a fix for something broken makes it work, it’s hard to argue with.  K9 also adds some other functionality.  I am just starting to play with it and I’ll let you know how it goes.


G1 in the house

So I have been waiting for something to replace my T-Mobile Sidekick 3 (2.5 if you ask me) for probably close to a year.  I was dis-satisfied with the browser, really dis-satisfied with the email capabilities and my battery had lost some of its charge-holding capabilities.

When I saw that T-Mobile was going to be the first carrier to release an Android-powered phone, I was really happy.  As details of the dream first started coming out, I was even happier.  When I watched the G-1 press release, I was ecstatic.  Now that I have the phone, I have a shit-eating grin.

Sure, it will take some getting used to, but the ability to have *real* IMAP mail right out of the box is amazing.  The integration with Google services has been a tiny bit frustrating, but not so bad over all.  For example, I had to export my contacts from Outlook as CSV and import to GMail.  But GMail decided to lop off mailing addresses for people, so I don’t have them in my phone.  Not super important — I can re-populate those as I go.

One thing I found was that Google introduced an Outlook calendar sync daemon for Windows XP and Vista that works with Outlook ’03 and ’07.  It basically just sits in ram and syncs your GMail calendar to your Outlook calendar, and vice versa.  The nice thing about this?  Now if I enter an appointment on my phone it will go to GMail and then end up in my Outlook — neat!

If only you could directly delete email from the “del” key on the keyboard!

I’ll do my best to post little tips and tricks and neat applications I find as I come across them.  Until then, carry on with your bad phone!


Seeding ruby… on rails, that is

So it’s been a little while since I’ve written a post, but that’s how this blog goes.  Sometimes I write lots of stuff, and sometimes I write nothing at all.

One of the things I wanted to do with the new blog is be a little bit “open source” about the projects I’m working on.  Not so much sharing all the code of the projects, but sharing little bits and pieces of interesting tidbits I find throughout my net travels.

One such bit and piece that I found recently is the seed-fu plugin.  This is a plugin for Ruby on Rails that allows you to, in a very YAML-like way, feed data into your application’s database with simple rake commands.  What’s the benefit of this?  Well, during development, it makes it extremely easy to wreck up your database and then re-populate it with some initial data.

While there are definitely other ways this could be done, seed-fu fit my needs at the moment, so I used it.  There are a bunch of other Ruby on Rails plugins that I use, but I’ll try to talk about them when I use them, and not go back through what I’ve used just for the sake of listing them.


Pages:1234