Archive for the ‘JavaScript, AJAX, & UI’ Category

 

Integrating Controllers, jQuery, JSONP, and Remote Domain Requests with Rails

July 2nd, 2009
By: Steven Haddox
No Comments »

I’m developing an application that needs to have a normal web presence (typical HTTP/HTTPS) as well as a very easily consumable 3rd party API. With these requirements in mind I easily decided to run with Ruby on Rails (.to_json anyone?) I’ve been working on it for over a month now and have encountered a situation where my controllers are getting a little large due to having to handle logic on whether the request via the API url was a Javascript AJAX requests or a regular HTTP request. Generally this is easily solved in the respond to block with something like:

respond_to do |format|
  format.html # reports/show.rhtml
  format.js { render :partial => 'reports/show' } # reports/_show.rhtml
end

This example is just rendering a partial that is also used in my show.rhtml to save updating more than one file at a time. However, my current project started turning into things like this (due to the API methodology we had decided upon with the client in advance that got extended into doing things we hadn’t anticipated):

# show method
respond_to do |format|
  format.html # reports/show.rhtml
  format.json { render :json => @report } # json format of the report data
  format.js { render :partial => 'reports/show' } # reports/_show.rhtml
  format.js_vdata {
    render :template => 'reports/show.visual_json', :layout => false, :content_type => 'application/json'
  }
  format.table {
    render :template => 'reports/show.html_table', :layout => false, :content_type => 'application/json'
  }
  ... [more formats for special MIME types here with customized views all from the same report data] ...
end

As you can see this code was being extended to generate multiple kinds of reports for loading via an API with AJAX requests. The extra formats are all being returned as JSON in order to allow for JSONP and remote-access from other domains and then the user can display the requested data / customize it as they desire. But how did I go about providing those same views to users on the web application itself? Create another format just to render the same view for regular HTTP requests? Definitely not very DRY. So it occurred to me that the following might be a possible solution:

#Controller show method
respond_to do |format|
  ...
  format.js_vdata {
    if request.xhr?
      render :template => 'reports/show.visual_json', :layout => false, :content_type => 'application/json' and return
    else
      render :template => 'reports/show.visual_json', :layout => true, :content_type => 'text/html' and return
    end
  }
  format.table {
    if request.xhr?
      render :template => 'reports/show.html_table', :layout => false, :content_type => 'application/json' and return
    else
      render :template => 'reports/show.html_table', :layout => true, :content_type => 'text/html' and return
    end
  }
end

#View template for reports/show.visual_json
< %- if request.xhr? -%>
  < %= @report.visual_data.to_json %>
< %- else -%>
  
  < %=debug @report.visual_data %>
< %- end -%>

Although this was a basic proof of concept there was already a problem with it. Any request coming from a remote domain would send requests for ‘jsonp’ and would not be recognized by request.xhr? (at least with jQuery 1.2.6 on the server we were consuming this API). I’m not sure why this was, but it seemed to be the situation I had to work with. This meant those requests were getting the HTML version of the page (not fun for parsing via Javascript). The solution I found was this (please note this is a very initial stab and is more than open to refactoring suggestions):

#Controller
before_filter :set_request_type

#show method
respond_to do |format|
  ...
  format.js_vdata {
    begin
      render_dynamic_template('reports/show.visual_json')
    else
      render_dynamic_template('reports/show.nil')
    end
  }
  format.table {
    begin
      render_dynamic_template('reports/show.html_table')
    else
      render_dynamic_template('reports/show.nil')
    end
  }
end

private
  def set_request_type
    @ajax_request = true if request.xhr? or (params[:callback] && params[:callback].include?('jsonp'))
  end

  def render_dynamic_template(template)
    template = 'reports/show.nil' if template.nil?
    if @ajax_request
      layout = false
      content_type = 'application/json'
    else
      layout = true
      content_type = 'text/html'
    end
    render :template => template, :layout => layout, :content_type => content_type
  end
#View template for reports/show.visual_json
< %- if @ajax_request -%>
  < %= @report.visual_data.to_json %>
< %- else -%>
  
  < %=debug @report.visual_data %>
< %- end -%>
#View template for reports/show.nil
< %- if @ajax_request -%>
  < %= [nil].to_json %>
< %- else -%>
  
  < %= 'There is no data at this time.' %>
< %- end -%>

Also, the best tutorial I could find for implementing jsonp support with a quick (like 2 minute) Google search was over at Sitepoint

And that should allow you to render both html and json/jsonp results based upon the kind of request coming in. Obviously it makes an assumption that remote jsonp requests will provide a parameter of ‘callback’ that includes ‘jsonp’ in the string, but given that it is your API that’s not a huge requirement to impose and you can customize it to how you see fit.

If you know of a better way to go about approaching this kind of task I’m more than open to being educated, but given the short time-frame I had and the few tutorials specific to jsonp I found this to be a pretty good first stab. Hopefully this post will help someone else if they find themselves looking for some way to accomplish similar tasks.

Share It:
[del.icio.us] [Digg] [Facebook] [Google] [MySpace] [Newsvine] [Slashdot] [StumbleUpon] [Email]

Flash Happy: Simple flash updates for your Rails application

August 28th, 2008
By: Steven Haddox
No Comments »

So I’ve been learning Ruby on Rails the past few months but I’ve mostly been working on projects that already have the major underpinnings created. I’ve had the opportunity to work on a side project on and off and I’ve finally gotten one of my major hurdles accomplished and am pretty happy with how I did it. I’m open to code refinement, but I thought I’d share it since I couldn’t find much in the way of tutorials regarding flash.now with Rails via Google.

Essentially what I did was implement a way to update the regular flash and the flash.now values at the same time. Read the rest of this entry »

Share It:
[del.icio.us] [Digg] [Facebook] [Google] [MySpace] [Newsvine] [Slashdot] [StumbleUpon] [Email]

StevenHaddox.com Now With More Grunge!

June 21st, 2008
By: Steven Haddox
No Comments »

So I spent an extra hour over the last few mornings (Thursday and Friday) as well as a half hour Friday night working on a small tweak to my current blog.  I added a “splat” image whenever you move your mouse over an icon at the top of the page.  I did this primarily as I kept losing my mouse when I’d use the icons and I wanted to more clearly distinguish where you were on the menu.

I also did it as I need to use similar code on a few other projects I’m working on, but this site was the most suitable for it to be implemented in first and it was one of those things I could leave and pick up fairly easily without a huge loss if I didn’t finish it all in one sitting.

As to the process I went through it was fairly simple once I figured out how to best do it. Read the rest of this entry »

Share It:
[del.icio.us] [Digg] [Facebook] [Google] [MySpace] [Newsvine] [Slashdot] [StumbleUpon] [Email]

A New Day, A New Look … on Everything

April 23rd, 2008
By: Steven Haddox
1 Comment »

What began as a simple goal of making my blog look better a few weeks ago became a sudden priority last night after being told that I won’t be employed with my current employer after this week essentially.  I need to put a good face forward and since my blog is the first thing that comes up when you Google my name, I decided to put in an all-nighter and get business taken care of.  

So thusly, welcome to my new theme for StevenHaddox.com. Read the rest of this entry »

Share It:
[del.icio.us] [Digg] [Facebook] [Google] [MySpace] [Newsvine] [Slashdot] [StumbleUpon] [Email]

Interesting link if you dare to click it

April 20th, 2008
By: Steven Haddox
No Comments »

Notice where this preview link goes through with the URL, and then notice what the page content is.

NOTE: If you are on Windows, I’d avoid this URL strongly (just in case).

http://preview.tinyurl.com/67lov7

Share It:
[del.icio.us] [Digg] [Facebook] [Google] [MySpace] [Newsvine] [Slashdot] [StumbleUpon] [Email]