From ab6d8333972695694d6403cc439b562a34e9ae14 Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Wed, 7 Apr 2010 21:00:51 +0000 Subject: [PATCH] Adding support for only resfreshing design document if really required --- lib/couchrest.rb | 2 +- lib/couchrest/mixins/class_proxy.rb | 24 ++++---- lib/couchrest/mixins/design_doc.rb | 58 ++++++++++++++----- lib/couchrest/mixins/views.rb | 15 ----- spec/couchrest/more/extended_doc_spec.rb | 18 +++++- spec/couchrest/more/extended_doc_view_spec.rb | 26 ++++++--- 6 files changed, 91 insertions(+), 52 deletions(-) diff --git a/lib/couchrest.rb b/lib/couchrest.rb index fd9701e..3cb0664 100644 --- a/lib/couchrest.rb +++ b/lib/couchrest.rb @@ -28,7 +28,7 @@ require 'couchrest/monkeypatches' # = CouchDB, close to the metal module CouchRest - VERSION = '0.37' unless self.const_defined?("VERSION") + VERSION = '0.37.3' unless self.const_defined?("VERSION") autoload :Server, 'couchrest/core/server' autoload :Database, 'couchrest/core/database' diff --git a/lib/couchrest/mixins/class_proxy.rb b/lib/couchrest/mixins/class_proxy.rb index 40f593a..0333785 100644 --- a/lib/couchrest/mixins/class_proxy.rb +++ b/lib/couchrest/mixins/class_proxy.rb @@ -89,18 +89,7 @@ module CouchRest docs end - def all_design_doc_versions - @klass.all_design_doc_versions(@database) - end - - def model_design_doc - @klass.model_design_doc(@database) - end - - def cleanup_design_docs! - @klass.cleanup_design_docs!(@database) - end - + # Mixins::DesignDoc def design_doc @@ -114,6 +103,17 @@ module CouchRest def save_design_doc @klass.save_design_doc(@database) end + + # DEPRICATED + def all_design_doc_versions + @klass.all_design_doc_versions(@database) + end + + def stored_design_doc + @klass.stored_design_doc(@database) + end + alias :model_design_doc :stored_design_doc + end end end diff --git a/lib/couchrest/mixins/design_doc.rb b/lib/couchrest/mixins/design_doc.rb index 1624244..962573f 100644 --- a/lib/couchrest/mixins/design_doc.rb +++ b/lib/couchrest/mixins/design_doc.rb @@ -15,7 +15,7 @@ module CouchRest end # Use when something has been changed, like a view, so that on the next request - # the design docs will be updated. + # the design docs will be updated (if changed!) def req_design_doc_refresh @design_doc_fresh = { } end @@ -43,17 +43,41 @@ module CouchRest } end + # DEPRECATED + # use stored_design_doc to retrieve the current design doc + def all_design_doc_versions(db = database) + db.documents :startkey => "_design/#{self.to_s}", + :endkey => "_design/#{self.to_s}-\u9999" + end + + # Retreive the latest version of the design document directly + # from the database. + def stored_design_doc(db = database) + db.get(design_doc_id) rescue nil + end + alias :model_design_doc :stored_design_doc + def refresh_design_doc(db = database) + raise "Database missing for design document refresh" if db.nil? unless design_doc_fresh(db) - reset_design_doc(db) + reset_design_doc save_design_doc(db) + design_doc_fresh(db, true) end end # Save the design doc onto a target database in a thread-safe way, # not modifying the model's design_doc - def save_design_doc(db = database) - update_design_doc(Design.new(design_doc), db) + # + # See also save_design_doc! to always save the design doc even if there + # are no changes. + def save_design_doc(db = database, force = false) + update_design_doc(Design.new(design_doc), db, force) + end + + # Force the update of the model's design_doc even if it hasn't changed. + def save_design_doc!(db = database) + save_design_doc(db, true) end protected @@ -67,34 +91,38 @@ module CouchRest end end - def reset_design_doc(db) - current = db.get(design_doc_id) rescue nil - design_doc['_id'] = design_doc_id + def reset_design_doc + current = stored_design_doc + design_doc['_id'] = design_doc_id if current.nil? design_doc.delete('_rev') else design_doc['_rev'] = current['_rev'] end - design_doc_fresh(db, true) end # Writes out a design_doc to a given database, returning the # updated design doc - def update_design_doc(design_doc, db) - saved = db.get(design_doc['_id']) rescue nil + def update_design_doc(design_doc, db, force = false) + saved = stored_design_doc if saved - design_doc['views'].each do |name, view| - saved['views'][name] = view + # Perform Hash comparison on views, only part that interests us + if force || design_doc['views'] != saved['views'] + design_doc['views'].each do |name, view| + saved['views'][name] = view + end + db.save_doc(saved) + saved + else + design_doc end - db.save_doc(saved) - saved else design_doc.database = db design_doc.save design_doc end end - + end # module ClassMethods end diff --git a/lib/couchrest/mixins/views.rb b/lib/couchrest/mixins/views.rb index 8543b1c..bbaa949 100644 --- a/lib/couchrest/mixins/views.rb +++ b/lib/couchrest/mixins/views.rb @@ -102,21 +102,6 @@ module CouchRest fetch_view_with_docs(db, name, query, raw, &block) end - # DEPRECATED - # user model_design_doc to retrieve the current design doc - def all_design_doc_versions(db = database) - db.documents :startkey => "_design/#{self.to_s}", - :endkey => "_design/#{self.to_s}-\u9999" - end - - def model_design_doc(db = database) - begin - @model_design_doc = db.get("_design/#{self.to_s}") - rescue - nil - end - end - private def fetch_view_with_docs(db, name, opts, raw=false, &block) diff --git a/spec/couchrest/more/extended_doc_spec.rb b/spec/couchrest/more/extended_doc_spec.rb index 87581d8..8cb4b00 100644 --- a/spec/couchrest/more/extended_doc_spec.rb +++ b/spec/couchrest/more/extended_doc_spec.rb @@ -368,7 +368,7 @@ describe "ExtendedDocument" do describe "finding the first instance of a model" do before(:each) do @db = reset_test_db! - WithTemplateAndUniqueID.req_design_doc_refresh + # WithTemplateAndUniqueID.req_design_doc_refresh # Removed by Sam Lown, design doc should be loaded automatically WithTemplateAndUniqueID.new('important-field' => '1').save WithTemplateAndUniqueID.new('important-field' => '2').save WithTemplateAndUniqueID.new('important-field' => '3').save @@ -388,6 +388,22 @@ describe "ExtendedDocument" do WithTemplateAndUniqueID.first.should be_nil end end + + describe "lazily refreshing the design document" do + before(:all) do + @db = reset_test_db! + WithTemplateAndUniqueID.new('important-field' => '1').save + end + it "should not save the design doc twice" do + WithTemplateAndUniqueID.all + WithTemplateAndUniqueID.req_design_doc_refresh + WithTemplateAndUniqueID.refresh_design_doc + rev = WithTemplateAndUniqueID.design_doc['_rev'] + WithTemplateAndUniqueID.req_design_doc_refresh + WithTemplateAndUniqueID.refresh_design_doc + WithTemplateAndUniqueID.design_doc['_rev'].should eql(rev) + end + end describe "getting a model with a subobject field" do before(:all) do diff --git a/spec/couchrest/more/extended_doc_view_spec.rb b/spec/couchrest/more/extended_doc_view_spec.rb index 7d6ef08..875fd88 100644 --- a/spec/couchrest/more/extended_doc_view_spec.rb +++ b/spec/couchrest/more/extended_doc_view_spec.rb @@ -50,6 +50,11 @@ describe "ExtendedDocument views" do articles = Article.by_date :descending => false articles.collect{|a|a.title}.should == @titles end + it "should allow you to create a new view on the fly" do + lambda{Article.by_title}.should raise_error + Article.view_by :title + lambda{Article.by_title}.should_not raise_error + end end describe "another model with a simple view" do @@ -187,7 +192,7 @@ describe "ExtendedDocument views" do Unattached.view_by :questions Unattached.by_questions(:database => @db) original_revision = Unattached.model_design_doc(@db)['_rev'] - Unattached.save_design_doc(@db) + Unattached.save_design_doc!(@db) Unattached.model_design_doc(@db)['_rev'].should_not == original_revision end end @@ -277,13 +282,18 @@ describe "ExtendedDocument views" do u.respond_to?(:database).should be_false end end - it "should clean up design docs left around on specific database" do - @us.by_title - original_id = @us.model_design_doc['_rev'] - Unattached.view_by :professor - @us.by_professor - @us.model_design_doc['_rev'].should_not == original_id - end + # Sam Lown 2010-04-07 + # Removed as unclear why this should happen as before my changes + # this happend by accident, not explicitly. + # If requested, this feature should be added as a specific method. + # + #it "should clean up design docs left around on specific database" do + # @us.by_title + # original_id = @us.model_design_doc['_rev'] + # Unattached.view_by :professor + # @us.by_professor + # @us.model_design_doc['_rev'].should_not == original_id + #end end describe "a model with a compound key view" do