compound-key views work

This commit is contained in:
Chris Anderson 2008-09-29 17:27:41 -07:00
parent 5e0cb81ad7
commit f408dfceb6
3 changed files with 70 additions and 15 deletions

View file

@ -15,6 +15,7 @@
require "rubygems" require "rubygems"
require 'json' require 'json'
require 'rest_client' require 'rest_client'
require 'extlib'
$:.unshift File.dirname(__FILE__) unless $:.unshift File.dirname(__FILE__) unless
$:.include?(File.dirname(__FILE__)) || $:.include?(File.dirname(__FILE__)) ||

View file

@ -1,7 +1,3 @@
require 'rubygems'
gem 'extlib'
require 'extlib'
module CouchRest module CouchRest
module Model module Model
class << self class << self
@ -148,19 +144,47 @@ module CouchRest
@@design_doc['views'][method_name] = { @@design_doc['views'][method_name] = {
'map' => map_function 'map' => map_function
} }
@@design_doc_fresh = false @@design_doc_fresh = false
self.meta_class.instance_eval do self.meta_class.instance_eval do
define_method method_name do define_method method_name do |args|
args ||= {}
unless @@design_doc_fresh unless @@design_doc_fresh
refresh_design_doc refresh_design_doc
end end
@@design_doc raw = args.delete(:raw)
view_name = "#{type}/#{method_name}"
if raw
fetch_view(view_name)
else
view = fetch_view(view_name)
# TODO this can be optimized once the include-docs patch is applied
view['rows'].collect{|r|new(database.get(r['id']))}
end
end end
end end
end end
private private
def fetch_view view_name
retryable = true
begin
database.view(view_name)
# the design doc could have been deleted by a rouge process
rescue RestClient::ResourceNotFound => e
if retryable
refresh_design_doc
retryable = false
retry
else
raise e
end
end
end
def design_doc_id def design_doc_id
"_design/#{self.to_s}" "_design/#{self.to_s}"
end end
@ -173,11 +197,13 @@ module CouchRest
} }
end end
def refresh_design_doc def refresh_design_doc
saved = database.get(design_doc_id) rescue nil saved = database.get(design_doc_id) rescue nil
if saved if saved
# merge the new views in and save if it needs to be saved @@design_doc['views'].each do |name, view|
saved['views'][name] = view
end
database.save(saved)
else else
database.save(@@design_doc) database.save(@@design_doc)
end end
@ -190,7 +216,7 @@ module CouchRest
def self.included(model) def self.included(model)
model.class_eval <<-EOS, __FILE__, __LINE__ model.class_eval <<-EOS, __FILE__, __LINE__
include Extlib::Hook include Extlib::Hook
register_instance_hooks :save #, :create, :update, :destroy register_instance_hooks :save, :create, :update #, :destroy
EOS EOS
end end
end # module Callbacks end # module Callbacks

View file

@ -22,6 +22,7 @@ class Article
key_writer :date key_writer :date
view_by :date view_by :date
view_by :user_id, :date
end end
describe CouchRest::Model do describe CouchRest::Model do
@ -189,7 +190,8 @@ describe CouchRest::Model do
describe "a model with simple views" do describe "a model with simple views" do
before(:all) do before(:all) do
written_at = Time.now - 24 * 3600 * 7 written_at = Time.now - 24 * 3600 * 7
["this and that", "also interesting", "more fun", "some junk"].each do |title| @titles = ["this and that", "also interesting", "more fun", "some junk"]
@titles.each do |title|
a = Article.new(:title => title) a = Article.new(:title => title)
a.date = written_at a.date = written_at
a.save a.save
@ -198,17 +200,43 @@ describe CouchRest::Model do
end end
it "should create the design doc" do it "should create the design doc" do
Article.by_date Article.by_date rescue nil
doc = Article.database.get("_design/Article") doc = Article.database.get("_design/Article")
doc['views']['by_date'].should_not be_nil doc['views']['by_date'].should_not be_nil
end end
it "should return the matching view result" do it "should return the matching raw view result" do
view = Article.by_date :raw => true view = Article.by_date :raw => true
# view.should == 'x' view['rows'].length.should == 4
# view['rows'].should == 4
end end
it "should return the matching object" do
articles = Article.by_date
articles.collect{|a|a.title}.should == @titles
end
end
describe "a model with a compound key view" do
before(:all) do
written_at = Time.now - 24 * 3600 * 7
@titles = ["uniq one", "even more interesting", "less fun", "not junk"]
@user_ids = ["quentin", "aaron"]
@titles.each_with_index do |title,i|
u = i % 2
a = Article.new(:title => title, :user_id => @user_ids[u])
a.date = written_at
a.save
written_at += 24 * 3600
end
end
it "should create the design doc" do
Article.by_user_id_and_date rescue nil
doc = Article.database.get("_design/Article")
doc['views']['by_date'].should_not be_nil
end
it "should sort correctly" do
articles = Article.by_user_id_and_date
# articles.should == 'x'
end
end end
end end