diff --git a/lib/couchrest/core/model.rb b/lib/couchrest/core/model.rb index 9b2560d..c0867d5 100644 --- a/lib/couchrest/core/model.rb +++ b/lib/couchrest/core/model.rb @@ -1,3 +1,5 @@ +require 'digest/md5' + # = CouchRest::Model - ORM, the CouchDB way module CouchRest # = CouchRest::Model - ORM, the CouchDB way @@ -270,7 +272,7 @@ module CouchRest refresh_design_doc end raw = query.delete(:raw) - view_name = "#{type}/#{method_name}" + view_name = "#{design_doc_slug}/#{method_name}" view = fetch_view(view_name, query) if raw @@ -283,6 +285,11 @@ module CouchRest end end + # Fetch the generated design doc. Could raise an error if the generated views have not been queried yet. + def design_doc + database.get("_design/#{design_doc_slug}") + end + private def fetch_view view_name, opts @@ -301,26 +308,33 @@ module CouchRest end end - def design_doc_id - "_design/#{self.to_s}" + def design_doc_slug + return @design_doc_slug if @design_doc_slug && @@design_doc_fresh + funcs = [] + @@design_doc['views'].each do |name, view| + funcs << "#{name}/#{view}" + end + md5 = Digest::MD5.hexdigest(funcs.sort.join('')) + @design_doc_slug = "#{self.to_s}-#{md5}" end def default_design_doc { - "_id" => design_doc_id, "language" => "javascript", "views" => {} } end def refresh_design_doc - saved = database.get(design_doc_id) rescue nil + did = "_design/#{design_doc_slug}" + saved = database.get(did) rescue nil if saved @@design_doc['views'].each do |name, view| saved['views'][name] = view end database.save(saved) else + @@design_doc['_id'] = did database.save(@@design_doc) end @@design_doc_fresh = true @@ -408,6 +422,7 @@ module CouchRest def cast_keys return unless self.class.casts + # TODO move the argument checking to the cast method for early crashes self.class.casts.each do |k,v| next unless self[k] target = v[:as] diff --git a/spec/couchrest/core/model_spec.rb b/spec/couchrest/core/model_spec.rb index 4787770..9781357 100644 --- a/spec/couchrest/core/model_spec.rb +++ b/spec/couchrest/core/model_spec.rb @@ -336,7 +336,7 @@ describe CouchRest::Model do it "should create the design doc" do Article.by_date rescue nil - doc = Article.database.get("_design/Article") + doc = Article.design_doc doc['views']['by_date'].should_not be_nil end @@ -371,7 +371,7 @@ describe CouchRest::Model do end it "should create the design doc" do Article.by_user_id_and_date rescue nil - doc = Article.database.get("_design/Article") + doc = Article.design_doc doc['views']['by_date'].should_not be_nil end it "should sort correctly" do @@ -412,6 +412,24 @@ describe CouchRest::Model do end end + describe "adding a view" do + before(:each) do + Article.by_date + @design_docs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999" + end + it "should not create a design doc on view definition" do + Article.view_by :created_at + newdocs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999" + newdocs["rows"].length.should == @design_docs["rows"].length + end + it "should create a new design document on view access" do + Article.view_by :created_at + Article.by_created_at + newdocs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999" + newdocs["rows"].length.should == @design_docs["rows"].length + 1 + end + end + describe "destroying an instance" do before(:each) do @obj = Basic.new