Dynamic date exclusions w/ JQuery Datepicker, Rails & Gon

A question came up the other day when I was showing a colleague the reservation page for the restaurant app I’ve recently written (http://alianosbatavia.com): If the restaurant is closed, can you dynamically exclude dates from the JQuery date picker? The answer was yes – but I hadn’t found a nice way to do it. The way it previously was configured looked something like this (coffee script):

  $("#reservation_date").datepicker(
    minDate: "-0d",
    maxDate: "+1Y",
    showOtherMonths: true,
    selectOtherMonths: true,
    beforeShowDay: (date)->
      closedDates = [[12,25],[1,1],[8,22]]
      for closedDate in closedDates
        if(closedDate[1] == date.getDate() && (closedDate[0]-1) == (date.getMonth()))
          return [false]
      return [true]
  )

Fast forward to yesterday – I was watching Railscast episode #324 during my morning commute. It’s about passing data to javascript from Rails apps. There are a few ways to do that using HTML data tags, etc, (I’ll let you watch the episode) but the last suggestion involved using a gem called Gon. Gon essentially creates store of values at the window level in javascript and pumps it full of data from variables in your controllers in your Rails app (again, more details in the episode).

Using Gon to exclude dates from the JQuery date picker? Super easy.

You need to include gon in the head tag of the page on which it will be used. I added mine to my applications layout:

In application.html.erb:

<head>
  <title><%=h yield(:title) %></title>
  <%= include_gon %>
  <%= stylesheet_link_tag "application" %>
  <%= javascript_include_tag "application" %>
  <%= csrf_meta_tags %>

That will add the gon storage to every page. Next, add some data to the gon storage:

In my controller methods (or in a filter):

gon.exceptions = closed_dates

And now, from my JQuery date picker config:

In my assets/reservation.js.coffee:

  $("#reservation_date").datepicker(
    minDate: "-0d",
    maxDate: "+1Y",
    showOtherMonths: true,
    selectOtherMonths: true,
    beforeShowDay: (date)->
      closedDates = gon.exceptions
      for closedDate in closedDates
        if(closedDate[1] == date.getDate() && (closedDate[0]-1) == (date.getMonth()))
          return [false]
      return [true]
  )

That’s it! Be sure to check out the Railscast and the Gon github page for more details.

Simple caching in Rails 3.1

Parting ways with http://alianosbatavia.com has been a lot harder than I thought. Every time I think I’m going to hang it up, I think of something new to add to it.  Recently, I wanted to use simple caching to load blocks of reservations at start up, then refresh those blocks after each successful update of blocks from the admin UI.  Here we’ll talk about reading to and writing from the cache in Rails 3.1.

Writing to the cache

In config/initializers/load_reservations.rb:

require File.dirname(__FILE__) + '/../../lib/reservations_loader.rb'
Rails.cache.write(:reservation_blocks, ReservationsLoader.build_reservations_map)

Reading from the cache
In app/models/reservation.rb:

blocks = Rails.cache.read(:reservation_blocks)

Pretty easy.  I have an observer on ReservationBlocks that refreshes the cache the same way it initially loads it on startup.  This gives me a fast and easy way to display only reservations that are available for the currently selected date on the reservations screen without having to query the database every time a reservation time is requested.

I resolve, version 2.0

2011 is gone and with new year comes new resolutions. Some of last year’s resolutions got resolved, others fell to the wayside, and now I’ve come to write down a few more.

I never got back into grails – although I still feel like I want to. That one stays on the list!

Revisited some old text books, but I still have more to revisit. I forgot a lot about design patterns. Some of that is interview fodder, but still among the things I like to know.

The tracker app never went out, but an equally cool side project did – http://alianosbatavia.com – an implementation of a turn-key restaurant web app. Fairly successful so far, gave me a reason to write a production rails app, learn more about SEO, etc. Still not sure what my next idea is, but I want to get another app out this year…

Is Java still relevant? I go back and forth on this. I am thinking of either learning Play! or Scala/Akka. Not sure I care about either one. I think this is at the bottom of the list.

Lastly, I need to write the posts I talked about writing last year, including my favorite anonymous inner class mock madness.

Hopefully, I’ll be back soon.

Size doesn’t matter (or work, apparently)

Here’s a quick one.

Recently when doing some Rails work, I was using FormHelper to add a text area to an erb and couldn’t seem to get the size param to work. The Rails API docs clearly mention the use of the ‘:size’ param or the ‘:rows’ and ‘:columns’ params being acceptable.

For what it’s worth, neither seem to render in Firefox 3/4 or Safari. If you’re having the same problem, add a style to your text area to control the size, and you should be in business…

     <%=form_builder.text_area(:attribute, {:class=>"aSizedTextArea"})%>

In your css file:

.aSizedTextArea {
    overflow-y: scroll;
    height: 100px;
}

Getting my spec on

Although I still consider myself a rookie in the RoR world, I recently made my way through the Rspec book, and came out of the experience with some new skills to sharpen. On an internal project at Redpoint, we’re again using CanCan for authorization and Authlogic for authentication. My first task after getting involved a second time around (I was involved before I learned Rspec/Cucumber/BDD, stopped, read the book, and now am back) was to back fill some test coverage.

Immediately, I ran into issues figuring out how much to test, when to test what, factories vs mocks, etc – all much discussed topics with typical purist and cool kid groups. After poring over a zillion resources via the normal sources (mostly google and stackoverflow), I decided the best way to sharpen those newly forged rspec skills was to dive in the purist way.

First, I made a quick decision to treat features tested via Cucumber as integration tests, and used models created with FactoryGirl to test them. Easy enough, I thought – the rest would be just as easy…

Well, not exactly.

After piecing together a solution from the blog and forum post’s of others (see links above). Here’s what I ended up with:

Authlogic – essentially, the strategy here is to override the methods normally put in ApplicationController.rb to create stub/mocks of UserSession and User models.

in spec_helper.rb:

require 'authlogic/test_case'

def current_user(stubs = {})
  @current_user = stub_model(User, {:login=&gt;"a user name"}.merge(stubs))
end

def user_session(stubs = {}, user_stubs = {})
  @user_session ||= mock(UserSession, {:user =&gt; current_user(user_stubs), :record =&gt; true}.merge(stubs))
end

def login(session_stubs = {}, user_stubs = {})
  UserSession.stub!(:find).and_return(user_session(session_stubs, user_stubs))
end

def logout
  @user_session = nil
end

…resulting in tests that can call ‘login’ and ‘logout’ to simulate authenticated and unauthenticated users:

before { 
     login 
}

For CanCan, the solution came much quicker, and I think it was in a response to someone’s forum posting from Ryan Bates himself. In this case, we create an instance of ability, which is essential what is happening in the background during normal operation, and stack it with whatever :can’s we’d like. This new object just extends CanCan’s ability class, and we can alter it however we please. Now, my test contains something along these lines:

before { 
    login

    @ability = Object.new
    @ability.extend(CanCan::Ability)
    controller.stub(:current_ability).and_return(@ability) 
}

…and throughout my tests, when I want to set abilities, I add something like this where necessary:

     @ability.can :manage, :all

I hope this saves someone using the same Gems some time to see in one place. That is the only aspect of this post I can take credit for.

Like learning English from an auctioneer…

As we all know, skill retention has a lot to do with level of immersion and length of stay – the deeper you are into a particular technology and the length of time that you’re at that depth usually are directly related to how long you can remember a given technology, language, or practice.

My experience with Ruby and Rails reflects this. I’ve been in and out of two projects in my free time while working on other projects during the day. My approach to picking up Rails was similar to how I picked up Groovy and Grails – get a book and read it . In my case it was the classic Advanced Web Development With Rails. Coming from a java background, the learning curve for Groovy was easy. I only had to learn Grails. For Ruby and Rails, diving right into Rails was ok, but I glossed over a lot of the Ruby syntax and shortcuts, assuming I would pick them up later. With Ruby having a steeper learning curve for me, and not being deeply immersed in these projects for long periods of time, my personal velocity suffered. It was like learning English from an auctioneer – too often going back to find syntax examples of things I knew I wanted to do, but couldn’t remember exactly how…

A few weeks back a co-worker sent a link to our team about Ruby Koans (http://rubykoans.com/). While I’m not a huge fan of the ‘path to enlightenment’/’Zen b.s., they serve as a fast and hands-on way to learn the language (and it’s shortcuts), and serve as a quick reference point for use later. In short, I’m a big fan, and if you’re interested in learning Ruby and making it stick, I recommend working through them. The easiest way to get started is at github: (https://github.com/edgecase/ruby_koans).

ruby_koans = awesome (or is it ruby_koans == awesome?) Check the koans!

Makes life easier. Is good.

Some resources to get started using some handy tools for ruby/rails development

RVM is awesome. Manage the version of ruby you’re using and the gems for each version and/or project with ease. Super handy. All the pain of changing ruby versions on the mac is eliminated.

Get your BDD on with Rspec, and then automate with Autotest. No more autospec layer for Rspec 2 – Autotest is directly integrated these days. Let your machine run the tests for you as you write/update code. The growl plugin for development on the mac is slick as well. This is what development should be like.

It makes sense now!

I just got through a few days of using jdpace’s PDFKit gem for rails. It is a very straightforward PDF generation tool for Rails which uses the wkhtmltopdf tool to generate PDF documents from HTML and CSS3. After watching the great-as-usual Railscast on the topic, there were just a couple of missing pieces that I had to put together from the PDFKit github wiki and few other sources. Here’s what the problem was:

I wanted to respond_to requests as either PDF or HTML, but only for certain actions. I also wanted to send formatting instructions to wkhtmltopdf. Here’s what filled in the blanks for me:

In environment.rb (this is a Rails 2.3.8 project):

require 'pdfkit' #above the run block
#code below belongs within the run block
config.middleware.use PDFKit::Middleware
  Mime::Type.register 'application/pdf', :pdf

In my controller I want to make the default layout nil (so my reports either use no layout, or use their own), and I want to respond to requests with pdf of the source page…

layout nil
def my_report
respond_to do |format|
      format.html
      format.pdf {
        html = render_to_string(:action => "my_report")
       kit = PDFKit.new(html, :page_size => 'Letter', :margin_bottom=>".25", :margin_top=>".25", :margin_left=>".25", :margin_right=>".25")
        kit.stylesheets << "#{Rails.root}/public/stylesheets/my_stylesheet.css"
        send_data(kit.to_pdf, :filename => "generate_a_file_name", :type => 'application/pdf')
        return
      }
    end
end


That is all. You can also change the disposition option for the generated pdf in the respond_to block to have the pdf render in the browser rather than download. There are many references to using the extended help feature of wkhtmltopdf to find more formatting options to pass to the generator. Be sure to use the correct names! Some names in the help file will not be the same as their equivalent labels in your app.

Just call me Casey Jones

I’ve recently found myself involved in some RoR work. It took a bit to take my java blinders off, but since they’ve been off, the work has been great. With past Grails experience in mind, here are a few first observations after a couple of weeks of being a Rails dev under my belt.

I like migrations
I used to think I liked the “declare everything in the model” style of defining models in grails, but since then I’ve come to appreciate having to write migrations for the (dare I say?) discipline they force upon the author. Writing those migrations makes me think carefully about how the model change I’m trying to make impacts what’s already in the database.

Plugin/gem maturity
The community is strong – there are far more useful plugins/gems available for RoR apps than there are for Grails apps. You get just a few key choices in a Grails app. With an RoR app, and this sometimes can be cause for concern, there are many plugins to choose from – authorization and authentication gems are a good example. There are basically two choices in Grails – Spring Security and JSecurity. There are many choices for RoR apps, and further, they can be mixed and matched with the authorization and authentication components being separate.

Railscasts
So useful. I’d like to have the option of choosing a celebrity voice-over for them, though. Homer Simpson and/or Snoop Dogg would be my choices. http://railscasts.com/

The learning curve
Groovy & Grails has a definite advantage in being easier to pick up for someone with a java background. I think this is also a downfall of groovy/grails, because it is so easy to fall back to java instead of learning a new (or more efficient) way to solve a problem (ie with a new language and framework a la RoR).

The enterprise and it’s architects
Code that runs on hardware they’ve already got, that leverages existing resources (people and hardware), and is at least somewhat familiar to them is appealing. RoR is not this.

C to tha I
If I can’t roll a build and have Chuck Norris give me the thumbs up afterwards, I am somehow not satisfied. Autotest, rspec, and growl can get me by in the meantime.

… I just wrote a rake task. I’ll write about that later.