Flickr tag question


#1

hey,

i am using the flickr wrapper for ruby and need to access the tags of a
specific photo. i got all the rest working. i must admit i am kind of
new to
ruby, but i tried and tried and couldn’t figure it out. among other
things i
want to read geotags like in my example here:

i’m sure it is deadsimple and i just overlooked it.

appreciate it,
stan


#2

I made a typo. Grrr.

irb(main):007:0> auth.token.getFrob(‘froblicious’)
irb(main):008:0> auth.token.cache_token

should have rather been

irb(main):007:0> flickr.auth.token.getToken(‘froblicious’)
irb(main):008:0> flickr.auth.token.cache_token

Hope this helps!

– G.


#3

Hi Stan,

I took a look at the various Flickr APIs for ruby and they seem to
vary in utility. The flickr gem is really easy to use but is
optimized for retrieval only. There’s little you can do to set your
own tags etc, since these are implemented as empty methods for now
(at least in flickr-1.0.0.gem …) so I guess there’s not a lot of
mileage in that. Starts easy, gets hard later when you really need
some obscure little feature … The rflickr API seems to be the most
complete but is sparsely documented to put it kindly.

Here’s how I got started … You probably want to make sure you don’t
have the flickr gem installed but you do have the rflickr gem installed.

API INSTALLATION AND ACTIVATION

% sudo gem uninstall flickr
% sudo gem install rflickr

Load irb

% irb
irb(main):001:0> require ‘flickr’
irb(main):002:0> API_KEY = “your-api-key-goes-here”
irb(main):003:0> SHARED_SECRET = “your-shared-secret-goes-here”
irb(main):004:0> flickr = Flickr.new("/tmp/flickr.cache", API_KEY,
SHARED_SECRET)
irb(main):005:0> flickr.auth.token
=> nil
irb(main):006:0> flickr.auth.login_link
=> “http://blahblahblah

You would click on the ‘blahblahblah’ link to authorize the API
usage. I think in your case, you already have an API key which is
authorized so you would instead skip straight to the next step … In
any case, the callback URL for Flickr API will return a frob value on
the callback URL to you … let’s assume the frob value is
‘froblicious’ (I used a normal index page as my callback, e.g http://
web.site.com/existing_content and it got called back as http://
web.site.com/existing_contact?frob=xxxyyyzzzz). Ok, let’s go on …

irb(main):007:0> auth.token.getFrob(‘froblicious’)
irb(main):008:0> auth.token.cache_token

The cache_token method will save it to your cache file (/tmp/
flickr.cache) in our example here and you can from then on do the
Flickr.new(cache_file,api_key,shared_secret) thing without bothering
with auth again …

GETTING STARTED WITH THE RFLICKR API

So if you quit irb, and then load it again,

% irb
irb(main):001:0> require ‘flickr’
irb(main):002:0> API_KEY = “your-api-key-goes-here”
irb(main):003:0> SHARED_SECRET = “your-shared-secret-goes-here”
irb(main):004:0> flickr = Flickr.new("/tmp/flickr.cache", API_KEY,
SHARED_SECRET)
irb(main):005:0> flickr.auth.token
=> “this time it’s not nil!”

You will see that you are no more getting a nil auth token and you
should be able to use it from now on. For convenience, you can edit
rflickr/lib/flickr/base.rb and hard code the API_KEY and
SHARED_SECRET there. If you do that, you would only need to call the
constructor with the cache_file argument. You could always hard code
that as well :slight_smile:

EXTRACTING FLICKR TAGS

Since you are probably going to be looking for photos with a
particular tag, it’s going to be a little tricky. I don’t see any
Flickr API method that would take a set of tags and give all photos
with that tag. The best that I see is that you can search for
particular tags by user id, but not for all tags!

e.g my tags are as below …

irb(main):018:0> flickr.tags.getListUser ‘82552702@N00’
=> [“accra”, “ada”, “benin”, “busyinternet”, “cotonou”, “dad”,
“estelle”, “estuary”, “family”, “flowers”, “friends”, “fuelstation”,
“gasim”, “ghana”, “guido”, “hpepc”, “inspiron5100”, “kalahari”,
“linksyswrt54g”, “manetparadise”, “mom”, “motorbiketaxis”, “namibia”,
“paul”, “pharaon”, “puppies”, “rain”, “sandra”]

So I’m not too sure how you are going to manage this … let’s try
the flickr.photos.search API instead …

irb(main):020:0> photolist = flickr.photos.search nil, ‘semapedia’

And BINGO. We got the photos :slight_smile:

I guess we need to loop through them now in order to get at the tags,
to see what other tags are attached, for example …

irb(main):089:0> def show_tags_for_photolist(photolist)
irb(main):090:1> for photo in photolist
irb(main):091:2> print “#{photo.title} =>\n”
irb(main):092:2> for tag in photo.tags
irb(main):093:3> print “\t#{tag.raw}\n”
irb(main):094:3> end
irb(main):095:2> print “\n”
irb(main):096:2> end
irb(main):097:1> end

And now you can go ahead and do … (if you want all the ‘semapedia
AND nyc’ tagged photos visible to you …)

irb(main):097:1> show_tags_for_photolist(flickr.photos.search(nil,
‘semapedia,nyc’, ‘all’)) ; nil

If you use irb to get a feel for the API or how to get your groove
on, you can add a ; nil to the end of methods that return a long
result, so that stuff doesn’t scroll off the screen …

I really hope this helps getting you started and welcome to rails. It
takes a little time and you would be well advised to go buy the Agile
Web D. with Rails book and perhaps the Ruby for Rails book
as well as Rails Recipes to help you avoid doing all the R&D that
people have already done :slight_smile:

– G.


#4

On 22/05/06, Guido S. removed_email_address@domain.invalid wrote:

Yet another typo. Today must be my inconsistent day, or my consistent
day depending on how you want to look at it :slight_smile:

Great explanation though Guido. thanks.
(And for taking the time to correct it!)

regards


Dave Pawson
XSLT XSL-FO FAQ.
http://www.dpawson.co.uk


#5

Yet another typo. Today must be my inconsistent day, or my consistent
day depending on how you want to look at it :slight_smile:

The text below is a little misleading. If you follow it exactly, it
won’t work …

You would click on the ‘blahblahblah’ link to authorize the API usage.
I think in your case, you already have an API key which is authorized
so you would instead skip straight to the next step … In any case,
the callback URL for Flickr API will return a frob value on the
callback URL to you … let’s assume the frob value is ‘froblicious’
(I used a normal index page as my callback, e.g
http://web.site.com/existing_content and it got called back as
http://web.site.com/existing_contact?frob=xxxyyyzzzz). Ok, let’s go on

Instead, you get to call

flickr.auth.getToken(‘xxxyyyzzz’) to get your API activated after you
click on the Flickr button that leads you to your callback URL …
getting the proper xxxyyyzzz value from that URL, of course!

– G.


#6

Hey Guido,

thanks so much for your insights and samples. I haven’t had time to
really
test the waters since the weekend, but will do and share my experience
with
you.

One question: You told me uninstall flickr and install flickr

% sudo gem uninstall flickr
% sudo gem install rflickr

But then later in the code it is still the class Flickr im dealing with,
same as before. How about packaging in ruby, isn’t that something that
should be enforced? If I would have both installed which is not complety
unrealistic how would i distinguish between them?

Thanks again for your great help,
Stan


#7

Thanks Guido, I think I understand. If would be to write a module that
is
used in other applications I would use a path to prevent eventual naming
conflicts and applications would not just say

require ‘myModule’

but

require ‘org/sampleName/domain/myModule’

does that make sense?

Appreciate it;)
Stan


#8

Almost, but not quite. rflickr and flickr are different gems but both
contain a flickr.rb file that gets loaded on require ‘flickr’ …

Ruby has a ‘class path’ that is uses for loading files and it probably
loads the first matching file in that path … Actually, I think
there are several such paths, you have vendor, site and the ruby
distribution itself. If the ruby runtime files live in
/usr/local/lib/ruby, then you would have …

1.8 -> the runtime files/classes for ruby-1.8
site_ruby/1.8 -> files for locally installed stuff
vendor_ruby/1.8 -> files installed with ruby (but not in ruby’s core)

On top of that, gems have their own loading mechanism, so perhaps my
example should have been something like

require ‘rubygems’
require_gem ‘rflickr’

Rubygems manipulates the ‘class path’ to include all activated gems.
In such a case, require will fall back to using the gems in the path,
and we are back to the situation where the first match will be loaded
… so in such a case, it may be better to just use the require_gem
method instead …

See http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/185638
(excerpts below)

The require_gem does two basic functions:

(1) Activates a gem with an appropriate version number (see below for
more on “activate”)

(2) Auto requires the autorequire file if the gem has specified one.

After much experience with gems, the RubyGems team has come to the
conclusion that the autorequire step causes more trouble than its worth.
The require_gem command will be probably be deprecated in the future and
be replaced with a command that only does the activation step.
(‘activate_gem’ will probably be then name of this new command, although
no promises there).

Require_gem is only needed if you wish to assert which versions of a gem
you are willing to accept. If you don’t care, it is better to not use
it.

Today, Gems monitors all require requests given to Ruby. If a require
fails to load a file, then Gems will check its repository to see if
there is a file that satisfies the require statement. If so, RubyGems
will activate the latest version of the gem that provides that file and
will retry the require.

– G.


#9

Not really. You would just require ‘myModule’ …

require is a function that rubygems overrides, so when it fails, the
gems are smart enough to look through their own path
‘org/sampleName/domain/myModule’ and would find your module for you.

When that doesn’t work, you can use the require_gem function instead,
which chooses what to load based on the name of the gem being
required. You can also tell it what version of the gem to load …

So what you would do if you wrote a module that other applications
would use, would be to put it in a gem … And try to pick a name that
no one is using. If that doesn’t work, say, there is a conflict, then
the version can be used to select which one to really use. I don’t
think the obvious pathological case of two gems having the same name
and version happens because then there’s only one file on the gem
server (and the other would have been overwritten :slight_smile:

– G.