mattetti-couchrest 0.2.1.0 → 0.13

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 (37) hide show
  1. data/README.md +6 -31
  2. data/Rakefile +1 -1
  3. data/examples/model/example.rb +13 -19
  4. data/lib/couchrest/core/database.rb +4 -3
  5. data/lib/couchrest/core/model.rb +615 -0
  6. data/lib/couchrest/core/response.rb +4 -5
  7. data/lib/couchrest/core/server.rb +1 -1
  8. data/lib/couchrest/mixins/callbacks.rb +33 -74
  9. data/lib/couchrest/mixins/design_doc.rb +1 -2
  10. data/lib/couchrest/mixins/document_queries.rb +1 -1
  11. data/lib/couchrest/mixins/extended_document_mixins.rb +1 -2
  12. data/lib/couchrest/mixins/properties.rb +3 -8
  13. data/lib/couchrest/mixins/validation.rb +1 -2
  14. data/lib/couchrest/mixins/views.rb +5 -5
  15. data/lib/couchrest/monkeypatches.rb +48 -65
  16. data/lib/couchrest/more/extended_document.rb +8 -75
  17. data/lib/couchrest/more/property.rb +1 -12
  18. data/lib/couchrest/support/class.rb +132 -148
  19. data/lib/couchrest.rb +8 -33
  20. data/spec/couchrest/core/database_spec.rb +23 -28
  21. data/spec/couchrest/core/model_spec.rb +856 -0
  22. data/spec/couchrest/more/casted_model_spec.rb +0 -14
  23. data/spec/couchrest/more/extended_doc_spec.rb +4 -450
  24. data/spec/couchrest/more/property_spec.rb +5 -16
  25. data/spec/spec_helper.rb +0 -4
  26. metadata +3 -16
  27. data/lib/couchrest/mixins/extended_attachments.rb +0 -68
  28. data/lib/couchrest/validation/validators/confirmation_validator.rb +0 -99
  29. data/spec/couchrest/more/casted_extended_doc_spec.rb +0 -40
  30. data/spec/couchrest/more/extended_doc_attachment_spec.rb +0 -129
  31. data/spec/couchrest/more/extended_doc_view_spec.rb +0 -206
  32. data/spec/couchrest/support/class_spec.rb +0 -59
  33. data/spec/fixtures/more/article.rb +0 -34
  34. data/spec/fixtures/more/course.rb +0 -14
  35. data/spec/fixtures/more/event.rb +0 -6
  36. data/spec/fixtures/more/person.rb +0 -8
  37. data/spec/fixtures/more/question.rb +0 -6
@@ -1,68 +0,0 @@
1
- module CouchRest
2
- module Mixins
3
- module ExtendedAttachments
4
-
5
- # creates a file attachment to the current doc
6
- def create_attachment(args={})
7
- raise ArgumentError unless args[:file] && args[:name]
8
- return if has_attachment?(args[:name])
9
- self['_attachments'] ||= {}
10
- set_attachment_attr(args)
11
- rescue ArgumentError => e
12
- raise ArgumentError, 'You must specify :file and :name'
13
- end
14
-
15
- # reads the data from an attachment
16
- def read_attachment(attachment_name)
17
- Base64.decode64(database.fetch_attachment(self, attachment_name))
18
- end
19
-
20
- # modifies a file attachment on the current doc
21
- def update_attachment(args={})
22
- raise ArgumentError unless args[:file] && args[:name]
23
- return unless has_attachment?(args[:name])
24
- delete_attachment(args[:name])
25
- set_attachment_attr(args)
26
- rescue ArgumentError => e
27
- raise ArgumentError, 'You must specify :file and :name'
28
- end
29
-
30
- # deletes a file attachment from the current doc
31
- def delete_attachment(attachment_name)
32
- return unless self['_attachments']
33
- self['_attachments'].delete attachment_name
34
- end
35
-
36
- # returns true if attachment_name exists
37
- def has_attachment?(attachment_name)
38
- !!(self['_attachments'] && self['_attachments'][attachment_name] && !self['_attachments'][attachment_name].empty?)
39
- end
40
-
41
- # returns URL to fetch the attachment from
42
- def attachment_url(attachment_name)
43
- return unless has_attachment?(attachment_name)
44
- "#{database.root}/#{self.id}/#{attachment_name}"
45
- end
46
-
47
- private
48
-
49
- def encode_attachment(data)
50
- ::Base64.encode64(data).gsub(/\r|\n/,'')
51
- end
52
-
53
- def get_mime_type(file)
54
- ::MIME::Types.type_for(file.path).empty? ?
55
- 'text\/plain' : MIME::Types.type_for(file.path).first.content_type.gsub(/\//,'\/')
56
- end
57
-
58
- def set_attachment_attr(args)
59
- content_type = args[:content_type] ? args[:content_type] : get_mime_type(args[:file])
60
- self['_attachments'][args[:name]] = {
61
- 'content-type' => content_type,
62
- 'data' => encode_attachment(args[:file].read)
63
- }
64
- end
65
-
66
- end # module ExtendedAttachments
67
- end
68
- end
@@ -1,99 +0,0 @@
1
- # Extracted from dm-validations 0.9.10
2
- #
3
- # Copyright (c) 2007 Guy van den Berg
4
- #
5
- # Permission is hereby granted, free of charge, to any person obtaining
6
- # a copy of this software and associated documentation files (the
7
- # "Software"), to deal in the Software without restriction, including
8
- # without limitation the rights to use, copy, modify, merge, publish,
9
- # distribute, sublicense, and/or sell copies of the Software, and to
10
- # permit persons to whom the Software is furnished to do so, subject to
11
- # the following conditions:
12
- #
13
- # The above copyright notice and this permission notice shall be
14
- # included in all copies or substantial portions of the Software.
15
- #
16
- # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
- # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
- # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
- # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
- # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
- # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
- # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23
-
24
- module CouchRest
25
- module Validation
26
-
27
- ##
28
- #
29
- # @author Guy van den Berg
30
- # @since 0.9
31
- class ConfirmationValidator < GenericValidator
32
-
33
- def initialize(field_name, options = {})
34
- super
35
- @options = options
36
- @field_name, @confirm_field_name = field_name, (options[:confirm] || "#{field_name}_confirmation").to_sym
37
- @options[:allow_nil] = true unless @options.has_key?(:allow_nil)
38
- end
39
-
40
- def call(target)
41
- unless valid?(target)
42
- error_message = @options[:message] || ValidationErrors.default_error_message(:confirmation, field_name)
43
- add_error(target, error_message, field_name)
44
- return false
45
- end
46
-
47
- return true
48
- end
49
-
50
- def valid?(target)
51
- field_value = target.send(field_name)
52
- return true if @options[:allow_nil] && field_value.nil?
53
- return false if !@options[:allow_nil] && field_value.nil?
54
-
55
- confirm_value = target.instance_variable_get("@#{@confirm_field_name}")
56
- field_value == confirm_value
57
- end
58
-
59
- end # class ConfirmationValidator
60
-
61
- module ValidatesIsConfirmed
62
-
63
- ##
64
- # Validates that the given attribute is confirmed by another attribute.
65
- # A common use case scenario is when you require a user to confirm their
66
- # password, for which you use both password and password_confirmation
67
- # attributes.
68
- #
69
- # @option :allow_nil<Boolean> true/false (default is true)
70
- # @option :confirm<Symbol> the attribute that you want to validate
71
- # against (default is firstattr_confirmation)
72
- #
73
- # @example [Usage]
74
- #
75
- # class Page < Hash
76
- # include CouchRest::ExtendedModel
77
- # include CouchRest::Validations
78
- #
79
- # property :password, String
80
- # property :email, String
81
- # attr_accessor :password_confirmation
82
- # attr_accessor :email_repeated
83
- #
84
- # validates_is_confirmed :password
85
- # validates_is_confirmed :email, :confirm => :email_repeated
86
- #
87
- # # a call to valid? will return false unless:
88
- # # password == password_confirmation
89
- # # and
90
- # # email == email_repeated
91
- #
92
- def validates_is_confirmed(*fields)
93
- opts = opts_from_validator_args(fields)
94
- add_validator_to_context(opts, fields, CouchRest::Validation::ConfirmationValidator)
95
- end
96
-
97
- end # module ValidatesIsConfirmed
98
- end # module Validation
99
- end # module CouchRest
@@ -1,40 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
2
- require File.join(FIXTURE_PATH, 'more', 'card')
3
-
4
- class Car < CouchRest::ExtendedDocument
5
- use_database TEST_SERVER.default_database
6
-
7
- property :name
8
- property :driver, :cast_as => 'Driver'
9
- end
10
-
11
- class Driver < CouchRest::ExtendedDocument
12
- use_database TEST_SERVER.default_database
13
- # You have to add a casted_by accessor if you want to reach a casted extended doc parent
14
- attr_accessor :casted_by
15
-
16
- property :name
17
- end
18
-
19
- describe "casting an extended document" do
20
-
21
- before(:each) do
22
- @car = Car.new(:name => 'Renault 306')
23
- @driver = Driver.new(:name => 'Matt')
24
- end
25
-
26
- # it "should not create an empty casted object" do
27
- # @car.driver.should be_nil
28
- # end
29
-
30
- it "should let you assign the casted attribute after instantializing an object" do
31
- @car.driver = @driver
32
- @car.driver.name.should == 'Matt'
33
- end
34
-
35
- it "should let the casted document who casted it" do
36
- Car.new(:name => 'Renault 306', :driver => @driver)
37
- @car.driver.casted_by.should == @car
38
- end
39
-
40
- end
@@ -1,129 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
2
-
3
- describe "ExtendedDocument attachments" do
4
-
5
- describe "#has_attachment?" do
6
- before(:each) do
7
- @obj = Basic.new
8
- @obj.save.should == true
9
- @file = File.open(FIXTURE_PATH + '/attachments/test.html')
10
- @attachment_name = 'my_attachment'
11
- @obj.create_attachment(:file => @file, :name => @attachment_name)
12
- end
13
-
14
- it 'should return false if there is no attachment' do
15
- @obj.has_attachment?('bogus').should be_false
16
- end
17
-
18
- it 'should return true if there is an attachment' do
19
- @obj.has_attachment?(@attachment_name).should be_true
20
- end
21
-
22
- it 'should return true if an object with an attachment is reloaded' do
23
- @obj.save.should be_true
24
- reloaded_obj = Basic.get(@obj.id)
25
- reloaded_obj.has_attachment?(@attachment_name).should be_true
26
- end
27
-
28
- it 'should return false if an attachment has been removed' do
29
- @obj.delete_attachment(@attachment_name)
30
- @obj.has_attachment?(@attachment_name).should be_false
31
- end
32
- end
33
-
34
- describe "creating an attachment" do
35
- before(:each) do
36
- @obj = Basic.new
37
- @obj.save.should == true
38
- @file_ext = File.open(FIXTURE_PATH + '/attachments/test.html')
39
- @file_no_ext = File.open(FIXTURE_PATH + '/attachments/README')
40
- @attachment_name = 'my_attachment'
41
- @content_type = 'media/mp3'
42
- end
43
-
44
- it "should create an attachment from file with an extension" do
45
- @obj.create_attachment(:file => @file_ext, :name => @attachment_name)
46
- @obj.save.should == true
47
- reloaded_obj = Basic.get(@obj.id)
48
- reloaded_obj['_attachments'][@attachment_name].should_not be_nil
49
- end
50
-
51
- it "should create an attachment from file without an extension" do
52
- @obj.create_attachment(:file => @file_no_ext, :name => @attachment_name)
53
- @obj.save.should == true
54
- reloaded_obj = Basic.get(@obj.id)
55
- reloaded_obj['_attachments'][@attachment_name].should_not be_nil
56
- end
57
-
58
- it 'should raise ArgumentError if :file is missing' do
59
- lambda{ @obj.create_attachment(:name => @attachment_name) }.should raise_error
60
- end
61
-
62
- it 'should raise ArgumentError if :name is missing' do
63
- lambda{ @obj.create_attachment(:file => @file_ext) }.should raise_error
64
- end
65
-
66
- it 'should set the content-type if passed' do
67
- @obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
68
- @obj['_attachments'][@attachment_name]['content-type'].should == @content_type
69
- end
70
- end
71
-
72
- describe 'reading, updating, and deleting an attachment' do
73
- before(:each) do
74
- @obj = Basic.new
75
- @file = File.open(FIXTURE_PATH + '/attachments/test.html')
76
- @attachment_name = 'my_attachment'
77
- @obj.create_attachment(:file => @file, :name => @attachment_name)
78
- @obj.save.should == true
79
- @file.rewind
80
- @content_type = 'media/mp3'
81
- end
82
-
83
- it 'should read an attachment that exists' do
84
- @obj.read_attachment(@attachment_name).should == @file.read
85
- end
86
-
87
- it 'should update an attachment that exists' do
88
- file = File.open(FIXTURE_PATH + '/attachments/README')
89
- @file.should_not == file
90
- @obj.update_attachment(:file => file, :name => @attachment_name)
91
- @obj.save
92
- reloaded_obj = Basic.get(@obj.id)
93
- file.rewind
94
- reloaded_obj.read_attachment(@attachment_name).should_not == @file.read
95
- reloaded_obj.read_attachment(@attachment_name).should == file.read
96
- end
97
-
98
- it 'should se the content-type if passed' do
99
- file = File.open(FIXTURE_PATH + '/attachments/README')
100
- @file.should_not == file
101
- @obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
102
- @obj['_attachments'][@attachment_name]['content-type'].should == @content_type
103
- end
104
-
105
- it 'should delete an attachment that exists' do
106
- @obj.delete_attachment(@attachment_name)
107
- @obj.save
108
- lambda{Basic.get(@obj.id).read_attachment(@attachment_name)}.should raise_error
109
- end
110
- end
111
-
112
- describe "#attachment_url" do
113
- before(:each) do
114
- @obj = Basic.new
115
- @file = File.open(FIXTURE_PATH + '/attachments/test.html')
116
- @attachment_name = 'my_attachment'
117
- @obj.create_attachment(:file => @file, :name => @attachment_name)
118
- @obj.save.should == true
119
- end
120
-
121
- it 'should return nil if attachment does not exist' do
122
- @obj.attachment_url('bogus').should be_nil
123
- end
124
-
125
- it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do
126
- @obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
127
- end
128
- end
129
- end
@@ -1,206 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
2
- require File.join(FIXTURE_PATH, 'more', 'article')
3
- require File.join(FIXTURE_PATH, 'more', 'course')
4
-
5
- describe "ExtendedDocument views" do
6
-
7
- describe "a model with simple views and a default param" do
8
- before(:all) do
9
- Article.all.map{|a| a.destroy(true)}
10
- Article.database.bulk_delete
11
- written_at = Time.now - 24 * 3600 * 7
12
- @titles = ["this and that", "also interesting", "more fun", "some junk"]
13
- @titles.each do |title|
14
- a = Article.new(:title => title)
15
- a.date = written_at
16
- a.save
17
- written_at += 24 * 3600
18
- end
19
- end
20
-
21
- it "should have a design doc" do
22
- Article.design_doc["views"]["by_date"].should_not be_nil
23
- end
24
-
25
- it "should save the design doc" do
26
- Article.by_date #rescue nil
27
- doc = Article.database.get Article.design_doc.id
28
- doc['views']['by_date'].should_not be_nil
29
- end
30
-
31
- it "should return the matching raw view result" do
32
- view = Article.by_date :raw => true
33
- view['rows'].length.should == 4
34
- end
35
-
36
- it "should not include non-Articles" do
37
- Article.database.save_doc({"date" => 1})
38
- view = Article.by_date :raw => true
39
- view['rows'].length.should == 4
40
- end
41
-
42
- it "should return the matching objects (with default argument :descending => true)" do
43
- articles = Article.by_date
44
- articles.collect{|a|a.title}.should == @titles.reverse
45
- end
46
-
47
- it "should allow you to override default args" do
48
- articles = Article.by_date :descending => false
49
- articles.collect{|a|a.title}.should == @titles
50
- end
51
- end
52
-
53
- describe "another model with a simple view" do
54
- before(:all) do
55
- reset_test_db!
56
- %w{aaa bbb ddd eee}.each do |title|
57
- Course.new(:title => title).save
58
- end
59
- end
60
- it "should make the design doc upon first query" do
61
- Course.by_title
62
- doc = Course.design_doc
63
- doc['views']['all']['map'].should include('Course')
64
- end
65
- it "should can query via view" do
66
- # register methods with method-missing, for local dispatch. method
67
- # missing lookup table, no heuristics.
68
- view = Course.view :by_title
69
- designed = Course.by_title
70
- view.should == designed
71
- end
72
- it "should get them" do
73
- rs = Course.by_title
74
- rs.length.should == 4
75
- end
76
- it "should yield" do
77
- courses = []
78
- rs = Course.by_title # remove me
79
- Course.view(:by_title) do |course|
80
- courses << course
81
- end
82
- courses[0]["doc"]["title"].should =='aaa'
83
- end
84
- end
85
-
86
-
87
- describe "a ducktype view" do
88
- before(:all) do
89
- @id = TEST_SERVER.default_database.save_doc({:dept => true})['id']
90
- end
91
- it "should setup" do
92
- duck = Course.get(@id) # from a different db
93
- duck["dept"].should == true
94
- end
95
- it "should make the design doc" do
96
- @as = Course.by_dept
97
- @doc = Course.design_doc
98
- @doc["views"]["by_dept"]["map"].should_not include("couchrest")
99
- end
100
- it "should not look for class" do |variable|
101
- @as = Course.by_dept
102
- @as[0]['_id'].should == @id
103
- end
104
- end
105
-
106
- describe "a model with a compound key view" do
107
- before(:all) do
108
- Article.design_doc_fresh = false
109
- Article.by_user_id_and_date.each{|a| a.destroy(true)}
110
- Article.database.bulk_delete
111
- written_at = Time.now - 24 * 3600 * 7
112
- @titles = ["uniq one", "even more interesting", "less fun", "not junk"]
113
- @user_ids = ["quentin", "aaron"]
114
- @titles.each_with_index do |title,i|
115
- u = i % 2
116
- a = Article.new(:title => title, :user_id => @user_ids[u])
117
- a.date = written_at
118
- a.save
119
- written_at += 24 * 3600
120
- end
121
- end
122
- it "should create the design doc" do
123
- Article.by_user_id_and_date rescue nil
124
- doc = Article.design_doc
125
- doc['views']['by_date'].should_not be_nil
126
- end
127
- it "should sort correctly" do
128
- articles = Article.by_user_id_and_date
129
- articles.collect{|a|a['user_id']}.should == ['aaron', 'aaron', 'quentin',
130
- 'quentin']
131
- articles[1].title.should == 'not junk'
132
- end
133
- it "should be queryable with couchrest options" do
134
- articles = Article.by_user_id_and_date :limit => 1, :startkey => 'quentin'
135
- articles.length.should == 1
136
- articles[0].title.should == "even more interesting"
137
- end
138
- end
139
-
140
- describe "with a custom view" do
141
- before(:all) do
142
- @titles = ["very uniq one", "even less interesting", "some fun",
143
- "really junk", "crazy bob"]
144
- @tags = ["cool", "lame"]
145
- @titles.each_with_index do |title,i|
146
- u = i % 2
147
- a = Article.new(:title => title, :tags => [@tags[u]])
148
- a.save
149
- end
150
- end
151
- it "should be available raw" do
152
- view = Article.by_tags :raw => true
153
- view['rows'].length.should == 5
154
- end
155
-
156
- it "should be default to :reduce => false" do
157
- ars = Article.by_tags
158
- ars.first.tags.first.should == 'cool'
159
- end
160
-
161
- it "should be raw when reduce is true" do
162
- view = Article.by_tags :reduce => true, :group => true
163
- view['rows'].find{|r|r['key'] == 'cool'}['value'].should == 3
164
- end
165
- end
166
-
167
- # TODO: moved to Design, delete
168
- describe "adding a view" do
169
- before(:each) do
170
- reset_test_db!
171
- Article.by_date
172
- @design_docs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999"
173
- end
174
- it "should not create a design doc on view definition" do
175
- Article.view_by :created_at
176
- newdocs = Article.database.documents :startkey => "_design/", :endkey => "_design/\u9999"
177
- newdocs["rows"].length.should == @design_docs["rows"].length
178
- end
179
- it "should create a new version of the design document on view access" do
180
- old_design_doc = Article.database.documents(:key => @design_docs["rows"].first["key"], :include_docs => true)["rows"][0]["doc"]
181
- Article.view_by :updated_at
182
- Article.by_updated_at
183
- newdocs = Article.database.documents({:startkey => "_design/", :endkey => "_design/\u9999"})
184
-
185
- doc = Article.database.documents(:key => @design_docs["rows"].first["key"], :include_docs => true)["rows"][0]["doc"]
186
- doc["_rev"].should_not == old_design_doc["_rev"]
187
- doc["views"].keys.should include("by_updated_at")
188
- end
189
- end
190
-
191
- describe "with a lot of designs left around" do
192
- before(:each) do
193
- Article.by_date
194
- Article.view_by :field
195
- Article.by_field
196
- end
197
- it "should clean them up" do
198
- ddocs = Article.all_design_doc_versions
199
- Article.view_by :stream
200
- Article.by_stream
201
- Article.cleanup_design_docs!
202
- ddocs = Article.all_design_doc_versions
203
- ddocs["rows"].length.should == 1
204
- end
205
- end
206
- end
@@ -1,59 +0,0 @@
1
- require File.join(File.dirname(__FILE__), '..', '..', 'spec_helper')
2
- require File.join(File.dirname(__FILE__), '..', '..', '..', 'lib', 'couchrest', 'support', 'class')
3
-
4
- describe CouchRest::ClassExtension do
5
-
6
- before :all do
7
- class FullyDefinedClassExtensions
8
- def self.respond_to?(method)
9
- if CouchRest::ClassExtension::InstanceMethods.instance_methods.include?(method)
10
- true
11
- else
12
- super
13
- end
14
- end
15
- end
16
-
17
- class PartDefinedClassExtensions
18
- def self.respond_to?(method)
19
- methods = CouchRest::ClassExtension::InstanceMethods.instance_methods
20
- methods.delete('cattr_reader')
21
-
22
- if methods.include?(method)
23
- false
24
- else
25
- super
26
- end
27
- end
28
- end
29
-
30
- class NoClassExtensions
31
- def self.respond_to?(method)
32
- if CouchRest::ClassExtension::InstanceMethods.instance_methods.include?(method)
33
- false
34
- else
35
- super
36
- end
37
- end
38
- end
39
-
40
-
41
- end
42
-
43
- it "should not include InstanceMethods if the class extensions are already defined" do
44
- FullyDefinedClassExtensions.send(:include, CouchRest::ClassExtension)
45
- FullyDefinedClassExtensions.ancestors.should_not include(CouchRest::ClassExtension::InstanceMethods)
46
- end
47
-
48
- it "should raise RuntimeError if the class extensions are only partially defined" do
49
- lambda {
50
- PartDefinedClassExtensions.send(:include, CouchRest::ClassExtension)
51
- }.should raise_error(RuntimeError)
52
- end
53
-
54
- it "should include class extensions if they are not already defined" do
55
- NoClassExtensions.send(:include, CouchRest::ClassExtension)
56
- NoClassExtensions.ancestors.should include(CouchRest::ClassExtension::InstanceMethods)
57
- end
58
-
59
- end
@@ -1,34 +0,0 @@
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
@@ -1,14 +0,0 @@
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
@@ -1,6 +0,0 @@
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
@@ -1,8 +0,0 @@
1
- class Person < Hash
2
- include ::CouchRest::CastedModel
3
- property :name
4
-
5
- def last_name
6
- name.last
7
- end
8
- end
@@ -1,6 +0,0 @@
1
- class Question < Hash
2
- include ::CouchRest::CastedModel
3
-
4
- property :q
5
- property :a
6
- end