<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>lib/couch_potato/persistence/custom_view.rb</filename>
    </added>
    <added>
      <filename>lib/couch_potato/persistence/view_query.rb</filename>
    </added>
    <added>
      <filename>spec/custom_view_spec.rb</filename>
    </added>
    <added>
      <filename>spec/unit/view_query_spec.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -10,6 +10,8 @@ module CouchPotato
         before_destroy :update_lower_positions_after_destroy
         before_update :update_positions
         
+        #self.default_order ||= [:position]
+        
         def self.set_ordering_scope(scope)
           self.ordering_scope = scope
         end
@@ -33,10 +35,10 @@ module CouchPotato
       @old_position = MAX if new_document?
       return unless @old_position
       if position &lt; @old_position
-        new_lower_items = find_in_positions self.position, @old_position - 1
+        new_lower_items = find_in_positions(self.position, @old_position - 1).reject{|item| item._id == self._id}
         move new_lower_items, :down
       elsif position &gt; @old_position
-        new_higher_items = find_in_positions @old_position + 1, position
+        new_higher_items = find_in_positions(@old_position + 1, position).reject{|item| item._id == self._id}
         move new_higher_items, :up
       end
     end
@@ -69,16 +71,5 @@ module CouchPotato
       end
     end
   end
-  
-  module ExternalCollectionOrderedFindExtension
-    def items
-      if @item_class.property_names.include?(:position)
-        super @item_class, @owner_id_attribute_name =&gt; owner_id, :position =&gt; 1..CouchPotato::Ordering::MAX
-      else
-        super
-      end
-    end
-  end
-  CouchPotato::Persistence::ExternalCollection.send :include, ExternalCollectionOrderedFindExtension
 end
 </diff>
      <filename>lib/couch_potato/ordering.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,6 +9,8 @@ require File.dirname(__FILE__) + '/persistence/json'
 require File.dirname(__FILE__) + '/persistence/bulk_save_queue'
 require File.dirname(__FILE__) + '/persistence/find'
 require File.dirname(__FILE__) + '/persistence/dirty_attributes'
+require File.dirname(__FILE__) + '/persistence/custom_view'
+require File.dirname(__FILE__) + '/persistence/view_query'
 
 module CouchPotato
   module Persistence
@@ -18,11 +20,12 @@ module CouchPotato
     
     def self.included(base)
       base.send :extend, ClassMethods, Find
-      base.send :include, Callbacks, Properties, Validatable, Json, DirtyAttributes
+      base.send :include, Callbacks, Properties, Validatable, Json, DirtyAttributes, CustomView
       base.class_eval do
         attr_accessor :_id, :_rev, :_attachments, :_deleted, :created_at, :updated_at
         attr_reader :bulk_save_queue
         alias_method :id, :_id
+        cattr_accessor :default_order
       end
     end
     
@@ -99,6 +102,12 @@ module CouchPotato
       other.class == self.class &amp;&amp; self.to_json == other.to_json
     end
     
+    def inspect
+      self.class.property_names.inject(&quot;&lt;#{self.class.name} _id: '#{_id}', _rev: '#{_rev}' &quot;) do |res, property_name|
+        res &lt;&lt; &quot;#{property_name}: #{self.send(property_name)} &quot;
+      end &lt;&lt; '&gt;'
+    end
+    
     private
     
     def create_document</diff>
      <filename>lib/couch_potato/persistence.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,7 +1,7 @@
 module CouchPotato
   module Persistence
     class BulkSaveQueue
-      attr_reader :callbacks
+      attr_reader :callbacks, :instances
       
       def initialize
         @other_queues = []</diff>
      <filename>lib/couch_potato/persistence/bulk_save_queue.rb</filename>
    </modified>
    <modified>
      <diff>@@ -59,7 +59,7 @@ module CouchPotato
       
       def items
         unless @items
-          @items = Finder.new.find @item_class, @owner_id_attribute_name =&gt; owner_id
+          @items = Finder.new.find @item_class, {@owner_id_attribute_name =&gt; owner_id}
           @original_item_ids = @items.map(&amp;:_id)
         end
         @items</diff>
      <filename>lib/couch_potato/persistence/external_collection.rb</filename>
    </modified>
    <modified>
      <diff>@@ -8,107 +8,57 @@ module CouchPotato
       # value can also be a range which will do a range search with startkey/endkey
       # WARNING: calling this methods creates a new view in couchdb if it's not present already so don't overuse this
       def find(clazz, conditions = {}, view_options = {})
-        params = view_parameters(clazz, conditions, view_options)
-        to_instances clazz, query_view!(params)
+        to_instances clazz, query_view(clazz, conditions, view_options_with_default_order(clazz, view_options))
       end
       
       def count(clazz, conditions = {}, view_options = {})
-        params = view_parameters(clazz, conditions, view_options)
-        query_view!(params, '_count')['rows'].first.try(:[], 'value') || 0
+        query_view(clazz, conditions, view_options, '_count', count_reduce_function)['rows'].first.try(:[], 'value') || 0
       end
       
       private
       
-      def query_view!(params, view_postfix = nil)
-        begin
-          query_view params, view_postfix
-        rescue RestClient::ResourceNotFound =&gt; e
-          create_view params
-          query_view params, view_postfix
+      def view_options_with_default_order(clazz, view_options)
+        if clazz.default_order
+          view_options[:order] ||= clazz.default_order
         end
+        view_options
+      end
+      
+      def query_view(clazz, conditions, view_options, view_postfix = nil, reduce_fuction = nil)
+        ViewQuery.new(design_document(clazz), view(conditions, view_options[:order]) + view_postfix.to_s, map_function(clazz, search_fields(conditions, view_options[:order])), reduce_fuction, conditions, view_options).query_view!
       end
       
       def db(name = nil)
         ::CouchPotato::Persistence.Db(name)
       end
       
-      def create_view(params)
-        # in couchdb 0.9 we could use only 1 view and pass reduce=false for find and count with reduce
-        design_doc = db.get &quot;_design/#{params[:design_document]}&quot; rescue nil
-        db.save({
-          &quot;_id&quot; =&gt; &quot;_design/#{params[:design_document]}&quot;,
-          :views =&gt; {
-            params[:view] =&gt; {
-              :map =&gt; map_function(params)
-            },
-            params[:view] + '_count' =&gt; {
-              :map =&gt; map_function(params),
-              :reduce =&gt; &quot;function(keys, values) {
-                return values.length;
-              }&quot;
-            }
-          }
-        }.merge(design_doc ? {'_rev' =&gt; design_doc['_rev']} : {}))
+      def design_document(clazz)
+        clazz.name.underscore
       end
       
-      def map_function(params)
+      def map_function(clazz, search_fields)
         &quot;function(doc) {
-          if(doc.ruby_class == '#{params[:class]}') {
+          if(doc.ruby_class == '#{clazz}') {
             emit(
-              [#{params[:search_fields].map{|attr| &quot;doc[\&quot;#{attr}\&quot;]&quot;}.join(', ')}], doc
+              [#{search_fields.map{|attr| &quot;doc[\&quot;#{attr}\&quot;]&quot;}.join(', ')}], doc
                 );
           }
         }&quot;
       end
       
-      def to_instances(clazz, query_result)
-        query_result['rows'].map{|doc| doc['value']}.map{|json| clazz.json_create json}
-      end
-      
-      def query_view(params, view_postfix)
-        db.view params[:view_url] + view_postfix.to_s, search_keys(params)
-      end
-      
-      def search_keys(params)
-        if params[:search_values].select{|v| v.is_a?(Range)}.any? || params[:order]
-          {:startkey =&gt; startkey(params), :endkey =&gt; endkey(params)}.merge(params[:view_options])
-        elsif params[:search_values].select{|v| v.is_a?(Array)}.any?
-          {:keys =&gt; prepare_multi_key_search(params[:search_values])}.merge(params[:view_options])
-        else
-          {:key =&gt; params[:search_values]}.merge(params[:view_options])
-        end
-      end
-      
-      def startkey(params)
-        params[:search_values].map{|v| v.is_a?(Range) ? v.first : v}
+      def count_reduce_function
+        &quot;function(keys, values) {
+          return values.length;
+        }&quot;
       end
       
-      def endkey(params)
-        params[:search_values].map{|v| v.is_a?(Range) ? v.last : v || {}}
+      def view(conditions, order)
+        &quot;by_#{view_name(conditions, order)}&quot;
       end
       
-      def prepare_multi_key_search(values)
-        array = values.select{|v| v.is_a?(Array)}.first
-        index = values.index array
-        array.map do |item|
-          copy = values.dup
-          copy[index] = item
-          copy
-        end
-      end
       
-      def view_parameters(clazz, conditions, view_options)
-        order = view_options.delete(:order)
-        {
-          :class =&gt; clazz,
-          :design_document =&gt; clazz.name.underscore,
-          :search_fields =&gt; sorted_keys(conditions, order),
-          :search_values =&gt; sorted_keys(conditions, order).map{|key| conditions[key]},
-          :view_options =&gt; view_options,
-          :order =&gt; order,
-          :view =&gt; &quot;by_#{view_name(conditions, order)}&quot;,
-          :view_url =&gt; &quot;#{clazz.name.underscore}/by_#{view_name(conditions, order)}&quot;
-        }
+      def search_fields(conditions, order)
+        sorted_keys(conditions, order)
       end
       
       def sorted_keys(conditions, order)
@@ -118,6 +68,11 @@ module CouchPotato
       def view_name(conditions, order)
         sorted_keys(conditions, order).join('_and_')
       end
+      
+      def to_instances(clazz, query_result)
+        query_result['rows'].map{|doc| doc['value']}.map{|json| clazz.json_create json}
+      end
+      
     end
   end
 end
\ No newline at end of file</diff>
      <filename>lib/couch_potato/persistence/finder.rb</filename>
    </modified>
    <modified>
      <diff>@@ -60,6 +60,10 @@ describe 'has_many stored separately' do
   end
   
   describe &quot;all&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
+    
     it &quot;should find all dependent objects by search conditions&quot; do
       commenter = Commenter.create!
       comment1 = commenter.comments.create! :title =&gt; 'my title'
@@ -83,6 +87,10 @@ describe 'has_many stored separately' do
   end
   
   describe &quot;count&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
+    
     it &quot;should count the dependent objects by search criteria&quot; do
       commenter = Commenter.create!
       commenter.comments.create! :title =&gt; 'my title'
@@ -101,6 +109,9 @@ describe 'has_many stored separately' do
   end
   
   describe &quot;first&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
     it &quot;should find the first dependent object by search conditions&quot; do
       commenter = Commenter.create!
       comment1 = commenter.comments.create! :title =&gt; 'my title'
@@ -109,13 +120,17 @@ describe 'has_many stored separately' do
     end
     
     it &quot;should return the first dependent object&quot; do
-      comment1 = @commenter.comments.build :title =&gt; 'my title'
-      comment2 = @commenter.comments.build :title =&gt; 'my title2'
+      Comment.default_order = [:_id]
+      comment1 = @commenter.comments.build :title =&gt; 'my title', :_id =&gt; '1'
+      comment2 = @commenter.comments.build :title =&gt; 'my title2', :_id =&gt; '2'
       @commenter.comments.first.should == comment1
     end    
   end
   
   describe &quot;create&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
     it &quot;should persist child objects&quot; do
       @commenter.comments.build(:title =&gt; 'my title')
       @commenter.save!
@@ -150,6 +165,9 @@ describe 'has_many stored separately' do
   end
   
   describe &quot;update&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
     it &quot;should persist child objects&quot; do
       comment = @commenter.comments.build(:title =&gt; 'my title')
       @commenter.save!
@@ -179,6 +197,9 @@ describe 'has_many stored separately' do
   end
   
   describe &quot;destroy&quot; do
+    before(:each) do
+      Commenter.db.delete!
+    end
     
     class AdminComment
       include CouchPotato::Persistence</diff>
      <filename>spec/has_many_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -25,14 +25,14 @@ describe CouchPotato::Ordering do
       photo = @album.photos.create!
       photo.position.should == 1
     end
-    
+
     it &quot;should increase the position when adding a second item&quot; do
       @album.photos.create!
       photo = @album.photos.create!
       photo.position.should == 2
     end
   end
-  
+
   describe 'insert' do
     it &quot;should increse the position of the items that are now lower than this&quot; do
       photo1 = @album.photos.create!
@@ -60,14 +60,14 @@ describe CouchPotato::Ordering do
       CouchPotato::Persistence.Db.get(photo2._id)['position'].should == 1
     end
   end
-  
+
   it &quot;should order by position&quot; do
-    @album.photos.create!
-    @album.photos.create! :position =&gt; 1
-    @album = Album.get @album._id
-    @album.photos.map(&amp;:position).should == [1,2]
+      @album.photos.create!
+      @album.photos.create! :position =&gt; 1
+      @album = Album.get @album._id
+      @album.photos.map(&amp;:position).should == [1,2]
   end
-  
+
   describe &quot;destroy&quot; do
     it &quot;should decrease the position of the lower items&quot; do
       photo1 = @album.photos.create!
@@ -76,19 +76,19 @@ describe CouchPotato::Ordering do
       CouchPotato::Persistence.Db.get(photo2._id)['position'].should == 1
     end
   end
-  
+
   describe &quot;scoping&quot; do
     it &quot;should only update objects within the scope&quot; do
       photo1 = @album.photos.create!
       photo2 = @album.photos.create!
       album2 = Album.create!
       album2.photos.create!
-      
+
       photo2.position = 1
       photo2.save!
-      
+
       album2.photos.first.position.should == 1
     end
   end
-  
+    
 end
\ No newline at end of file</diff>
      <filename>spec/ordering_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,3 +29,12 @@ class Comment
   property :title
   belongs_to :commenter
 end
+
+
+def sp(*args)
+  puts '&lt;pre&gt;'
+  args.each do |arg|
+    puts &quot;#{arg.inspect}&quot;
+  end
+  puts '&lt;/pre&gt;'
+end
\ No newline at end of file</diff>
      <filename>spec/spec_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -15,6 +15,12 @@ describe CouchPotato::Persistence::Finder, 'find' do
     @database.should_receive(:view).with(anything, {:key =&gt; ['xyz', 'abc']}).and_return({'rows' =&gt; []})
     CouchPotato::Persistence::Finder.new.find Comment, {:name =&gt; 'xyz', :title =&gt; 'abc'}
   end
+  
+  it &quot;should order by default order of class&quot; do
+    Comment.stub!(:default_order).and_return([:title])
+    @database.should_receive(:view).with('comment/by_title', {:startkey =&gt; [nil], :endkey =&gt; [{}]}).and_return({'rows' =&gt; []})
+    CouchPotato::Persistence::Finder.new.find Comment, {}
+  end
 end
 
 describe CouchPotato::Persistence::Finder, &quot;with sort&quot; do</diff>
      <filename>spec/unit/finder_spec.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>87641f0001d955cedcf977bcfa156dcd96ba7469</id>
    </parent>
    <parent>
      <id>c0280d6979de08eeca530bfbbcd8a90abe23b39a</id>
    </parent>
  </parents>
  <author>
    <name>Alexander Lang</name>
    <email>alex@upstream-berlin.com</email>
  </author>
  <url>http://github.com/langalex/couch_potato/commit/9dc7b99b7a73727432979b3947064fb2f6d9622f</url>
  <id>9dc7b99b7a73727432979b3947064fb2f6d9622f</id>
  <committed-date>2009-01-23T04:37:13-08:00</committed-date>
  <authored-date>2009-01-23T04:37:13-08:00</authored-date>
  <message>added default order</message>
  <tree>4d62b758e5939ff650abb1d54e4d2a79588a9eb0</tree>
  <committer>
    <name>Alexander Lang</name>
    <email>alex@upstream-berlin.com</email>
  </committer>
</commit>
