Demoting collection support, using latest couchrest, ensuring reduce always included when needed
This commit is contained in:
parent
d1baf99324
commit
9e1f4282f6
8 changed files with 135 additions and 113 deletions
12
Gemfile.lock
12
Gemfile.lock
|
@ -3,7 +3,7 @@ PATH
|
|||
specs:
|
||||
couchrest_model (1.1.0.beta)
|
||||
activemodel (~> 3.0.0)
|
||||
couchrest (~> 1.0.1)
|
||||
couchrest (~> 1.0.2)
|
||||
mime-types (~> 1.15)
|
||||
railties (~> 3.0.0)
|
||||
tzinfo (~> 0.3.22)
|
||||
|
@ -28,10 +28,10 @@ GEM
|
|||
i18n (~> 0.4)
|
||||
activesupport (3.0.4)
|
||||
builder (2.1.2)
|
||||
couchrest (1.0.1)
|
||||
json (>= 1.4.6)
|
||||
mime-types (>= 1.15)
|
||||
rest-client (>= 1.5.1)
|
||||
couchrest (1.0.2)
|
||||
json (~> 1.5.1)
|
||||
mime-types (~> 1.15)
|
||||
rest-client (~> 1.6.1)
|
||||
diff-lcs (1.1.2)
|
||||
erubis (2.6.6)
|
||||
abstract (>= 1.0.0)
|
||||
|
@ -67,7 +67,7 @@ PLATFORMS
|
|||
|
||||
DEPENDENCIES
|
||||
activemodel (~> 3.0.0)
|
||||
couchrest (~> 1.0.1)
|
||||
couchrest (~> 1.0.2)
|
||||
couchrest_model!
|
||||
mime-types (~> 1.15)
|
||||
rack-test (>= 0.5.7)
|
||||
|
|
|
@ -23,7 +23,7 @@ Gem::Specification.new do |s|
|
|||
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
||||
s.require_paths = ["lib"]
|
||||
|
||||
s.add_dependency(%q<couchrest>, "~> 1.0.1")
|
||||
s.add_dependency(%q<couchrest>, "~> 1.0.2")
|
||||
s.add_dependency(%q<mime-types>, "~> 1.15")
|
||||
s.add_dependency(%q<activemodel>, "~> 3.0.0")
|
||||
s.add_dependency(%q<tzinfo>, "~> 0.3.22")
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
|
||||
* Minor enhancements:
|
||||
* A yield parameter in an anonymous casted model property block is no longer required (@samlown)
|
||||
* Narrow the rescued exception to avoid catching class evaluation errors that has nothing to to with the association (thanks Simone Carletti)
|
||||
* Fix validate uniqueness test that was never executed (thanks Simone Carletti)
|
||||
* Adds a #reload method to reload document attributes (thanks Simone Carletti)
|
||||
* Narrow the rescued exception to avoid catching class evaluation errors that has nothing to to with the association (thanks Simone Carletti)
|
||||
* Fix validate uniqueness test that was never executed (thanks Simone Carletti)
|
||||
* Adds a #reload method to reload document attributes (thanks Simone Carletti)
|
||||
* CollectionProxy no longer provided by default with simple views (pending deprication)
|
||||
|
||||
== CouchRest Model 1.0.0
|
||||
|
||||
|
|
|
@ -85,9 +85,14 @@ module CouchRest
|
|||
end
|
||||
|
||||
# returns stored defaults if there is a view named this in the design doc
|
||||
def has_view?(view)
|
||||
view = view.to_s
|
||||
design_doc && design_doc['views'] && design_doc['views'][view]
|
||||
def has_view?(name)
|
||||
design_doc && design_doc.has_view?(name)
|
||||
end
|
||||
|
||||
# Check if the view can be reduced by checking to see if it has a
|
||||
# reduce function.
|
||||
def can_reduce_view?(name)
|
||||
design_doc && design_doc.can_reduce_view?(name)
|
||||
end
|
||||
|
||||
# Dispatches to any named view.
|
||||
|
@ -127,12 +132,9 @@ module CouchRest
|
|||
if raw || (opts.has_key?(:include_docs) && opts[:include_docs] == false)
|
||||
fetch_view(db, name, opts, &block)
|
||||
else
|
||||
if block.nil?
|
||||
collection_proxy_for(design_doc, name, opts.merge({:database => db, :include_docs => true}))
|
||||
else
|
||||
view = fetch_view db, name, opts.merge({:include_docs => true}), &block
|
||||
view['rows'].collect{|r|build_from_database(r['doc'])} if view['rows']
|
||||
end
|
||||
opts = opts.merge(:include_docs => true)
|
||||
view = fetch_view db, name, opts, &block
|
||||
view['rows'].collect{|r| build_from_database(r['doc'])} if view['rows']
|
||||
end
|
||||
end
|
||||
|
||||
|
|
89
spec/couchrest/collection_spec.rb
Normal file
89
spec/couchrest/collection_spec.rb
Normal file
|
@ -0,0 +1,89 @@
|
|||
require File.expand_path("../../spec_helper", __FILE__)
|
||||
require File.join(FIXTURE_PATH, 'more', 'article')
|
||||
|
||||
describe "Collections" do
|
||||
|
||||
before(:all) do
|
||||
reset_test_db!
|
||||
Article.refresh_design_doc
|
||||
titles = ["very uniq one", "really interesting", "some fun",
|
||||
"really awesome", "crazy bob", "this rocks", "super rad"]
|
||||
titles.each_with_index do |title,i|
|
||||
a = Article.new(:title => title, :date => Date.today)
|
||||
a.save
|
||||
end
|
||||
|
||||
titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
|
||||
"yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
|
||||
titles.each_with_index do |title,i|
|
||||
a = Article.new(:title => title, :date => Date.today - 1)
|
||||
a.save
|
||||
end
|
||||
end
|
||||
it "should return a proxy that looks like an array of 7 Article objects" do
|
||||
articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
|
||||
:key => Date.today, :include_docs => true)
|
||||
articles.class.should == Array
|
||||
articles.size.should == 7
|
||||
end
|
||||
it "should provide a class method for paginate" do
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 3
|
||||
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 2, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 3
|
||||
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 1
|
||||
end
|
||||
it "should provide a class method for paginated_each" do
|
||||
options = { :design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 1, :descending => true, :key => Date.today,
|
||||
:include_docs => true }
|
||||
Article.paginated_each(options) do |a|
|
||||
a.should_not be_nil
|
||||
end
|
||||
end
|
||||
it "should provide a class method to get a collection for a view" do
|
||||
articles = Article.find_all_article_details(:key => Date.today)
|
||||
articles.class.should == Array
|
||||
articles.size.should == 7
|
||||
end
|
||||
it "should get a subset of articles using paginate" do
|
||||
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
||||
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 2, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 3, :per_page => 3).size.should == 1
|
||||
end
|
||||
it "should get all articles, a few at a time, using paginated each" do
|
||||
articles = Article.collection_proxy_for('Article', 'by_date', :key => Date.today, :include_docs => true)
|
||||
articles.paginated_each(:per_page => 3) do |a|
|
||||
a.should_not be_nil
|
||||
end
|
||||
end
|
||||
|
||||
it "should raise an exception if design_doc is not provided" do
|
||||
lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error
|
||||
lambda{Article.paginate(:view_name => 'by_date')}.should raise_error
|
||||
end
|
||||
it "should raise an exception if view_name is not provided" do
|
||||
lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
|
||||
lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
|
||||
end
|
||||
it "should be able to span multiple keys" do
|
||||
articles = Article.collection_proxy_for('Article', 'by_date', :startkey => Date.today - 1, :endkey => Date.today, :include_docs => true)
|
||||
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 3, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 5, :per_page => 3).size.should == 1
|
||||
end
|
||||
it "should pass database parameter to pager" do
|
||||
proxy = mock(:proxy)
|
||||
proxy.stub!(:paginate)
|
||||
::CouchRest::Model::Collection::CollectionProxy.should_receive(:new).with('database', anything(), anything(), anything(), anything()).and_return(proxy)
|
||||
Article.paginate(:design_doc => 'Article', :view_name => 'by_date', :database => 'database')
|
||||
end
|
||||
|
||||
end
|
|
@ -27,6 +27,20 @@ describe "Model views" do
|
|||
end
|
||||
|
||||
end
|
||||
|
||||
describe "#has_view?" do
|
||||
it "should check the design doc" do
|
||||
Article.design_doc.should_receive(:has_view?).with(:test).and_return(true)
|
||||
Article.has_view?(:test).should be_true
|
||||
end
|
||||
end
|
||||
|
||||
describe "#can_reduce_view?" do
|
||||
it "should check if view has a reduce method" do
|
||||
Article.design_doc.should_receive(:can_reduce_view?).with(:test).and_return(true)
|
||||
Article.can_reduce_view?(:test).should be_true
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
describe "a model with simple views and a default param" do
|
||||
|
@ -184,6 +198,11 @@ describe "Model views" do
|
|||
course.title.should eql('bbb')
|
||||
end
|
||||
|
||||
it "should perform a search for first when reduce method present" do
|
||||
course = Course.first_from_view('by_active')
|
||||
course.should_not be_nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
describe "a ducktype view" do
|
||||
|
@ -374,96 +393,5 @@ describe "Model views" do
|
|||
Article.design_doc["views"].keys.should include("by_updated_at")
|
||||
end
|
||||
end
|
||||
|
||||
describe "with a collection" do
|
||||
before(:all) do
|
||||
reset_test_db!
|
||||
titles = ["very uniq one", "really interesting", "some fun",
|
||||
"really awesome", "crazy bob", "this rocks", "super rad"]
|
||||
titles.each_with_index do |title,i|
|
||||
a = Article.new(:title => title, :date => Date.today)
|
||||
a.save
|
||||
end
|
||||
|
||||
titles = ["yesterday very uniq one", "yesterday really interesting", "yesterday some fun",
|
||||
"yesterday really awesome", "yesterday crazy bob", "yesterday this rocks"]
|
||||
titles.each_with_index do |title,i|
|
||||
a = Article.new(:title => title, :date => Date.today - 1)
|
||||
a.save
|
||||
end
|
||||
end
|
||||
require 'date'
|
||||
it "should return a proxy that looks like an array of 7 Article objects" do
|
||||
articles = Article.by_date :key => Date.today
|
||||
articles.class.should == Array
|
||||
articles.size.should == 7
|
||||
end
|
||||
it "should get a subset of articles using paginate" do
|
||||
articles = Article.by_date :key => Date.today
|
||||
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 2, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 3, :per_page => 3).size.should == 1
|
||||
end
|
||||
it "should get all articles, a few at a time, using paginated each" do
|
||||
articles = Article.by_date :key => Date.today
|
||||
articles.paginated_each(:per_page => 3) do |a|
|
||||
a.should_not be_nil
|
||||
end
|
||||
end
|
||||
it "should provide a class method to access the collection directly" do
|
||||
articles = Article.collection_proxy_for('Article', 'by_date', :descending => true,
|
||||
:key => Date.today, :include_docs => true)
|
||||
articles.class.should == Array
|
||||
articles.size.should == 7
|
||||
end
|
||||
it "should provide a class method for paginate" do
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 3
|
||||
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 2, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 3
|
||||
|
||||
articles = Article.paginate(:design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 3, :descending => true, :key => Date.today, :include_docs => true)
|
||||
articles.size.should == 1
|
||||
end
|
||||
it "should provide a class method for paginated_each" do
|
||||
options = { :design_doc => 'Article', :view_name => 'by_date',
|
||||
:per_page => 3, :page => 1, :descending => true, :key => Date.today,
|
||||
:include_docs => true }
|
||||
Article.paginated_each(options) do |a|
|
||||
a.should_not be_nil
|
||||
end
|
||||
end
|
||||
it "should provide a class method to get a collection for a view" do
|
||||
articles = Article.find_all_article_details(:key => Date.today)
|
||||
articles.class.should == Array
|
||||
articles.size.should == 7
|
||||
end
|
||||
it "should raise an exception if design_doc is not provided" do
|
||||
lambda{Article.collection_proxy_for(nil, 'by_date')}.should raise_error
|
||||
lambda{Article.paginate(:view_name => 'by_date')}.should raise_error
|
||||
end
|
||||
it "should raise an exception if view_name is not provided" do
|
||||
lambda{Article.collection_proxy_for('Article', nil)}.should raise_error
|
||||
lambda{Article.paginate(:design_doc => 'Article')}.should raise_error
|
||||
end
|
||||
it "should be able to span multiple keys" do
|
||||
articles = Article.by_date :startkey => Date.today, :endkey => Date.today - 1
|
||||
articles.paginate(:page => 1, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 2, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 3, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 4, :per_page => 3).size.should == 3
|
||||
articles.paginate(:page => 5, :per_page => 3).size.should == 1
|
||||
end
|
||||
it "should pass database parameter to pager" do
|
||||
proxy = mock(:proxy)
|
||||
proxy.stub!(:paginate)
|
||||
::CouchRest::Model::Collection::CollectionProxy.should_receive(:new).with('database', anything(), anything(), anything(), anything()).and_return(proxy)
|
||||
Article.paginate(:design_doc => 'Article', :view_name => 'by_date', :database => 'database')
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
2
spec/fixtures/more/article.rb
vendored
2
spec/fixtures/more/article.rb
vendored
|
@ -18,7 +18,7 @@ class Article < CouchRest::Model::Base
|
|||
:reduce =>
|
||||
"function(keys, values, rereduce) {
|
||||
return sum(values);
|
||||
}"
|
||||
}"
|
||||
|
||||
property :date, Date
|
||||
property :slug, :read_only => true
|
||||
|
|
6
spec/fixtures/more/course.rb
vendored
6
spec/fixtures/more/course.rb
vendored
|
@ -13,13 +13,15 @@ class Course < CouchRest::Model::Base
|
|||
property :hours, Integer
|
||||
property :profit, BigDecimal
|
||||
property :started_on, :type => Date
|
||||
property :updated_at, :type => DateTime
|
||||
property :updated_at, DateTime
|
||||
property :active, :type => TrueClass
|
||||
property :very_active, :type => TrueClass
|
||||
property :klass, :type => Class
|
||||
|
||||
|
||||
view_by :title
|
||||
view_by :title, :active
|
||||
view_by :dept, :ducktype => true
|
||||
|
||||
view_by :active, :map => "function(d) { if (d['#{model_type_key}'] == 'Course' && d['active']) { emit(d['updated_at'], 1); }}", :reduce => "function(k,v,r) { return sum(v); }"
|
||||
|
||||
end
|
||||
|
|
Loading…
Reference in a new issue