peterpunk-couchrest 0.23.1

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 (94) hide show
  1. data/LICENSE +176 -0
  2. data/README.md +95 -0
  3. data/Rakefile +75 -0
  4. data/THANKS.md +18 -0
  5. data/examples/model/example.rb +144 -0
  6. data/examples/word_count/markov +38 -0
  7. data/examples/word_count/views/books/chunked-map.js +3 -0
  8. data/examples/word_count/views/books/united-map.js +1 -0
  9. data/examples/word_count/views/markov/chain-map.js +6 -0
  10. data/examples/word_count/views/markov/chain-reduce.js +7 -0
  11. data/examples/word_count/views/word_count/count-map.js +6 -0
  12. data/examples/word_count/views/word_count/count-reduce.js +3 -0
  13. data/examples/word_count/word_count.rb +46 -0
  14. data/examples/word_count/word_count_query.rb +40 -0
  15. data/examples/word_count/word_count_views.rb +26 -0
  16. data/lib/couchrest.rb +198 -0
  17. data/lib/couchrest/commands/generate.rb +71 -0
  18. data/lib/couchrest/commands/push.rb +103 -0
  19. data/lib/couchrest/core/database.rb +303 -0
  20. data/lib/couchrest/core/design.rb +79 -0
  21. data/lib/couchrest/core/document.rb +87 -0
  22. data/lib/couchrest/core/response.rb +20 -0
  23. data/lib/couchrest/core/server.rb +88 -0
  24. data/lib/couchrest/core/view.rb +4 -0
  25. data/lib/couchrest/helper/pager.rb +103 -0
  26. data/lib/couchrest/helper/streamer.rb +44 -0
  27. data/lib/couchrest/helper/upgrade.rb +51 -0
  28. data/lib/couchrest/mixins.rb +4 -0
  29. data/lib/couchrest/mixins/attachments.rb +31 -0
  30. data/lib/couchrest/mixins/callbacks.rb +483 -0
  31. data/lib/couchrest/mixins/class_proxy.rb +108 -0
  32. data/lib/couchrest/mixins/design_doc.rb +90 -0
  33. data/lib/couchrest/mixins/document_queries.rb +44 -0
  34. data/lib/couchrest/mixins/extended_attachments.rb +68 -0
  35. data/lib/couchrest/mixins/extended_document_mixins.rb +7 -0
  36. data/lib/couchrest/mixins/properties.rb +133 -0
  37. data/lib/couchrest/mixins/validation.rb +244 -0
  38. data/lib/couchrest/mixins/views.rb +169 -0
  39. data/lib/couchrest/monkeypatches.rb +113 -0
  40. data/lib/couchrest/more/casted_model.rb +28 -0
  41. data/lib/couchrest/more/extended_document.rb +219 -0
  42. data/lib/couchrest/more/property.rb +40 -0
  43. data/lib/couchrest/support/blank.rb +42 -0
  44. data/lib/couchrest/support/class.rb +176 -0
  45. data/lib/couchrest/validation/auto_validate.rb +163 -0
  46. data/lib/couchrest/validation/contextual_validators.rb +78 -0
  47. data/lib/couchrest/validation/validation_errors.rb +119 -0
  48. data/lib/couchrest/validation/validators/absent_field_validator.rb +74 -0
  49. data/lib/couchrest/validation/validators/confirmation_validator.rb +99 -0
  50. data/lib/couchrest/validation/validators/format_validator.rb +117 -0
  51. data/lib/couchrest/validation/validators/formats/email.rb +66 -0
  52. data/lib/couchrest/validation/validators/formats/url.rb +43 -0
  53. data/lib/couchrest/validation/validators/generic_validator.rb +120 -0
  54. data/lib/couchrest/validation/validators/length_validator.rb +134 -0
  55. data/lib/couchrest/validation/validators/method_validator.rb +89 -0
  56. data/lib/couchrest/validation/validators/numeric_validator.rb +104 -0
  57. data/lib/couchrest/validation/validators/required_field_validator.rb +109 -0
  58. data/lib/couchrest/validation/validators/uniqueness_validator.rb +89 -0
  59. data/spec/couchrest/core/couchrest_spec.rb +201 -0
  60. data/spec/couchrest/core/database_spec.rb +699 -0
  61. data/spec/couchrest/core/design_spec.rb +138 -0
  62. data/spec/couchrest/core/document_spec.rb +267 -0
  63. data/spec/couchrest/core/server_spec.rb +35 -0
  64. data/spec/couchrest/helpers/pager_spec.rb +122 -0
  65. data/spec/couchrest/helpers/streamer_spec.rb +23 -0
  66. data/spec/couchrest/more/casted_extended_doc_spec.rb +40 -0
  67. data/spec/couchrest/more/casted_model_spec.rb +98 -0
  68. data/spec/couchrest/more/extended_doc_attachment_spec.rb +130 -0
  69. data/spec/couchrest/more/extended_doc_spec.rb +531 -0
  70. data/spec/couchrest/more/extended_doc_subclass_spec.rb +98 -0
  71. data/spec/couchrest/more/extended_doc_view_spec.rb +355 -0
  72. data/spec/couchrest/more/property_spec.rb +190 -0
  73. data/spec/fixtures/attachments/README +3 -0
  74. data/spec/fixtures/attachments/couchdb.png +0 -0
  75. data/spec/fixtures/attachments/test.html +11 -0
  76. data/spec/fixtures/more/article.rb +34 -0
  77. data/spec/fixtures/more/card.rb +20 -0
  78. data/spec/fixtures/more/course.rb +14 -0
  79. data/spec/fixtures/more/event.rb +6 -0
  80. data/spec/fixtures/more/invoice.rb +17 -0
  81. data/spec/fixtures/more/location.rb +18 -0
  82. data/spec/fixtures/more/person.rb +8 -0
  83. data/spec/fixtures/more/question.rb +6 -0
  84. data/spec/fixtures/more/service.rb +12 -0
  85. data/spec/fixtures/views/lib.js +3 -0
  86. data/spec/fixtures/views/test_view/lib.js +3 -0
  87. data/spec/fixtures/views/test_view/only-map.js +4 -0
  88. data/spec/fixtures/views/test_view/test-map.js +3 -0
  89. data/spec/fixtures/views/test_view/test-reduce.js +3 -0
  90. data/spec/spec.opts +6 -0
  91. data/spec/spec_helper.rb +26 -0
  92. data/utils/remap.rb +27 -0
  93. data/utils/subset.rb +30 -0
  94. metadata +203 -0
@@ -0,0 +1,190 @@
1
+ require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
2
+ require File.join(FIXTURE_PATH, 'more', 'card')
3
+ require File.join(FIXTURE_PATH, 'more', 'invoice')
4
+ require File.join(FIXTURE_PATH, 'more', 'service')
5
+ require File.join(FIXTURE_PATH, 'more', 'event')
6
+ require File.join(FIXTURE_PATH, 'more', 'location')
7
+
8
+
9
+ describe "ExtendedDocument properties" do
10
+
11
+ before(:each) do
12
+ reset_test_db!
13
+ @card = Card.new(:first_name => "matt")
14
+ end
15
+
16
+ it "should be accessible from the object" do
17
+ @card.properties.should be_an_instance_of(Array)
18
+ @card.properties.map{|p| p.name}.should include("first_name")
19
+ end
20
+
21
+ it "should let you access a property value (getter)" do
22
+ @card.first_name.should == "matt"
23
+ end
24
+
25
+ it "should let you set a property value (setter)" do
26
+ @card.last_name = "Aimonetti"
27
+ @card.last_name.should == "Aimonetti"
28
+ end
29
+
30
+ it "should not let you set a property value if it's read only" do
31
+ lambda{@card.read_only_value = "test"}.should raise_error
32
+ end
33
+
34
+ it "should let you use an alias for an attribute" do
35
+ @card.last_name = "Aimonetti"
36
+ @card.family_name.should == "Aimonetti"
37
+ @card.family_name.should == @card.last_name
38
+ end
39
+
40
+ it "should be auto timestamped" do
41
+ @card.created_at.should be_nil
42
+ @card.updated_at.should be_nil
43
+ @card.save.should be_true
44
+ @card.created_at.should_not be_nil
45
+ @card.updated_at.should_not be_nil
46
+ end
47
+
48
+ describe "validation" do
49
+ before(:each) do
50
+ @invoice = Invoice.new(:client_name => "matt", :employee_name => "Chris", :location => "San Diego, CA")
51
+ end
52
+
53
+ it "should be able to be validated" do
54
+ @card.valid?.should == true
55
+ end
56
+
57
+ it "should let you validate the presence of an attribute" do
58
+ @card.first_name = nil
59
+ @card.should_not be_valid
60
+ @card.errors.should_not be_empty
61
+ @card.errors.on(:first_name).should == ["First name must not be blank"]
62
+ end
63
+
64
+ it "should let you look up errors for a field by a string name" do
65
+ @card.first_name = nil
66
+ @card.should_not be_valid
67
+ @card.errors.on('first_name').should == ["First name must not be blank"]
68
+ end
69
+
70
+ it "should validate the presence of 2 attributes" do
71
+ @invoice.clear
72
+ @invoice.should_not be_valid
73
+ @invoice.errors.should_not be_empty
74
+ @invoice.errors.on(:client_name).first.should == "Client name must not be blank"
75
+ @invoice.errors.on(:employee_name).should_not be_empty
76
+ end
77
+
78
+ it "should let you set an error message" do
79
+ @invoice.location = nil
80
+ @invoice.valid?
81
+ @invoice.errors.on(:location).should == ["Hey stupid!, you forgot the location"]
82
+ end
83
+
84
+ it "should validate before saving" do
85
+ @invoice.location = nil
86
+ @invoice.should_not be_valid
87
+ @invoice.save.should be_false
88
+ @invoice.should be_new_document
89
+ end
90
+ end
91
+
92
+ describe "autovalidation" do
93
+ before(:each) do
94
+ @service = Service.new(:name => "Coumpound analysis", :price => 3_000)
95
+ end
96
+
97
+ it "should be valid" do
98
+ @service.should be_valid
99
+ end
100
+
101
+ it "should not respond to properties not setup" do
102
+ @service.respond_to?(:client_name).should be_false
103
+ end
104
+
105
+ describe "property :name, :length => 4...20" do
106
+
107
+ it "should autovalidate the presence when length is set" do
108
+ @service.name = nil
109
+ @service.should_not be_valid
110
+ @service.errors.should_not be_nil
111
+ @service.errors.on(:name).first.should == "Name must be between 4 and 19 characters long"
112
+ end
113
+
114
+ it "should autovalidate the correct length" do
115
+ @service.name = "a"
116
+ @service.should_not be_valid
117
+ @service.errors.should_not be_nil
118
+ @service.errors.on(:name).first.should == "Name must be between 4 and 19 characters long"
119
+ end
120
+ end
121
+ end
122
+
123
+ describe "casting" do
124
+ describe "cast keys to any type" do
125
+ before(:all) do
126
+ event_doc = { :subject => "Some event", :occurs_at => Time.now }
127
+ e = Event.database.save_doc event_doc
128
+
129
+ @event = Event.get e['id']
130
+ end
131
+ it "should cast created_at to Time" do
132
+ @event['occurs_at'].should be_an_instance_of(Time)
133
+ end
134
+ end
135
+ end
136
+
137
+ describe "changes" do
138
+ before(:each) do
139
+ @service = Service.new(:name => "Coumpound analysis", :price => 3_000)
140
+ end
141
+
142
+ describe "new record" do
143
+ describe "initializing" do
144
+ it "should have all passed_keys as changed properties" do
145
+ @service.changed_attributes.should include(:name)
146
+ @service.changed_attributes.should include(:price)
147
+ end
148
+ end
149
+
150
+ describe "initializing with defaults" do
151
+ before(:each) do
152
+ @location = Location.new
153
+ end
154
+ it "should have all passed_keys as changed properties" do
155
+ @location.changed_attributes.should include(:city)
156
+ @location.changed_attributes.should include(:state)
157
+ @location.changed_attributes.should_not include(:zip)
158
+ end
159
+ end
160
+
161
+ describe "saving" do
162
+
163
+ it "should not have changed properties after save" do
164
+ @service.save
165
+ @service.changed_attributes.should be_empty
166
+ end
167
+
168
+ end
169
+
170
+ end
171
+
172
+ describe "existing record" do
173
+
174
+ before(:each) do
175
+ @service = Service.new(:name => "Coumpound analysis", :price => 3_000)
176
+ @service.save
177
+ end
178
+ describe "changing attributes" do
179
+ it "should know the changed attribute" do
180
+ @service.name = "New name"
181
+ @service.changed_attributes.should include(:name)
182
+ @service.changed_attributes.should_not include(:price)
183
+ end
184
+ end
185
+
186
+ end
187
+
188
+ end
189
+
190
+ end
@@ -0,0 +1,3 @@
1
+ This is an example README file.
2
+
3
+ More of the README, whee.
@@ -0,0 +1,11 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <title>Test</title>
5
+ </head>
6
+ <body>
7
+ <p>
8
+ Test
9
+ </p>
10
+ </body>
11
+ </html>
@@ -0,0 +1,34 @@
1
+ class Article < CouchRest::ExtendedDocument
2
+ use_database TEST_SERVER.default_database
3
+ unique_id :slug
4
+
5
+ view_by :date, :descending => true
6
+ view_by :user_id, :date
7
+
8
+ view_by :tags,
9
+ :map =>
10
+ "function(doc) {
11
+ if (doc['couchrest-type'] == 'Article' && doc.tags) {
12
+ doc.tags.forEach(function(tag){
13
+ emit(tag, 1);
14
+ });
15
+ }
16
+ }",
17
+ :reduce =>
18
+ "function(keys, values, rereduce) {
19
+ return sum(values);
20
+ }"
21
+
22
+ property :date
23
+ property :slug, :read_only => true
24
+ property :title
25
+ property :tags
26
+
27
+ timestamps!
28
+
29
+ save_callback :before, :generate_slug_from_title
30
+
31
+ def generate_slug_from_title
32
+ self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new_document?
33
+ end
34
+ end
@@ -0,0 +1,20 @@
1
+ class Card < CouchRest::ExtendedDocument
2
+ # Include the validation module to get access to the validation methods
3
+ include CouchRest::Validation
4
+ # set the auto_validation before defining the properties
5
+ auto_validate!
6
+
7
+ # Set the default database to use
8
+ use_database TEST_SERVER.default_database
9
+
10
+ # Official Schema
11
+ property :first_name
12
+ property :last_name, :alias => :family_name
13
+ property :read_only_value, :read_only => true
14
+
15
+ timestamps!
16
+
17
+ # Validation
18
+ validates_present :first_name
19
+
20
+ end
@@ -0,0 +1,14 @@
1
+ require File.join(FIXTURE_PATH, 'more', 'question')
2
+ require File.join(FIXTURE_PATH, 'more', 'person')
3
+
4
+ class Course < CouchRest::ExtendedDocument
5
+ use_database TEST_SERVER.default_database
6
+
7
+ property :title
8
+ property :questions, :cast_as => ['Question']
9
+ property :professor, :cast_as => 'Person'
10
+ property :final_test_at, :cast_as => 'Time'
11
+
12
+ view_by :title
13
+ view_by :dept, :ducktype => true
14
+ end
@@ -0,0 +1,6 @@
1
+ class Event < CouchRest::ExtendedDocument
2
+ use_database TEST_SERVER.default_database
3
+
4
+ property :subject
5
+ property :occurs_at, :cast_as => 'Time', :send => 'parse'
6
+ end
@@ -0,0 +1,17 @@
1
+ class Invoice < CouchRest::ExtendedDocument
2
+ # Include the validation module to get access to the validation methods
3
+ include CouchRest::Validation
4
+
5
+ # Set the default database to use
6
+ use_database TEST_SERVER.default_database
7
+
8
+ # Official Schema
9
+ property :client_name
10
+ property :employee_name
11
+ property :location
12
+
13
+ # Validation
14
+ validates_present :client_name, :employee_name
15
+ validates_present :location, :message => "Hey stupid!, you forgot the location"
16
+
17
+ end
@@ -0,0 +1,18 @@
1
+ class Location < CouchRest::ExtendedDocument
2
+ # Include the validation module to get access to the validation methods
3
+ include CouchRest::Validation
4
+ # set the auto_validation before defining the properties
5
+ auto_validate!
6
+
7
+ # Set the default database to use
8
+ use_database TEST_SERVER.default_database
9
+
10
+ # Official Schema
11
+ property :city, :default => "Ciudad de Buenos Aires"
12
+ property :state, :default => "Buenos Aires"
13
+ property :zip
14
+
15
+ timestamps!
16
+
17
+
18
+ end
@@ -0,0 +1,8 @@
1
+ class Person < Hash
2
+ include ::CouchRest::CastedModel
3
+ property :name
4
+
5
+ def last_name
6
+ name.last
7
+ end
8
+ end
@@ -0,0 +1,6 @@
1
+ class Question < Hash
2
+ include ::CouchRest::CastedModel
3
+
4
+ property :q
5
+ property :a
6
+ end
@@ -0,0 +1,12 @@
1
+ class Service < CouchRest::ExtendedDocument
2
+ # Include the validation module to get access to the validation methods
3
+ include CouchRest::Validation
4
+ auto_validate!
5
+ # Set the default database to use
6
+ use_database TEST_SERVER.default_database
7
+
8
+ # Official Schema
9
+ property :name, :length => 4...20
10
+ property :price, :type => Integer
11
+
12
+ end
@@ -0,0 +1,3 @@
1
+ function globalLib() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,3 @@
1
+ function justThisView() {
2
+ return "fixture";
3
+ };
@@ -0,0 +1,4 @@
1
+ function(doc) {
2
+ //include-lib
3
+ emit(null, null);
4
+ };
@@ -0,0 +1,3 @@
1
+ function(doc) {
2
+ emit(null, null);
3
+ };
@@ -0,0 +1,3 @@
1
+ function(ks,vs,co) {
2
+ return vs.length;
3
+ };
data/spec/spec.opts ADDED
@@ -0,0 +1,6 @@
1
+ --colour
2
+ --format
3
+ progress
4
+ --loadby
5
+ mtime
6
+ --reverse
@@ -0,0 +1,26 @@
1
+ require "rubygems"
2
+ require "spec" # Satisfies Autotest and anyone else not using the Rake tasks
3
+
4
+ require File.join(File.dirname(__FILE__), '..','lib','couchrest')
5
+ # check the following file to see how to use the spec'd features.
6
+
7
+ unless defined?(FIXTURE_PATH)
8
+ FIXTURE_PATH = File.join(File.dirname(__FILE__), '/fixtures')
9
+ SCRATCH_PATH = File.join(File.dirname(__FILE__), '/tmp')
10
+
11
+ COUCHHOST = "http://127.0.0.1:5984"
12
+ TESTDB = 'couchrest-test'
13
+ TEST_SERVER = CouchRest.new
14
+ TEST_SERVER.default_database = TESTDB
15
+ end
16
+
17
+ class Basic < CouchRest::ExtendedDocument
18
+ use_database TEST_SERVER.default_database
19
+ end
20
+
21
+ def reset_test_db!
22
+ cr = TEST_SERVER
23
+ db = cr.database(TESTDB)
24
+ db.recreate! rescue nil
25
+ db
26
+ end
data/utils/remap.rb ADDED
@@ -0,0 +1,27 @@
1
+ require 'rubygems'
2
+ require 'couchrest'
3
+
4
+ # set the source db and map view
5
+ source = CouchRest.new("http://127.0.0.1:5984").database('source-db')
6
+ source_view = 'mydesign/view-map'
7
+
8
+ # set the target db
9
+ target = CouchRest.new("http://127.0.0.1:5984").database('target-db')
10
+
11
+
12
+ pager = CouchRest::Pager.new(source)
13
+
14
+ # pager will yield once per uniq key in the source view
15
+
16
+ pager.key_reduce(source_view, 10000) do |key, values|
17
+ # create a doc from the key and the values
18
+ example_doc = {
19
+ :key => key,
20
+ :values => values.uniq
21
+ }
22
+
23
+ target.save(example_doc)
24
+
25
+ # keep us up to date with progress
26
+ puts k if (rand > 0.9)
27
+ end