Adding support for only resfreshing design document if really required

This commit is contained in:
Sam Lown 2010-04-07 21:00:51 +00:00
parent 5fd1c3903b
commit ab6d833397
6 changed files with 91 additions and 52 deletions

View file

@ -28,7 +28,7 @@ require 'couchrest/monkeypatches'
# = CouchDB, close to the metal # = CouchDB, close to the metal
module CouchRest 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 :Server, 'couchrest/core/server'
autoload :Database, 'couchrest/core/database' autoload :Database, 'couchrest/core/database'

View file

@ -89,18 +89,7 @@ module CouchRest
docs docs
end 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 # Mixins::DesignDoc
def design_doc def design_doc
@ -114,6 +103,17 @@ module CouchRest
def save_design_doc def save_design_doc
@klass.save_design_doc(@database) @klass.save_design_doc(@database)
end 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 end
end end

View file

@ -15,7 +15,7 @@ module CouchRest
end end
# Use when something has been changed, like a view, so that on the next request # 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 def req_design_doc_refresh
@design_doc_fresh = { } @design_doc_fresh = { }
end end
@ -43,17 +43,41 @@ module CouchRest
} }
end 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) def refresh_design_doc(db = database)
raise "Database missing for design document refresh" if db.nil?
unless design_doc_fresh(db) unless design_doc_fresh(db)
reset_design_doc(db) reset_design_doc
save_design_doc(db) save_design_doc(db)
design_doc_fresh(db, true)
end end
end end
# Save the design doc onto a target database in a thread-safe way, # Save the design doc onto a target database in a thread-safe way,
# not modifying the model's design_doc # 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 end
protected protected
@ -67,34 +91,38 @@ module CouchRest
end end
end end
def reset_design_doc(db) def reset_design_doc
current = db.get(design_doc_id) rescue nil current = stored_design_doc
design_doc['_id'] = design_doc_id design_doc['_id'] = design_doc_id
if current.nil? if current.nil?
design_doc.delete('_rev') design_doc.delete('_rev')
else else
design_doc['_rev'] = current['_rev'] design_doc['_rev'] = current['_rev']
end end
design_doc_fresh(db, true)
end end
# Writes out a design_doc to a given database, returning the # Writes out a design_doc to a given database, returning the
# updated design doc # updated design doc
def update_design_doc(design_doc, db) def update_design_doc(design_doc, db, force = false)
saved = db.get(design_doc['_id']) rescue nil saved = stored_design_doc
if saved if saved
design_doc['views'].each do |name, view| # Perform Hash comparison on views, only part that interests us
saved['views'][name] = view 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 end
db.save_doc(saved)
saved
else else
design_doc.database = db design_doc.database = db
design_doc.save design_doc.save
design_doc design_doc
end end
end end
end # module ClassMethods end # module ClassMethods
end end

View file

@ -102,21 +102,6 @@ module CouchRest
fetch_view_with_docs(db, name, query, raw, &block) fetch_view_with_docs(db, name, query, raw, &block)
end 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 private
def fetch_view_with_docs(db, name, opts, raw=false, &block) def fetch_view_with_docs(db, name, opts, raw=false, &block)

View file

@ -368,7 +368,7 @@ describe "ExtendedDocument" do
describe "finding the first instance of a model" do describe "finding the first instance of a model" do
before(:each) do before(:each) do
@db = reset_test_db! @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' => '1').save
WithTemplateAndUniqueID.new('important-field' => '2').save WithTemplateAndUniqueID.new('important-field' => '2').save
WithTemplateAndUniqueID.new('important-field' => '3').save WithTemplateAndUniqueID.new('important-field' => '3').save
@ -388,6 +388,22 @@ describe "ExtendedDocument" do
WithTemplateAndUniqueID.first.should be_nil WithTemplateAndUniqueID.first.should be_nil
end end
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 describe "getting a model with a subobject field" do
before(:all) do before(:all) do

View file

@ -50,6 +50,11 @@ describe "ExtendedDocument views" do
articles = Article.by_date :descending => false articles = Article.by_date :descending => false
articles.collect{|a|a.title}.should == @titles articles.collect{|a|a.title}.should == @titles
end 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 end
describe "another model with a simple view" do describe "another model with a simple view" do
@ -187,7 +192,7 @@ describe "ExtendedDocument views" do
Unattached.view_by :questions Unattached.view_by :questions
Unattached.by_questions(:database => @db) Unattached.by_questions(:database => @db)
original_revision = Unattached.model_design_doc(@db)['_rev'] 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 Unattached.model_design_doc(@db)['_rev'].should_not == original_revision
end end
end end
@ -277,13 +282,18 @@ describe "ExtendedDocument views" do
u.respond_to?(:database).should be_false u.respond_to?(:database).should be_false
end end
end end
it "should clean up design docs left around on specific database" do # Sam Lown 2010-04-07
@us.by_title # Removed as unclear why this should happen as before my changes
original_id = @us.model_design_doc['_rev'] # this happend by accident, not explicitly.
Unattached.view_by :professor # If requested, this feature should be added as a specific method.
@us.by_professor #
@us.model_design_doc['_rev'].should_not == original_id #it "should clean up design docs left around on specific database" do
end # @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 end
describe "a model with a compound key view" do describe "a model with a compound key view" do