require 'rubygems'
require 'relaxdb'

# Specify the db to be used. Create it in CouchDB yourself locally.

RelaxDB::Database.set_std_db :host => "localhost", :port => 5984, :db => "photos"

#
# Define the classes
#

class Photo < RelaxDB::Document
  
  property :name
  property :tags

end

class Tag < RelaxDB::Document
  
  property :name
  property :photos
  
end

#
# Create the views
#

tags_view = <<MAP_FUNC
  function(doc) {
    if(doc.class == "Tag" && doc.photos) {
      var i;
      for(i = 0; i < doc.photos.length; i++) {
        emit(doc.photos[i], doc);
      }
    }
  }
MAP_FUNC

photos_view = <<MAP_FUNC
  function(doc) {
    if(doc.class == "Photo" && doc.tags) {
      var i;
      for(i = 0; i < doc.tags.length; i++) {
        emit(doc.tags[i], doc);
      }
    }
  }
MAP_FUNC

DesignDocument.get(Photo).add_view_to_data("all_tags", tags_view).save
DesignDocument.get(Tag).add_view_to_data("all_photos", photos_view).save

#
# Insert some data
#

Photo.destroy_all!
Tag.destroy_all!

mg = Photo.new(:_id => "mg", :name => "Migration").save
des = Photo.new(:_id => "des", :name => "Dar es Salaam").save

wd = Tag.new(:_id => "wd", :name => "wildebeest").save
tz = Tag.new(:_id => "tz", :name => "tanzania").save

# Being forced to use ids and set the relationship on both sides is clunky and error 
# prone, but it's no more than a current limitation of the library

mg.tags = [wd._id, tz._id]
des.tags = [tz._id]

wd.photos = [mg._id]
tz.photos = [mg._id, des._id]

RelaxDB.bulk_save(mg, des, wd, tz)

#
# Examine the data, confirm in the CouchDB log that n+1 requests aren't being made
#

mg = Photo.all_by(:name) { |q| q.key = "Migration"}[0]
mg_tags = Photo.view("all_tags?key=\"#{mg._id}\"")
puts mg_tags.inject("Tags for #{mg.name}") { |m, t| m << " '#{t.name}'" }

tz = Tag.all_by(:name) { |q| q.key = "tanzania" }[0]
tz_photos = Tag.view("all_photos?key=\"#{tz._id}\"")
puts tz_photos.inject("Photos for #{tz.name}") { |m, p| m << " '#{p.name}'" }
