From 85109b4b223cc48118c38f1ffc5ad3c9eb9dfb5f Mon Sep 17 00:00:00 2001 From: Sam Lown Date: Fri, 29 Apr 2011 23:06:31 +0200 Subject: [PATCH] Finalizing support for automatic configuration --- lib/couchrest/model/configuration.rb | 1 + lib/couchrest/model/connection.rb | 22 ++++++-------- lib/couchrest/model/proxyable.rb | 9 ++---- spec/couchrest/connection_spec.rb | 16 +++++++++-- spec/couchrest/proxyable_spec.rb | 43 +++++++++++++++++----------- spec/couchrest/view_spec.rb | 8 ++++-- 6 files changed, 59 insertions(+), 40 deletions(-) diff --git a/lib/couchrest/model/configuration.rb b/lib/couchrest/model/configuration.rb index 6c0d489..5b80393 100644 --- a/lib/couchrest/model/configuration.rb +++ b/lib/couchrest/model/configuration.rb @@ -35,6 +35,7 @@ module CouchRest :port => '5984', :prefix => app_name, :suffix => nil, + :join => '_', :username => nil, :password => nil } diff --git a/lib/couchrest/model/connection.rb b/lib/couchrest/model/connection.rb index 56340a1..87b30e7 100644 --- a/lib/couchrest/model/connection.rb +++ b/lib/couchrest/model/connection.rb @@ -3,10 +3,6 @@ module CouchRest module Connection extend ActiveSupport::Concern - def database - self.class.database - end - def server self.class.server end @@ -16,15 +12,13 @@ module CouchRest # Overwrite the normal use_database method so that a database # name can be provided instead of a full connection. def use_database(db) - @_database_name = db + @database = prepare_database(db) end - # Replace CouchRest's database reader with a more advanced - # version that will make a best guess at the database you might - # want to use. Allows for a string to be provided instead of - # a database object. + # Overwrite the default database method so that it always + # provides something from the configuration def database - @database ||= prepare_database(@_database_name) + super || (@database ||= prepare_database) end def server @@ -34,7 +28,7 @@ module CouchRest def prepare_database(db = nil) unless db.is_a?(CouchRest::Database) conf = connection_configuration - db = [conf[:prefix], db.to_s, conf[:suffix]].compact.join('_') + db = [conf[:prefix], db.to_s, conf[:suffix]].reject{|s| s.to_s.empty?}.join(conf[:join]) self.server.database!(db) else db @@ -51,7 +45,7 @@ module CouchRest end def connection_configuration - @server_configuration ||= + @connection_configuration ||= self.connection.update( (load_connection_config_file[environment] || {}).symbolize_keys ) @@ -59,9 +53,9 @@ module CouchRest def load_connection_config_file connection_config_cache[connection_config_file] ||= - File.exists?(connection_config_file) ? + (File.exists?(connection_config_file) ? YAML::load(ERB.new(IO.read(connection_config_file)).result) : - { } + { }).symbolize_keys end def connection_config_cache diff --git a/lib/couchrest/model/proxyable.rb b/lib/couchrest/model/proxyable.rb index 8c26105..a3fa6cd 100644 --- a/lib/couchrest/model/proxyable.rb +++ b/lib/couchrest/model/proxyable.rb @@ -47,14 +47,11 @@ module CouchRest private - # Ensure that the model can no longer be used for normal requests - # be overwriting the database reader method so that a helpful - # error message is displayed. + # Ensure that no attempt is made to autoload a database connection + # by overwriting it to provide a basic accessor. def overwrite_database_reader(model_name) class_eval <<-EOS, __FILE__, __LINE__ + 1 - def database - raise StandardError, "#{self.to_s} documents must be accessed via the '#{model_name}' proxy" - end + def database; @database; end EOS end diff --git a/spec/couchrest/connection_spec.rb b/spec/couchrest/connection_spec.rb index 2724f00..9e9c856 100644 --- a/spec/couchrest/connection_spec.rb +++ b/spec/couchrest/connection_spec.rb @@ -85,6 +85,12 @@ describe CouchRest::Model::Base do @class.should respond_to(:prepare_database) end + it "should join the database name correctly" do + @class.connection[:suffix] = 'db' + db = @class.prepare_database('test') + db.name.should eql('couchrest_test_db') + end + end describe "protected methods" do @@ -93,6 +99,13 @@ describe CouchRest::Model::Base do it "should provide main config by default" do @class.send(:connection_configuration).should eql(@class.connection) end + it "should load file if available" do + @class.connection_config_file = File.join(FIXTURE_PATH, 'config', 'couchdb.yml') + hash = @class.send(:connection_configuration) + hash[:protocol].should eql('https') + hash[:host].should eql('sample.cloudant.com') + hash[:join].should eql('_') + end end describe ".load_connection_config_file" do @@ -101,10 +114,9 @@ describe CouchRest::Model::Base do end it "should load file if available" do @class.connection_config_file = File.join(FIXTURE_PATH, 'config', 'couchdb.yml') - puts @class.send(:connection_config_cache).inspect hash = @class.send(:load_connection_config_file) hash[:development].should_not be_nil - @class.server.uri.should eql("https://test:uesr@sample.cloudant.com:443") + @class.server.uri.should eql("https://test:user@sample.cloudant.com:443") end end diff --git a/spec/couchrest/proxyable_spec.rb b/spec/couchrest/proxyable_spec.rb index 6de3401..dfa2326 100644 --- a/spec/couchrest/proxyable_spec.rb +++ b/spec/couchrest/proxyable_spec.rb @@ -13,6 +13,32 @@ end describe "Proxyable" do + describe "#proxy_database" do + + before do + @class = Class.new(CouchRest::Model::Base) + @class.class_eval do + def slug; 'proxy'; end + end + @obj = @class.new + end + + it "should respond to method" do + @obj.should respond_to(:proxy_database) + end + + it "should provide proxy database from method" do + @class.stub!(:proxy_database_method).twice.and_return(:slug) + @obj.proxy_database.should be_a(CouchRest::Database) + @obj.proxy_database.name.should eql('couchrest_proxy') + end + + it "should raise an error if called and no proxy_database_method set" do + lambda { @obj.proxy_database }.should raise_error(StandardError, /Please set/) + end + + end + describe "class methods" do before(:each) do @@ -48,7 +74,6 @@ describe "Proxyable" do @obj = DummyProxyable.new CouchRest::Model::Proxyable::ModelProxy.should_receive(:new).with(Cat, @obj, 'dummy_proxyable', 'db').and_return(true) @obj.should_receive('proxy_database').and_return('db') - @obj.should_receive(:respond_to?).with('proxy_database').and_return(true) @obj.cats end @@ -60,22 +85,8 @@ describe "Proxyable" do @obj = DummyProxyable.new CouchRest::Model::Proxyable::ModelProxy.should_receive(:new).with(::Document, @obj, 'dummy_proxyable', 'db').and_return(true) @obj.should_receive('proxy_database').and_return('db') - @obj.should_receive(:respond_to?).with('proxy_database').and_return(true) @obj.documents end - - it "should raise an error if the database method is missing" do - @class.proxy_for(:cats) - @obj = @class.new - @obj.should_receive(:respond_to?).with('proxy_database').and_return(false) - lambda { @obj.cats }.should raise_error(StandardError, "Missing #proxy_database method for proxy") - end - - it "should raise an error if custom database method missing" do - @class.proxy_for(:proxy_kittens, :database_method => "foobardom") - @obj = @class.new - lambda { @obj.proxy_kittens }.should raise_error(StandardError, "Missing #foobardom method for proxy") - end end end @@ -316,7 +327,7 @@ describe "Proxyable" do it "should allow creation of new entries" do inv = @company.proxyable_invoices.new(:client => "Lorena", :total => 35) - inv.database.should_not be_nil + # inv.database.should_not be_nil inv.save.should be_true @company.proxyable_invoices.count.should eql(1) @company.proxyable_invoices.first.client.should eql("Lorena") diff --git a/spec/couchrest/view_spec.rb b/spec/couchrest/view_spec.rb index e9259ff..d54d252 100644 --- a/spec/couchrest/view_spec.rb +++ b/spec/couchrest/view_spec.rb @@ -7,11 +7,15 @@ require File.join(FIXTURE_PATH, 'more', 'course') describe "Model views" do class Unattached < CouchRest::Model::Base - # Note: no use_database here property :title property :questions property :professor view_by :title + + # Force the database to always be nil + def self.database + nil + end end @@ -195,7 +199,7 @@ describe "Model views" do end end - describe "a model class not tied to a database" do + describe "a model class with database provided manually" do before(:all) do reset_test_db! @db = DB