SyntaxHighlighter

Wednesday, April 22, 2009

Google Image Search in Rails using the Google Ajax API

Google has a neat Ajax API for searching images on the web. This is neat, but I wanted to integrate it into my site and didn't want to rely on Javascript so heavily. Luckily, Google also supplies a JSON api that's very easy to work with.

Instead, I made a GoogleImage class and reference it in the controller like so. This is in a controller action. The view for this supplies a keyword via a form, and there is a simple 'next' | 'pevious' link that modifies the start parameter.

This is in the view (app/views/search/google_images.html.erb)

<% for image in @google_images %>
<%= link_to(image_tag(image.thumbnail, :style => 'padding:3px; border:solid 1px #EEE; margin:2px; width:100px; float:left'), image.original) %>
<% end %>
<%= clear %>
<%= link_to_unless (params[:start] == 0), 'Prev', :overwrite_params => { :start => (params[:start] - 8) } %> |
<%= link_to_unless (params[:start] > 0 && @google_images.blank?), 'Next', :overwrite_params => { :start => (params[:start] + 8) } %>


This is in the controller (app/controllers/search_controller.rb)


def google_images
params[:start] = params[:start].to_i
@page_title = "Import image from Google"
@google_images = GoogleImage.all(params[:keywords], params[:start])
end



And this is the model (app/models/google_image.rb)

class GoogleImage

require 'json'

attr_accessor :thumbnail, :original, :name, :position

def initialize(params)
super()
self.name = params[:name]
self.thumbnail = params[:thumbnail]
self.original = params[:original]
self.position = params[:position]
end

def self.find (keyword, position = 0)
url = "http://ajax.googleapis.com/ajax/services/search/images?rsz=large&start=#{position}&v=1.0&q=#{CGI.escape(keyword)}"
json_results = open(url) {|f| f.read };
results = JSON.parse(json_results)
image_array = results['responseData']['results']
image = image_array[0] if image_array
google_image = self.new(:thumbnail => image['tbUrl'], :original => image['unescapedUrl'], :position => position, :name => keyword.titleize)
end

def self.all (keyword, position = 0)
return [] if (keyword.nil? || keyword.strip.blank?)
url = "http://ajax.googleapis.com/ajax/services/search/images?rsz=large&start=#{position}&v=1.0&q=#{CGI.escape(keyword)}"
json_results = open(url) {|f| f.read };
results = JSON.parse(json_results)
begin
image_array = results['responseData']['results']
google_images = image_array.map{|image| self.new(:thumbnail => image['tbUrl'], :original => image['unescapedUrl'], :name => keyword.titleize) }
google_images.each_index{|i| google_images[i].position = position + i }
rescue
[]
end
end

end


A couple things to note
- the "start" parameter is not a page number. It's the index of the image in this search.
- Google seems to allow the first 64 images to come back. No more.
- Display is limited to 4 or 8 results (that's due to the result size param 'rsz').

3 comments:

  1. Hi Mark,

    This is Chetan from India. Do you know any rails plugin gives this kind of functionality? Or any idea to resolve these 2 bugs

    1) Google seems to allow the first 64 images to come back. No more.

    2)Display is limited to 4 or 8 results (that's due to the result size param 'rsz').

    Thanks,

    Chetan

    ReplyDelete
  2. This is nice blog mark! Just a few thing are missing in this, before using this code user need to install json ruby gem by typing sudo gem install json.

    And one more thing missing is require 'open-uri' this need to be added in code otherwise it throws an error Errno::ENOENT

    Please add these things so that it will help others.

    Thanks,

    Chetan

    ReplyDelete
  3. Anonymous3:49 AM

    thanks it helped me.....

    ReplyDelete