ClassProxy provides class-level methods on a dynamically chosen database.
Examples: db = CouchRest::Database.new(...) articles = Article.on(db) articles.all { ... } articles.by_title { ... } u = articles.get("someid") u = articles.new(:title => "I like plankton") u.save # saved on the correct database
This commit is contained in:
parent
af6ac7df89
commit
c4b49baecf
108
lib/couchrest/mixins/class_proxy.rb
Normal file
108
lib/couchrest/mixins/class_proxy.rb
Normal file
|
@ -0,0 +1,108 @@
|
||||||
|
module CouchRest
|
||||||
|
module Mixins
|
||||||
|
module ClassProxy
|
||||||
|
|
||||||
|
def self.included(base)
|
||||||
|
base.extend(ClassMethods)
|
||||||
|
end
|
||||||
|
|
||||||
|
module ClassMethods
|
||||||
|
|
||||||
|
# Return a proxy object which represents a model class on a
|
||||||
|
# chosen database instance. This allows you to DRY operations
|
||||||
|
# where a database is chosen dynamically.
|
||||||
|
#
|
||||||
|
# ==== Example:
|
||||||
|
#
|
||||||
|
# db = CouchRest::Database.new(...)
|
||||||
|
# articles = Article.on(db)
|
||||||
|
#
|
||||||
|
# articles.all { ... }
|
||||||
|
# articles.by_title { ... }
|
||||||
|
#
|
||||||
|
# u = articles.get("someid")
|
||||||
|
#
|
||||||
|
# u = articles.new(:title => "I like plankton")
|
||||||
|
# u.save # saved on the correct database
|
||||||
|
|
||||||
|
def on(database)
|
||||||
|
Proxy.new(self, database)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
class Proxy #:nodoc:
|
||||||
|
def initialize(klass, database)
|
||||||
|
@klass = klass
|
||||||
|
@database = database
|
||||||
|
end
|
||||||
|
|
||||||
|
# ExtendedDocument
|
||||||
|
|
||||||
|
def new(*args)
|
||||||
|
doc = @klass.new(*args)
|
||||||
|
doc.database = @database
|
||||||
|
doc
|
||||||
|
end
|
||||||
|
|
||||||
|
def method_missing(m, *args, &block)
|
||||||
|
if has_view?(m)
|
||||||
|
query = args.shift || {}
|
||||||
|
view(m, query, *args, &block)
|
||||||
|
else
|
||||||
|
super
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mixins::DocumentQueries
|
||||||
|
|
||||||
|
def all(opts = {}, &block)
|
||||||
|
@klass.all({:database => @database}.merge(opts), &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def first(opts = {})
|
||||||
|
@klass.first({:database => @database}.merge(opts))
|
||||||
|
end
|
||||||
|
|
||||||
|
def get(id)
|
||||||
|
@klass.get(id, @database)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mixins::Views
|
||||||
|
|
||||||
|
def has_view?(view)
|
||||||
|
@klass.has_view?(view)
|
||||||
|
end
|
||||||
|
|
||||||
|
def view(name, query={}, &block)
|
||||||
|
@klass.view(name, {:database => @database}.merge(query), &block)
|
||||||
|
end
|
||||||
|
|
||||||
|
def all_design_doc_versions
|
||||||
|
@klass.all_design_doc_versions(@database)
|
||||||
|
end
|
||||||
|
|
||||||
|
def cleanup_design_docs!
|
||||||
|
@klass.cleanup_design_docs!(@database)
|
||||||
|
end
|
||||||
|
|
||||||
|
# Mixins::DesignDoc
|
||||||
|
|
||||||
|
def design_doc
|
||||||
|
@klass.design_doc
|
||||||
|
end
|
||||||
|
|
||||||
|
def design_doc_fresh
|
||||||
|
@klass.design_doc_fresh
|
||||||
|
end
|
||||||
|
|
||||||
|
def refresh_design_doc
|
||||||
|
@klass.refresh_design_doc
|
||||||
|
end
|
||||||
|
|
||||||
|
def save_design_doc
|
||||||
|
@klass.save_design_doc_on(@database)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
|
@ -3,4 +3,5 @@ require File.join(File.dirname(__FILE__), 'document_queries')
|
||||||
require File.join(File.dirname(__FILE__), 'views')
|
require File.join(File.dirname(__FILE__), 'views')
|
||||||
require File.join(File.dirname(__FILE__), 'design_doc')
|
require File.join(File.dirname(__FILE__), 'design_doc')
|
||||||
require File.join(File.dirname(__FILE__), 'validation')
|
require File.join(File.dirname(__FILE__), 'validation')
|
||||||
require File.join(File.dirname(__FILE__), 'extended_attachments')
|
require File.join(File.dirname(__FILE__), 'extended_attachments')
|
||||||
|
require File.join(File.dirname(__FILE__), 'class_proxy')
|
||||||
|
|
|
@ -11,6 +11,7 @@ module CouchRest
|
||||||
include CouchRest::Mixins::Views
|
include CouchRest::Mixins::Views
|
||||||
include CouchRest::Mixins::DesignDoc
|
include CouchRest::Mixins::DesignDoc
|
||||||
include CouchRest::Mixins::ExtendedAttachments
|
include CouchRest::Mixins::ExtendedAttachments
|
||||||
|
include CouchRest::Mixins::ClassProxy
|
||||||
|
|
||||||
def self.inherited(subklass)
|
def self.inherited(subklass)
|
||||||
subklass.send(:include, CouchRest::Mixins::Properties)
|
subklass.send(:include, CouchRest::Mixins::Properties)
|
||||||
|
|
|
@ -8,6 +8,7 @@ describe "ExtendedDocument views" do
|
||||||
# Note: no use_database here
|
# Note: no use_database here
|
||||||
property :title
|
property :title
|
||||||
property :questions
|
property :questions
|
||||||
|
property :professor
|
||||||
view_by :title
|
view_by :title
|
||||||
end
|
end
|
||||||
|
|
||||||
|
@ -158,6 +159,13 @@ describe "ExtendedDocument views" do
|
||||||
end
|
end
|
||||||
things[0]["doc"]["title"].should =='aaa'
|
things[0]["doc"]["title"].should =='aaa'
|
||||||
end
|
end
|
||||||
|
it "should yield with by_key method" do
|
||||||
|
things = []
|
||||||
|
Unattached.by_title(:database=>@db) do |thing|
|
||||||
|
things << thing
|
||||||
|
end
|
||||||
|
things[0]["doc"]["title"].should =='aaa'
|
||||||
|
end
|
||||||
it "should barf on get if no database given" do
|
it "should barf on get if no database given" do
|
||||||
lambda{Unattached.get("aaa")}.should raise_error
|
lambda{Unattached.get("aaa")}.should raise_error
|
||||||
end
|
end
|
||||||
|
@ -186,6 +194,67 @@ describe "ExtendedDocument views" do
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
describe "class proxy" do
|
||||||
|
before(:all) do
|
||||||
|
reset_test_db!
|
||||||
|
@us = Unattached.on(TEST_SERVER.default_database)
|
||||||
|
%w{aaa bbb ddd eee}.each do |title|
|
||||||
|
u = @us.new(:title => title)
|
||||||
|
u.save
|
||||||
|
@first_id ||= u.id
|
||||||
|
end
|
||||||
|
end
|
||||||
|
it "should query all" do
|
||||||
|
rs = @us.all
|
||||||
|
rs.length.should == 4
|
||||||
|
end
|
||||||
|
it "should make the design doc upon first query" do
|
||||||
|
@us.by_title
|
||||||
|
doc = @us.design_doc
|
||||||
|
doc['views']['all']['map'].should include('Unattached')
|
||||||
|
end
|
||||||
|
it "should merge query params" do
|
||||||
|
rs = @us.by_title :startkey=>"bbb", :endkey=>"eee"
|
||||||
|
rs.length.should == 3
|
||||||
|
end
|
||||||
|
it "should query via view" do
|
||||||
|
view = @us.view :by_title
|
||||||
|
designed = @us.by_title
|
||||||
|
view.should == designed
|
||||||
|
end
|
||||||
|
it "should yield" do
|
||||||
|
things = []
|
||||||
|
@us.view(:by_title) do |thing|
|
||||||
|
things << thing
|
||||||
|
end
|
||||||
|
things[0]["doc"]["title"].should =='aaa'
|
||||||
|
end
|
||||||
|
it "should yield with by_key method" do
|
||||||
|
things = []
|
||||||
|
@us.by_title do |thing|
|
||||||
|
things << thing
|
||||||
|
end
|
||||||
|
things[0]["doc"]["title"].should =='aaa'
|
||||||
|
end
|
||||||
|
it "should get from specific database" do
|
||||||
|
u = @us.get(@first_id)
|
||||||
|
u.title.should == "aaa"
|
||||||
|
end
|
||||||
|
it "should get first" do
|
||||||
|
u = @us.first
|
||||||
|
u.title.should =~ /\A...\z/
|
||||||
|
end
|
||||||
|
it "should clean up design docs left around on specific database" do
|
||||||
|
@us.by_title
|
||||||
|
@us.all_design_doc_versions["rows"].length.should == 1
|
||||||
|
Unattached.view_by :professor
|
||||||
|
@us.by_professor
|
||||||
|
@us.all_design_doc_versions["rows"].length.should == 2
|
||||||
|
@us.cleanup_design_docs!
|
||||||
|
@us.all_design_doc_versions["rows"].length.should == 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
describe "a model with a compound key view" do
|
describe "a model with a compound key view" do
|
||||||
before(:all) do
|
before(:all) do
|
||||||
Article.design_doc_fresh = false
|
Article.design_doc_fresh = false
|
||||||
|
|
Loading…
Reference in a new issue