Arthur Chang

Flickr API: people.getPublicPhotos vs photos.search

The Flickr API is an incredibly well done API, allowing for very easy queries that provide a ton of information about photos, people, places, and more.  Sometimes, however, results from different api calls overlap, and it's hard to decide which to use.

The most common overlap is the flickr.photos.search with many other photo fetching calls.  The reason is because you can pass in countless amounts of parameters to narrow down your search, which can be replaced by other more simple searches.

I encountered an overlap when I was returning a page full of thumbnails from a particular Flickr user.  I was using the people.getPublicPhotos, passing in the nsid for the user.  This returned the latest photos the user posted, which was great.  I left it as is until I needed to get a few extras, including sorting.  The flickr.getPublicPhotos is very generic, and doesn't accept any other parameters, which is very limiting, so I turned to the flickr.photos.search to do a search with the nsid passed in, and I got the same results but with more control!

I'm wondering if this would yield a slower query, but in my tests there were no differences on my end.  Everything probably funnels eventually to the photos.search query on their end, with some nice wrappers that simplify some of the simpler use cases.

Anyhow, I grouped all my photo lookups into one function, and made it super DRY by giving a type for the search.  Here's an example (using the Flickraw ruby flickr api wrapper):

begin
        extras = 'owner_name, views, date_taken, geo'
       
        if params[:category] == 'user'
          user = flickr.people.findByUsername(:username => params[:search_term])
          search_term = user.nsid
          type = 'user_id'
          params[:sort] = 'date-posted-desc' if params[:sort].nil?
        else
          search_term = params[:search_term]
          type = 'text'
          params[:sort] = 'relevance' if params[:sort].nil?
        end
       
        @photos = flickr.photos.search(:sort => params[:sort], type.to_sym => search_term, :extras => extras)
      rescue Exception => e
        flash[:error] = 'No results'
        logger.info "#{e.message}"
      end

The above is simplified, but I funnel keyword searches with username searches by doing a lookup on the category of the search parameters.  The search is by username, so I have to do an extra call to get the user data which includes the nsid, and set that to the search term.

Try out the Flickr API, and if writing in ruby, the Flickraw gem kicks ass.  When the flickraw library loads, it fetches methods from flickr using introspective capabilities.  Thus the flickraw library does not need to update everytime flickr updates their api.  Flickraw has been my favorite solution so far in terms of flickr wrappers.

Tagged  //   code   flickr   flickraw  

God.rb with Non-Daemon Proccess (no pid file)

I was running orbited and activemq processes without any monitoring tools that would notify me of errors and to restart them if they ever went down.  I turned to God.rb, which monitors processes much like Monit, but in a really nice way.  It's also configured all in ruby so it's easy for a rails app.

One problem was that orbited nor activemq spits out a pid file by default.  In fact, I couldn't get orbited to put a pid file anywhere, even with pid.location configurations.  How the heck do I get God.rb to trac it?  Well I read a small snippet in the bible, I mean God.rb documentation, if it can be called that (it's so short):

Need to watch a script that doesn't have built in daemonization? No problem! God will daemonize and keep track of your process for you

Sweet!  So for all those trying to watch non-daemon processes, God.rb can do it.  Just don't specify the pid file, and it will store it in a default location that you don't need to worry about.  If you do need access to the pid file, for situations like stopping by killing the process using the pid, you can also give God.rb a different pid storage location by including the following at the top of your config:

God.pid_file_directory = '/home/tom/pids'

Checkout the God.rb docs for more information about it.  Just wanted to give you guys a heads up in case you ever came across this issue.

Tagged  //   code   daemon   god   god.rb   pid  

Campfire and Git pushes

Previously when using Campfire, we used a library called Marshmallow, that joins a room and says what commit happened in an SVN repository.  Since moving over to a Git repository, we needed a new bot that would come and tell us what was happening.

I turned to an unofficial Campfire API called Tinder, and wrote a little bit of code to join a single room that has guest access turned on, to say what was just committed to the repository.

The code joins a room, looks for commits in Git, and "speaks".  It runs post-update, so put this in the /git/repo.git/hooks/post-update file.  Don't forget to chmod 770 the post-update file so it can be executed.  This hook is basically what is run when you do a push to the repository.

#!/usr/bin/env ruby

require 'rubygems'
require 'tinder' #require the tinder gem

# room: the subdomain you use for subdomain.campfirenow.com
# path: path to your repository you want to track
# hash: the guest hash, should be about 5 characters long.  you need to turn on guest access in campfire manually first.
# msg: a nice commit message, check the manual for git-log for some flags
#          %an is the author name, %ar is time since the commit, %s is the message, %H is the commit hash
config = {
  :room => 'SUBDOMAIN',
  :path => '/git/repo/path/repo.git',
    :hash => 'GUEST_HASH',
  :msg  => 'Commit by %an (%ar): \"%s\"%nChangeset: http://trac.yoursite.com/changeset/%H'
}

# create new campfire instance with the room
campfire = Tinder::Campfire.new(config[:room])
# get the guest room
room = campfire.find_room_by_guest_hash(config[:hash], 'gitbot')

# get all the commits
commits = `cd #{config[:path]} && git log -#{ARGV.size} --pretty=format:"#{config[:msg]}"`

# say something for each commit
commits.each_line do |commit|
  room.speak "#{commit}"
end

I added some comments above explaining what was going on.  You might also be curious about the msg hash.  The changeset link is going to a modified version of Trac, which I've installed a Git Plugin, so Trac uses our Git repository instead of our SVN repository.  There's probably better tracking systems out there, but we're just reusing what we had before.

Tagged  //   Campfire   code   Git   Tinder  

Remote Branches in Git

Here's a nice ruby script that will automatically create a remote tracking branch on your git repository! Assuming you have a remote bare Git repository:

Create a file in your script directory called create-branch with the contents below:

#!/bin/sh
# create-branch <branch_name>

if [ $# -ne 1 ]; then
echo 1>&2 Usage: $0 branch_name
exit 127
fi

echo [GIT] creating branch: $1
git push origin origin:refs/heads/$1
echo [GIT] updating with origin
git fetch origin
echo [GIT] checking out remote branch: origin/$1
git checkout --track -b $1 origin/$1
echo [GIT] pulling update from: origin/$1
git pull
echo [GIT] finished creating remote branch: origin/$1
echo [GIT] finished creating tracking branch: $1

 

Now to create your remote branch, change to your rails root directory and:

ruby script/create-branch <new_branch_name>

 

This is a great way to share branches with others and committing them to a repository.  Central shared repositories are more of the SVN or CVS like mindset, while Git is designed in a way where you are not constrained to a central repository.  I never really found a real world use case where I wanted people all chained together without any real central backed up repository, but hey, you never know.

Tagged  //   code   Git   remote branches