Never been to DZone Snippets before?

Snippets is a public source code repository. Easily build up your personal collection of code snippets, categorize them with tags / keywords, and share them with the world

About this user

Daniel Haran

« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS 

Javascript Array Intersect

Simple intersect function

Object.extend(Array.prototype, {
  intersect: function(array){
    return this.findAll( function(token){ return array.include(token) } );
  }
});

Quick Flickr search in Ruby

// Examples for the three listed APIs weren't working. Instead of choosing one and debugging it, I chose to do something quick and dirty. "MY_API_KEY" and other params would need to be removed to make this more generic. A naive mapping of API method calls that take hashes, and returns an OpenStruct is an approach I'm considering, as it would likely break less often and require less code.

require 'net/http'
require 'rexml/document'
require 'ostruct'

class Flickr < OpenStruct
  include REXML

  def Flickr.search(text)
    doc = Document.new(
            Net::HTTP.get(
              URI.parse('http://api.flickr.com/services/rest/?method=flickr.photos.search&api_key=MY_API_KEY' +
                        '&extras=license,owner_name,original_format&license=4,5&per_page=20&sort=interestingness-desc' +
                        '&text=' + text)))
     throw "flickr error" unless doc.root.attributes['stat'] == "ok"
     doc.root.elements['photos'].get_elements('//photo').collect {|photo| photo << Flickr.new(photo) }
  end

  def initialize(e)
    super(e.attributes)
    self.new_ostruct_member("photo_id")
    self.photo_id = e.attributes['id']
  end

  def to_url(image_type="s")
    "http://farm#{farm}.static.flickr.com/#{server}/#{photo_id}_#{secret}_#{image_type}.jpg"
  end
end

DRYing up YAML fixtures

// Rails Recipes explained how to DRY up the database configuration code. I applied the same idea to user fixtures, which worked while we used MySQL. Once on Postgres, "defaults" started throwing an error. The easiest solution was to make quentin's values the 'defaults'

quentin: &defaults
  id: 1
  login: quentin
  email: quentin@example.com
  site_id: 1
  salt: 7e3041ebc2fc05a40c60028e2c4901a81035d3cd
  crypted_password: 00742970dc9e6319f8019fd54864d3ea740f04b1 # test
  created_at: <%= 5.days.ago.to_s :db %>
  activated_at: <%= 5.days.ago.to_s :db %> # only if you're activating new signups
aaron:
  id: 2
  login: aaron
  email: aaron@example.com
  activation_code: aaronscode
  site_id: 1
  <<: *defaults
#etc...

Rails Gravatar code and task

My application_helper had a basic gravatar function, but gravatar.com is best used cached.
def gravatar(email, user='')
  "<img alt=\"#{user}'s image\" src=\"/gravatars/#{MD5.new(email)}.gif\" height=\"80\" width=\"80\"/>"
end


lib/gravatar_api.rb:
require 'rc_rest'
class GravatarAPI < RCRest

  @@cache_dir = "/rails/gravatars/"
  cattr_accessor :cache_dir

  # from: http://www.gravatar.com/implement.php?#section_1_1
  # An optional "rating" parameter may follow with a value of [ G | PG | R | X ]
  # that determines the highest rating (inclusive) that will be returned.
  # see also rating guidelines: http://www.gravatar.com/rating.php
  @@acceptable_rating = "PG"
  cattr_accessor :acceptable_rating

  def wget_gravatar(md5)
    info = get_info md5
    # return true if file_expired && I decide on adding a time expiry :)
    `rm #{cache_dir}#{md5}.gif` if File.exists?("#{cache_dir}#{md5}.gif") || File.symlink?("#{cache_dir}#{md5}.gif")
    if info.success && GravatarAPI.rating_ok(acceptable_rating)
      `wget -r -O #{cache_dir}#{md5}.gif http://www.gravatar.com/avatar.php?gravatar_id=#{md5}`
      return true
    else
      `ln -s #{cache_dir}no_image.gif #{cache_dir}#{md5}.gif`
      return false
    end
  end

  def self.rating_ok(actual_rating)
    ratings = %w{ X R PG G }
    ratings.index(actual_rating) >= ratings.index(@@acceptable_rating)
  end

  class Error < RCRest::Error; end

  def initialize
  end

  def check_error(xml)
    raise Error, "unkown error" if !xml.elements['gravatar']
  end

  def make_url(md5)
    URI.parse "http://www.gravatar.com/info/md5/#{md5}"
  end

  Info = Struct.new :success, :rating, :xml
  def parse_response(xml)
    result = Info.new

    result.xml = xml
    result.success = xml.elements['gravatar/code'].text == "200"

    if result.success
      result.rating = xml.elements['gravatar/rating'].text
    end

    result
  end

  def get_info(md5)
    get md5
  end
end


lib/tasks/gravatar.rake
The intention is for "sudo rake cache_gravatars" to be a cron job
desc "wget's the gravatars for all the user emails in your database. call with RAILS_ENV=production or it defaults to development"
task :cache_gravatars => :environment do |t|
  require 'md5'
  require 'gravatar_api'
  ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
  g_api = GravatarAPI.new
  users = (User.find :all).collect {|u| u if u.email? }.compact
  users.each do |user|
    md5 = MD5.new(user.email).hexdigest
    has_g = g_api.wget_gravatar(md5)
    puts "added " + (has_g ? "file" : "symlink" ) + " for " + md5
    if has_g != user.has_gravatar? # Only update object if necessary
      user.has_gravatar = !user.has_gravatar
      user.update
    end
    #sleep(1) # you know, to play nice with gravatar.com if you have a gazillion records
  end
end


Finally, the signup code does an extra call:
def signup
  @user = User.new(params[:user])
  return unless request.post?
  begin
    g_api = GravatarAPI.new
    @user.has_gravatar = g_api.wget_gravatar( MD5.new(@user.email).hexdigest )
  rescue Exception => e
    logger.warn("unable to get gravatar info for user: " + @user.id)
    @user.has_gravatar = false
  end
  @user.save!
...


Migration used:
class Gravatar < ActiveRecord::Migration
  def self.up
    add_column :users, :has_gravatar, :boolean, :default => false
  end

  def self.down
    remove_column :users, :has_gravatar
  end
end


The deployment procedures adds a symbolic link from public/gravatars to /rails/gravatars.
« Newer Snippets
Older Snippets »
Showing 1-4 of 4 total  RSS