diff --git a/lib/couchrest.rb b/lib/couchrest.rb index 5cc6c6d..27a9837 100644 --- a/lib/couchrest.rb +++ b/lib/couchrest.rb @@ -15,6 +15,7 @@ require "rubygems" require 'json' require 'rest_client' +require 'extlib' $:.unshift File.dirname(__FILE__) unless $:.include?(File.dirname(__FILE__)) || diff --git a/lib/couchrest/core/model.rb b/lib/couchrest/core/model.rb index 3eb9eb0..3da5430 100644 --- a/lib/couchrest/core/model.rb +++ b/lib/couchrest/core/model.rb @@ -1,7 +1,3 @@ -require 'rubygems' -gem 'extlib' -require 'extlib' - module CouchRest module Model class << self @@ -148,19 +144,47 @@ module CouchRest @@design_doc['views'][method_name] = { 'map' => map_function } + @@design_doc_fresh = false + self.meta_class.instance_eval do - define_method method_name do + define_method method_name do |args| + args ||= {} unless @@design_doc_fresh refresh_design_doc end - @@design_doc + raw = args.delete(:raw) + view_name = "#{type}/#{method_name}" + + if raw + fetch_view(view_name) + else + view = fetch_view(view_name) + # TODO this can be optimized once the include-docs patch is applied + view['rows'].collect{|r|new(database.get(r['id']))} + end end end end private + def fetch_view view_name + retryable = true + begin + database.view(view_name) + # the design doc could have been deleted by a rouge process + rescue RestClient::ResourceNotFound => e + if retryable + refresh_design_doc + retryable = false + retry + else + raise e + end + end + end + def design_doc_id "_design/#{self.to_s}" end @@ -173,11 +197,13 @@ module CouchRest } end - def refresh_design_doc saved = database.get(design_doc_id) rescue nil if saved - # merge the new views in and save if it needs to be saved + @@design_doc['views'].each do |name, view| + saved['views'][name] = view + end + database.save(saved) else database.save(@@design_doc) end @@ -190,7 +216,7 @@ module CouchRest def self.included(model) model.class_eval <<-EOS, __FILE__, __LINE__ include Extlib::Hook - register_instance_hooks :save #, :create, :update, :destroy + register_instance_hooks :save, :create, :update #, :destroy EOS end end # module Callbacks diff --git a/spec/couchrest/core/model_spec.rb b/spec/couchrest/core/model_spec.rb index 5695c80..6be7d21 100644 --- a/spec/couchrest/core/model_spec.rb +++ b/spec/couchrest/core/model_spec.rb @@ -22,6 +22,7 @@ class Article key_writer :date view_by :date + view_by :user_id, :date end describe CouchRest::Model do @@ -189,7 +190,8 @@ describe CouchRest::Model do describe "a model with simple views" do before(:all) do written_at = Time.now - 24 * 3600 * 7 - ["this and that", "also interesting", "more fun", "some junk"].each do |title| + @titles = ["this and that", "also interesting", "more fun", "some junk"] + @titles.each do |title| a = Article.new(:title => title) a.date = written_at a.save @@ -198,17 +200,43 @@ describe CouchRest::Model do end it "should create the design doc" do - Article.by_date + Article.by_date rescue nil doc = Article.database.get("_design/Article") doc['views']['by_date'].should_not be_nil end - it "should return the matching view result" do + it "should return the matching raw view result" do view = Article.by_date :raw => true - # view.should == 'x' - # view['rows'].should == 4 + view['rows'].length.should == 4 end - + it "should return the matching object" do + articles = Article.by_date + articles.collect{|a|a.title}.should == @titles + end + end + + describe "a model with a compound key view" do + before(:all) do + written_at = Time.now - 24 * 3600 * 7 + @titles = ["uniq one", "even more interesting", "less fun", "not junk"] + @user_ids = ["quentin", "aaron"] + @titles.each_with_index do |title,i| + u = i % 2 + a = Article.new(:title => title, :user_id => @user_ids[u]) + a.date = written_at + a.save + written_at += 24 * 3600 + end + end + it "should create the design doc" do + Article.by_user_id_and_date rescue nil + doc = Article.database.get("_design/Article") + doc['views']['by_date'].should_not be_nil + end + it "should sort correctly" do + articles = Article.by_user_id_and_date + # articles.should == 'x' + end end end \ No newline at end of file