activecouch 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (52) hide show
  1. data/MIT-LICENSE +20 -0
  2. data/README +42 -0
  3. data/Rakefile +31 -0
  4. data/VERSION +1 -0
  5. data/lib/active_couch.rb +18 -0
  6. data/lib/active_couch/associations.rb +1 -0
  7. data/lib/active_couch/associations/has_many_association.rb +35 -0
  8. data/lib/active_couch/attribute.rb +46 -0
  9. data/lib/active_couch/base.rb +458 -0
  10. data/lib/active_couch/callbacks.rb +81 -0
  11. data/lib/active_couch/connection.rb +155 -0
  12. data/lib/active_couch/errors.rb +17 -0
  13. data/lib/active_couch/migrations.rb +3 -0
  14. data/lib/active_couch/migrations/errors.rb +4 -0
  15. data/lib/active_couch/migrations/migration.rb +77 -0
  16. data/lib/active_couch/migrations/migrator.rb +53 -0
  17. data/lib/active_couch/support.rb +2 -0
  18. data/lib/active_couch/support/extensions.rb +92 -0
  19. data/lib/active_couch/support/inflections.rb +52 -0
  20. data/lib/active_couch/support/inflector.rb +280 -0
  21. data/spec/attribute/initialize_spec.rb +138 -0
  22. data/spec/base/after_delete_spec.rb +107 -0
  23. data/spec/base/after_save_spec.rb +99 -0
  24. data/spec/base/before_delete_spec.rb +106 -0
  25. data/spec/base/before_save_spec.rb +98 -0
  26. data/spec/base/create_spec.rb +27 -0
  27. data/spec/base/database_spec.rb +65 -0
  28. data/spec/base/delete_spec.rb +78 -0
  29. data/spec/base/find_spec.rb +165 -0
  30. data/spec/base/from_json_spec.rb +48 -0
  31. data/spec/base/has_many_spec.rb +81 -0
  32. data/spec/base/has_spec.rb +76 -0
  33. data/spec/base/id_spec.rb +22 -0
  34. data/spec/base/initialize_spec.rb +43 -0
  35. data/spec/base/module_spec.rb +18 -0
  36. data/spec/base/nested_class_spec.rb +19 -0
  37. data/spec/base/rev_spec.rb +16 -0
  38. data/spec/base/save_spec.rb +65 -0
  39. data/spec/base/site_spec.rb +41 -0
  40. data/spec/base/to_json_spec.rb +64 -0
  41. data/spec/connection/initialize_spec.rb +28 -0
  42. data/spec/has_many_association/initialize_spec.rb +33 -0
  43. data/spec/migration/define_spec.rb +29 -0
  44. data/spec/migration/include_attributes_spec.rb +30 -0
  45. data/spec/migration/view_js_spec.rb +46 -0
  46. data/spec/migration/with_filter_spec.rb +13 -0
  47. data/spec/migration/with_key_spec.rb +13 -0
  48. data/spec/migrator/create_database_spec.rb +48 -0
  49. data/spec/migrator/delete_database_spec.rb +46 -0
  50. data/spec/migrator/migrate_spec.rb +99 -0
  51. data/spec/spec_helper.rb +9 -0
  52. metadata +104 -0
@@ -0,0 +1,22 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "An object instantiated from the subclass of ActiveCouch::Base" do
4
+ before(:each) do
5
+ class Person < ActiveCouch::Base
6
+ has :name, :which_is => :text
7
+ end
8
+
9
+ @person = Person.new
10
+ end
11
+
12
+ it "should have accessors for the id attribute" do
13
+ @person.should respond_to(:id)
14
+ @person.should respond_to(:id=)
15
+ end
16
+
17
+ it "should be able to set and retrieve the id variable" do
18
+ @person.id = 'abc-def'
19
+ @person.id.should == 'abc-def'
20
+ end
21
+
22
+ end
@@ -0,0 +1,43 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "ActiveCouch::Base #new method with a hash containing one key-value pair" do
4
+ before(:each) do
5
+ class Person < ActiveCouch::Base
6
+ has :name
7
+ end
8
+ end
9
+
10
+ it "should be able to initialize attributes correctly from a hash" do
11
+ p = Person.new(:name => 'McLovin')
12
+ p.name.should == 'McLovin'
13
+ end
14
+ end
15
+
16
+ describe "ActiveCouch::Base #new method with a hash containing more than one key-value pair" do
17
+ before(:each) do
18
+ class Person < ActiveCouch::Base
19
+ has :name
20
+ has :age, :which_is => :number, :with_default_value => 25
21
+ end
22
+ end
23
+
24
+ it "should be able to initialize attributes correctly from the hash" do
25
+ p = Person.new(:name => 'McLovin', :age => 12)
26
+ p.name.should == 'McLovin'
27
+ p.age.should == 12
28
+ end
29
+ end
30
+
31
+ describe "ActiveCouch::Base #new method with a hash containing a CouchDB reserved attribute" do
32
+ before(:each) do
33
+ class Person < ActiveCouch::Base
34
+ has :name
35
+ end
36
+ end
37
+
38
+ it "should be able to initialize attributes correclty from the has, including CouchDB reserved attributes" do
39
+ p = Person.new(:name => 'McLovin', :id => '123')
40
+ p.name.should == 'McLovin'
41
+ p.id.should == '123'
42
+ end
43
+ end
@@ -0,0 +1,18 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "A Cheezburger subclass of ActiveCouch::Base defined in the Burgers module" do
4
+ before(:all) do
5
+ module Burgers
6
+ class Cheezburger < ActiveCouch::Base
7
+ end
8
+ end
9
+ end
10
+
11
+ it "should have a base_class of Burgers::Cheezburger" do
12
+ Burgers::Cheezburger.base_class.should == Burgers::Cheezburger
13
+ end
14
+
15
+ it "should have a database_name of cheezburgers" do
16
+ Burgers::Cheezburger.database_name.should == 'cheezburgers'
17
+ end
18
+ end
@@ -0,0 +1,19 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "A Cheezburger subclass of ActiveCouch::Base nested in a Lolcat subclass of ActiveCouch::Base" do
4
+ before(:all) do
5
+ class Lolcat < ActiveCouch::Base
6
+ class Cheezburger < ActiveCouch::Base
7
+ end
8
+ end
9
+ end
10
+
11
+ it "should have a base_class of Lolcat::Cheezburger" do
12
+ Lolcat.base_class.should == Lolcat
13
+ Lolcat::Cheezburger.base_class.should == Lolcat::Cheezburger
14
+ end
15
+
16
+ it "should have a database_name of lolcat_cheezburger" do
17
+ Lolcat::Cheezburger.database_name.should == 'lolcat_cheezburgers'
18
+ end
19
+ end
@@ -0,0 +1,16 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "An object instantiated from the subclass of ActiveCouch::Base" do
4
+ before(:each) do
5
+ class Person < ActiveCouch::Base
6
+ has :name, :which_is => :text
7
+ end
8
+
9
+ @person = Person.new
10
+ end
11
+
12
+ it "should have reader/writer for the rev attribute" do
13
+ @person.should respond_to(:rev)
14
+ @person.should respond_to(:rev=)
15
+ end
16
+ end
@@ -0,0 +1,65 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "A Person subclass of ActiveCouch::Base" do
4
+ before(:each) do
5
+ class Person < ActiveCouch::Base
6
+ site 'http://localhost:5984/'
7
+ has :name
8
+ end
9
+ # Create a database called people
10
+ ActiveCouch::Migrator.create_database('http://localhost:5984/', 'people')
11
+ end
12
+
13
+ after(:each) do
14
+ # Delete after we're done
15
+ ActiveCouch::Migrator.delete_database('http://localhost:5984/', 'people')
16
+ end
17
+
18
+ it "should have an instance method called save" do
19
+ Person.new.methods.include?('save').should == true
20
+ end
21
+
22
+ it "should be able to persist itself in the CouchDB database" do
23
+ person = Person.new(:name => 'McLovin')
24
+ person.save.should == true
25
+ end
26
+ end
27
+
28
+ describe "A new ActiveCouch::Base instance" do
29
+ before(:each) do
30
+ class Person < ActiveCouch::Base
31
+ site 'http://localhost:5984/'
32
+ has :name, :which_is => :text
33
+ end
34
+
35
+ @person = Person.new(:name => 'Seth')
36
+ # Create a database called people
37
+ ActiveCouch::Migrator.create_database('http://localhost:5984/', 'people')
38
+ end
39
+
40
+ after(:each) do
41
+ # Delete after we're done
42
+ ActiveCouch::Migrator.delete_database('http://localhost:5984/', 'people')
43
+ end
44
+
45
+ it "should be new" do
46
+ @person.should be_new
47
+ end
48
+
49
+ it "should set the id and rev attributes after being saved" do
50
+ @person.save
51
+
52
+ @person.id.should_not == nil
53
+ @person.rev.should_not == nil
54
+ @person.should_not be_new
55
+ end
56
+
57
+ it "should allow you to set the id attribute, and the id must be reflected in the object after saving" do
58
+ @person.id = 'abc_def'
59
+ puts @person.to_json
60
+
61
+ @person.save
62
+ @person.id.should == 'abc_def'
63
+ end
64
+
65
+ end
@@ -0,0 +1,41 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "A subclass of ActiveCouch::Base object which has called establish_connection" do
4
+ before(:each) do
5
+ class Cat < ActiveCouch::Base
6
+ site 'http://192.168.0.150:7777'
7
+ end
8
+ end
9
+
10
+ after(:each) do
11
+ # Remove class definition so we can start fresh in each spec.
12
+ Object.send(:remove_const, :Cat)
13
+ end
14
+
15
+ it "should have the method connection" do
16
+ Cat.methods.index('connection').should_not == nil
17
+ Cat.connection.site.host.should == '192.168.0.150'
18
+ Cat.connection.site.port.should == 7777
19
+ end
20
+ end
21
+
22
+ describe "An object instantiated from a subclass of ActiveCouch::Base which has called establish_connection" do
23
+ before(:each) do
24
+ class Cat < ActiveCouch::Base
25
+ site 'http://192.168.0.150'
26
+ end
27
+ @cat = Cat.new
28
+ end
29
+
30
+ after(:each) do
31
+ # Remove class definition so we can start fresh in each spec.
32
+ Object.send(:remove_const, :Cat)
33
+ end
34
+
35
+
36
+ it "should have the method connection in objects instantiated from the subclass" do
37
+ @cat.methods.index('connection').should_not == nil
38
+ @cat.connection.site.host.should == '192.168.0.150'
39
+ @cat.connection.site.port.should == 5984
40
+ end
41
+ end
@@ -0,0 +1,64 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "ActiveCouch::Base #to_json method with just simple attributes" do
4
+ before(:each) do
5
+ class Hotel < ActiveCouch::Base
6
+ has :name, :which_is => :text, :with_default_value => "Swissotel The Stamford"
7
+ has :star_rating, :which_is => :decimal, :with_default_value => 5.0
8
+ has :rooms, :which_is => :number, :with_default_value => 100
9
+ end
10
+
11
+ @h = Hotel.new
12
+ end
13
+
14
+ it "should have to the to_json method" do
15
+ @h.should respond_to(:to_json)
16
+ end
17
+
18
+ it "should produce valid JSON output when sent the to_json method" do
19
+ json_output = @h.to_json
20
+ # Check for JSON regex, since attributes can appear in any order
21
+ (json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
22
+ (json_output =~ /"rooms":100/).should_not == nil
23
+ (json_output =~ /"star_rating":5.0/).should_not == nil
24
+ end
25
+
26
+ it "should produce valid JSON output when an attribute has been changed and the to_json method is sent" do
27
+ @h.rooms = 200
28
+ json_output = @h.to_json
29
+ # Check for JSON regex, since attributes can appear in any order
30
+ (json_output =~ /"name":"Swissotel The Stamford"/).should_not == nil
31
+ (json_output =~ /"rooms":200/).should_not == nil
32
+ (json_output =~ /"star_rating":5.0/).should_not == nil
33
+ end
34
+ end
35
+
36
+ describe "ActiveCouch::Base #to_json with associations" do
37
+ before(:each) do
38
+ class Hospital < ActiveCouch::Base
39
+ has :name
40
+ end
41
+
42
+ class CrazyPerson < ActiveCouch::Base
43
+ has :name, :which_is => :text, :with_default_value => "Crazed McLovin"
44
+ has_many :hospitals
45
+ end
46
+
47
+ @c = CrazyPerson.new
48
+
49
+ @h1 = Hospital.new(:name => "Crazy Hospital 1")
50
+ @h2 = Hospital.new(:name => "Crazy Hospital 2")
51
+
52
+ @c.add_hospital(@h1)
53
+ @c.add_hospital(@h2)
54
+ end
55
+
56
+ it "should produce valid JSON when sent the to_json method" do
57
+ json_output = @c.to_json
58
+ # Check for JSON regex, since attributes can appear in any order
59
+ (json_output =~ /"name":"Crazed McLovin"/).should_not == nil
60
+ (json_output =~ /"hospitals":\[.*?\]/).should_not == nil
61
+ (json_output =~ /\{.*?"name":"Crazy Hospital 1".*?\}/).should_not == nil
62
+ (json_output =~ /\{.*?"name":"Crazy Hospital 2".*?\}/).should_not == nil
63
+ end
64
+ end
@@ -0,0 +1,28 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe ActiveCouch::Connection do
4
+ it "should set the site for the connection object and there must be no error" do
5
+ @connection = ActiveCouch::Connection.new('http://192.168.0.150:7777')
6
+
7
+ @connection.site.host.should == "192.168.0.150"
8
+ @connection.site.port.should == 7777
9
+ @error.should == nil
10
+ end
11
+ end
12
+
13
+ describe "An ActiveCouch::Connection object instantiated with no site specified" do
14
+ it "should raise an ArgumentError and return nil" do
15
+ lambda {
16
+ @connection = ActiveCouch::Connection.new(nil)
17
+ }.should raise_error(ArgumentError, 'Missing site URI')
18
+ end
19
+ end
20
+
21
+ describe "An ActiveCouch::Connection object instantiated with site (with no port) specified" do
22
+ it "should use the default CouchDB port of 5984" do
23
+ @connection = ActiveCouch::Connection.new('http://192.168.0.150')
24
+
25
+ @connection.site.host.should == "192.168.0.150"
26
+ @connection.site.port.should == 5984
27
+ end
28
+ end
@@ -0,0 +1,33 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ class EmptyPerson < ActiveCouch::Base; end
4
+
5
+ describe "An ActiveCouch::HasManyAssociation object initialized with a name and with class set to Person" do
6
+ before(:each) do
7
+ @a = ActiveCouch::HasManyAssociation.new(:contacts, :class => EmptyPerson)
8
+ end
9
+
10
+ it "should set the klass to Person name must be contacts" do
11
+ @a.klass.should == EmptyPerson
12
+ @a.name.should == "contacts"
13
+ @a.container.should == []
14
+ end
15
+ end
16
+
17
+ describe "An ActiveCouch::HasManyAssociation object initialized with only a name" do
18
+ before(:each) do
19
+ @a = ActiveCouch::HasManyAssociation.new(:empty_people)
20
+ end
21
+
22
+ it "should set the klass to Person name must be people" do
23
+ @a.klass.should == EmptyPerson
24
+ @a.name.should == "empty_people"
25
+ @a.container.should == []
26
+ end
27
+ end
28
+
29
+ describe "An ActiveCouch::HasManyAssociation object initialized with only a name (but for which a class is not defined)" do
30
+ it "should raise a NameError" do
31
+ lambda { ass.new(:contacts) }.should raise_error(NameError)
32
+ end
33
+ end
@@ -0,0 +1,29 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "ActiveCouch::Migration #define method" do
4
+ it "should set @view and @database correctly if the first param is a String/Symbol" do
5
+ class ByName < ActiveCouch::Migration
6
+ define :by_name, :for_db => 'people'
7
+ end
8
+
9
+ ByName.instance_variable_get("@view").should == 'by_name'
10
+ ByName.instance_variable_get("@database").should == 'people'
11
+ end
12
+
13
+ it "should set @view correctly if the first param passed is not a String/Symbol" do
14
+ class ByFace < ActiveCouch::Migration
15
+ define :for_db => 'people'
16
+ end
17
+
18
+ ByFace.instance_variable_get("@view").should == 'by_face'
19
+ ByFace.instance_variable_get("@database").should == 'people'
20
+ end
21
+
22
+ it "should raise an exception if neither the view nor the database is given as parameters" do
23
+ lambda {
24
+ class Test < ActiveCouch::Migration; define; end
25
+ }.should raise_error(ArgumentError, 'Wrong arguments used to define the view')
26
+ end
27
+ end
28
+
29
+
@@ -0,0 +1,30 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "ActiveCouch::Migration #include_attributes method" do
4
+ it "should set the attrs instance variable to an array, if passed a multi-element array" do
5
+ class ByLongitude < ActiveCouch::Migration
6
+ define :for_db => 'hotels' do
7
+ include_attributes :name, :rating, :latitude, :longitude, :address
8
+ end
9
+ end
10
+ ByLongitude.instance_variable_get("@attrs").should == [:name, :rating, :latitude, :longitude, :address]
11
+ end
12
+
13
+ it "should set the attrs instance variable correctly, if passed a single-element array" do
14
+ class ByLongitude < ActiveCouch::Migration
15
+ define :for_db => 'hotels' do
16
+ include_attributes :name
17
+ end
18
+ end
19
+ ByLongitude.instance_variable_get("@attrs").should == [:name]
20
+ end
21
+
22
+ it "should set the attrs instance variable to an empty array, if not passed an array" do
23
+ class ByLongitude < ActiveCouch::Migration
24
+ define :for_db => 'hotels' do
25
+ include_attributes {}
26
+ end
27
+ end
28
+ ByLongitude.instance_variable_get("@attrs").should == []
29
+ end
30
+ end
@@ -0,0 +1,46 @@
1
+ require File.dirname(__FILE__) + '/../spec_helper.rb'
2
+
3
+ describe "ActiveCouch::Migration #view_js method" do
4
+ before(:each) do
5
+ class ByName < ActiveCouch::Migration
6
+ define :by_name, :for_db => 'people' do
7
+ with_key 'name'
8
+ end
9
+ end
10
+ end
11
+
12
+ it "should generate the correct javascript to be used in the view" do
13
+ (ByName.view_js =~ /map\(doc\.name, doc\);/).should_not == nil
14
+ end
15
+ end
16
+
17
+ describe "ActiveCouch::Migration #view_js method while calling the with_key and with_filter methods" do
18
+ before(:each) do
19
+ class ByLatitude < ActiveCouch::Migration
20
+ define :for_db => 'hotels' do
21
+ with_key 'latitude'
22
+ with_filter 'doc.name == "Hilton"'
23
+ end
24
+ end
25
+ end
26
+
27
+ it "should generate the correct javascript to be used in the view" do
28
+ (ByLatitude.view_js =~ /map\(doc\.latitude, doc\);/).should_not == nil
29
+ (ByLatitude.view_js =~ /if\(doc\.name == \\"Hilton\\"\)/).should_not == nil
30
+ end
31
+ end
32
+
33
+ describe "A subclass of ActiveCouch::Migration while calling with_key and include_attributes method" do
34
+ before(:each) do
35
+ class ByLongitude < ActiveCouch::Migration
36
+ define :for_db => 'hotels' do
37
+ with_key 'latitude'
38
+ include_attributes :name, :rating, :latitude, :longitude, :address
39
+ end
40
+ end
41
+ end
42
+
43
+ it "should generate the correct javascript which will be used in the permanent view" do
44
+ (ByLongitude.view_js =~ /map\(doc\.latitude, \{name: doc\.name , rating: doc\.rating , latitude: doc\.latitude , longitude: doc\.longitude , address: doc\.address\}\);/).should_not == nil
45
+ end
46
+ end