Working on adding checksum support to design documents to handle updates
This commit is contained in:
parent
a6becd7305
commit
221e5a5470
30
Gemfile.lock
30
Gemfile.lock
|
@ -12,21 +12,22 @@ GEM
|
||||||
remote: http://rubygems.org/
|
remote: http://rubygems.org/
|
||||||
specs:
|
specs:
|
||||||
abstract (1.0.0)
|
abstract (1.0.0)
|
||||||
actionpack (3.0.5)
|
actionpack (3.0.6)
|
||||||
activemodel (= 3.0.5)
|
activemodel (= 3.0.6)
|
||||||
activesupport (= 3.0.5)
|
activesupport (= 3.0.6)
|
||||||
builder (~> 2.1.2)
|
builder (~> 2.1.2)
|
||||||
erubis (~> 2.6.6)
|
erubis (~> 2.6.6)
|
||||||
i18n (~> 0.4)
|
i18n (~> 0.5.0)
|
||||||
rack (~> 1.2.1)
|
rack (~> 1.2.1)
|
||||||
rack-mount (~> 0.6.13)
|
rack-mount (~> 0.6.14)
|
||||||
rack-test (~> 0.5.7)
|
rack-test (~> 0.5.7)
|
||||||
tzinfo (~> 0.3.23)
|
tzinfo (~> 0.3.23)
|
||||||
activemodel (3.0.5)
|
activemodel (3.0.6)
|
||||||
activesupport (= 3.0.5)
|
activesupport (= 3.0.6)
|
||||||
builder (~> 2.1.2)
|
builder (~> 2.1.2)
|
||||||
i18n (~> 0.4)
|
i18n (~> 0.5.0)
|
||||||
activesupport (3.0.5)
|
activesupport (3.0.6)
|
||||||
|
bouncy-castle-java (1.5.0145.2)
|
||||||
builder (2.1.2)
|
builder (2.1.2)
|
||||||
couchrest (1.1.0.pre2)
|
couchrest (1.1.0.pre2)
|
||||||
json (~> 1.5.1)
|
json (~> 1.5.1)
|
||||||
|
@ -36,16 +37,19 @@ GEM
|
||||||
erubis (2.6.6)
|
erubis (2.6.6)
|
||||||
abstract (>= 1.0.0)
|
abstract (>= 1.0.0)
|
||||||
i18n (0.5.0)
|
i18n (0.5.0)
|
||||||
|
jruby-openssl (0.7.3)
|
||||||
|
bouncy-castle-java
|
||||||
json (1.5.1)
|
json (1.5.1)
|
||||||
|
json (1.5.1-java)
|
||||||
mime-types (1.16)
|
mime-types (1.16)
|
||||||
rack (1.2.1)
|
rack (1.2.1)
|
||||||
rack-mount (0.6.14)
|
rack-mount (0.6.14)
|
||||||
rack (>= 1.0.0)
|
rack (>= 1.0.0)
|
||||||
rack-test (0.5.7)
|
rack-test (0.5.7)
|
||||||
rack (>= 1.0)
|
rack (>= 1.0)
|
||||||
railties (3.0.5)
|
railties (3.0.6)
|
||||||
actionpack (= 3.0.5)
|
actionpack (= 3.0.6)
|
||||||
activesupport (= 3.0.5)
|
activesupport (= 3.0.6)
|
||||||
rake (>= 0.8.7)
|
rake (>= 0.8.7)
|
||||||
thor (~> 0.14.4)
|
thor (~> 0.14.4)
|
||||||
rake (0.8.7)
|
rake (0.8.7)
|
||||||
|
@ -63,12 +67,14 @@ GEM
|
||||||
tzinfo (0.3.26)
|
tzinfo (0.3.26)
|
||||||
|
|
||||||
PLATFORMS
|
PLATFORMS
|
||||||
|
java
|
||||||
ruby
|
ruby
|
||||||
|
|
||||||
DEPENDENCIES
|
DEPENDENCIES
|
||||||
activemodel (~> 3.0.0)
|
activemodel (~> 3.0.0)
|
||||||
couchrest (= 1.1.0.pre2)
|
couchrest (= 1.1.0.pre2)
|
||||||
couchrest_model!
|
couchrest_model!
|
||||||
|
jruby-openssl (>= 0.7.3)
|
||||||
mime-types (~> 1.15)
|
mime-types (~> 1.15)
|
||||||
rack-test (>= 0.5.7)
|
rack-test (>= 0.5.7)
|
||||||
railties (~> 3.0.0)
|
railties (~> 3.0.0)
|
||||||
|
|
|
@ -30,5 +30,6 @@ Gem::Specification.new do |s|
|
||||||
s.add_dependency(%q<railties>, "~> 3.0.0")
|
s.add_dependency(%q<railties>, "~> 3.0.0")
|
||||||
s.add_development_dependency(%q<rspec>, ">= 2.0.0")
|
s.add_development_dependency(%q<rspec>, ">= 2.0.0")
|
||||||
s.add_development_dependency(%q<rack-test>, ">= 0.5.7")
|
s.add_development_dependency(%q<rack-test>, ">= 0.5.7")
|
||||||
|
s.add_development_dependency("jruby-openssl", ">= 0.7.3")
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|
|
@ -7,7 +7,7 @@ module CouchRest
|
||||||
module ClassMethods
|
module ClassMethods
|
||||||
|
|
||||||
def design_doc
|
def design_doc
|
||||||
@design_doc ||= Design.new(default_design_doc)
|
@design_doc ||= ::CouchRest::Design.new(default_design_doc)
|
||||||
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
|
||||||
|
@ -90,24 +90,17 @@ module CouchRest
|
||||||
# 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, force = false)
|
def update_design_doc(design_doc, db, force = false)
|
||||||
|
design_doc['couchrest-hash'] = design_doc.checksum
|
||||||
saved = stored_design_doc(db)
|
saved = stored_design_doc(db)
|
||||||
if saved
|
if saved
|
||||||
changes = force
|
if force || saved['couchrest-hash'] != design_doc['couchrest-hash']
|
||||||
design_doc['views'].each do |name, view|
|
saved.merge!(design_doc)
|
||||||
if !compare_views(saved['views'][name], view)
|
|
||||||
changes = true
|
|
||||||
saved['views'][name] = view
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if changes
|
|
||||||
db.save_doc(saved)
|
db.save_doc(saved)
|
||||||
end
|
end
|
||||||
design_doc
|
|
||||||
else
|
else
|
||||||
design_doc.database = db
|
db.save_doc(design_doc)
|
||||||
design_doc.save
|
|
||||||
design_doc
|
|
||||||
end
|
end
|
||||||
|
design_doc
|
||||||
end
|
end
|
||||||
|
|
||||||
# Return true if the two views match
|
# Return true if the two views match
|
||||||
|
|
|
@ -90,6 +90,13 @@ module CouchRest
|
||||||
result ? all.last : limit(1).descending.all.last
|
result ? all.last : limit(1).descending.all.last
|
||||||
end
|
end
|
||||||
|
|
||||||
|
# Return the number of documents in the currently defined result set.
|
||||||
|
# Use <tt>#count</tt> for the total number of documents regardless
|
||||||
|
# of the current limit defined.
|
||||||
|
def length
|
||||||
|
docs.length
|
||||||
|
end
|
||||||
|
|
||||||
# Perform a count operation based on the current view. If the view
|
# Perform a count operation based on the current view. If the view
|
||||||
# can be reduced, the reduce will be performed and return the first
|
# can be reduced, the reduce will be performed and return the first
|
||||||
# value. This is okay for most simple queries, but may provide
|
# value. This is okay for most simple queries, but may provide
|
||||||
|
@ -383,30 +390,24 @@ module CouchRest
|
||||||
def execute
|
def execute
|
||||||
return self.result if result
|
return self.result if result
|
||||||
raise "Database must be defined in model or view!" if use_database.nil?
|
raise "Database must be defined in model or view!" if use_database.nil?
|
||||||
retryable = true
|
|
||||||
# Remove the reduce value if its not needed
|
# Remove the reduce value if its not needed
|
||||||
query.delete(:reduce) unless can_reduce?
|
query.delete(:reduce) unless can_reduce?
|
||||||
begin
|
|
||||||
self.result = model.design_doc.view_on(use_database, name, query.reject{|k,v| v.nil?})
|
# Save the design doc for the current database. This should be efficient
|
||||||
rescue RestClient::ResourceNotFound => e
|
# and check for changes
|
||||||
if retryable
|
|
||||||
model.save_design_doc(use_database)
|
model.save_design_doc(use_database)
|
||||||
retryable = false
|
|
||||||
retry
|
self.result = model.design_doc.view_on(use_database, name, query.reject{|k,v| v.nil?})
|
||||||
else
|
|
||||||
raise e
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
|
|
||||||
# Class Methods
|
# Class Methods
|
||||||
class << self
|
class << self
|
||||||
|
|
||||||
# Simplified view creation. A new view will be added to the
|
# Simplified view creation. A new view will be added to the
|
||||||
# provided model's design document using the name and options.
|
# provided model's design document using the name and options.
|
||||||
#
|
#
|
||||||
# If the view name starts with "by_" and +:by+ is not provided in
|
# If the view name starts with "by_" and +:by+ is not provided in
|
||||||
# the options, the new view's map method will be interpretted and
|
# the options, the new view's map method will be interpreted and
|
||||||
# generated automatically. For example:
|
# generated automatically. For example:
|
||||||
#
|
#
|
||||||
# View.create(Meeting, "by_date_and_name")
|
# View.create(Meeting, "by_date_and_name")
|
||||||
|
|
15
lib/couchrest/model/support/couchrest_database.rb
Normal file
15
lib/couchrest/model/support/couchrest_database.rb
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
|
||||||
|
CouchRest::Database.class_eval do
|
||||||
|
|
||||||
|
alias :delete_orig! :delete!
|
||||||
|
def delete!
|
||||||
|
clear_model_fresh_cache
|
||||||
|
delete_orig!
|
||||||
|
end
|
||||||
|
|
||||||
|
# If the database is deleted, ensure that the design docs will be refreshed.
|
||||||
|
def clear_model_fresh_cache
|
||||||
|
::CouchRest::Model::Base.subclasses.each{|klass| klass.req_design_doc_refresh if klass.respond_to?(:req_design_doc_refresh)}
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
24
lib/couchrest/model/support/couchrest_design.rb
Normal file
24
lib/couchrest/model/support/couchrest_design.rb
Normal file
|
@ -0,0 +1,24 @@
|
||||||
|
|
||||||
|
CouchRest::Design.class_eval do
|
||||||
|
|
||||||
|
# Calculate a checksum of the Design document. Used for ensuring the latest
|
||||||
|
# version has been sent to the database.
|
||||||
|
#
|
||||||
|
# This will generate an flatterned, ordered array of all the elements of the
|
||||||
|
# design document, convert to string then generate an MD5 Hash. This should
|
||||||
|
# result in a consisitent Hash accross all platforms.
|
||||||
|
#
|
||||||
|
def checksum
|
||||||
|
# create a copy of basic elements
|
||||||
|
base = self.dup
|
||||||
|
base.delete('_id')
|
||||||
|
base.delete('_rev')
|
||||||
|
result = nil
|
||||||
|
flatten =
|
||||||
|
lambda{|v|
|
||||||
|
v.is_a?(Hash) ? v.flatten.map{|v| flatten.call(v)}.flatten : v
|
||||||
|
}
|
||||||
|
Digest::MD5.hexdigest(flatten.call(base).sort.join(''))
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
|
@ -45,7 +45,8 @@ require "couchrest/model/designs"
|
||||||
require "couchrest/model/designs/view"
|
require "couchrest/model/designs/view"
|
||||||
|
|
||||||
# Monkey patches applied to couchrest
|
# Monkey patches applied to couchrest
|
||||||
require "couchrest/model/support/couchrest"
|
require "couchrest/model/support/couchrest_database"
|
||||||
|
require "couchrest/model/support/couchrest_design"
|
||||||
# Core Extensions
|
# Core Extensions
|
||||||
require "couchrest/model/core_extensions/hash"
|
require "couchrest/model/core_extensions/hash"
|
||||||
require "couchrest/model/core_extensions/time_parsing"
|
require "couchrest/model/core_extensions/time_parsing"
|
||||||
|
|
|
@ -163,6 +163,13 @@ describe "Design View" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "#length" do
|
||||||
|
it "should provide a length from the docs array" do
|
||||||
|
@obj.should_receive(:docs).and_return([1, 2, 3])
|
||||||
|
@obj.length.should eql(3)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "#count" do
|
describe "#count" do
|
||||||
it "should raise an error if view prepared for group" do
|
it "should raise an error if view prepared for group" do
|
||||||
@obj.should_receive(:query).and_return({:group => true})
|
@obj.should_receive(:query).and_return({:group => true})
|
||||||
|
|
Loading…
Reference in a new issue