couchrest_model 2.1.0.rc1 → 2.2.0.beta1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (56) hide show
  1. checksums.yaml +4 -4
  2. data/.gitignore +1 -1
  3. data/.travis.yml +15 -4
  4. data/Gemfile.activesupport-4.x +4 -0
  5. data/Gemfile.activesupport-5.x +4 -0
  6. data/README.md +2 -0
  7. data/VERSION +1 -1
  8. data/couchrest_model.gemspec +3 -2
  9. data/history.md +14 -1
  10. data/lib/couchrest/model/associations.rb +3 -8
  11. data/lib/couchrest/model/base.rb +15 -7
  12. data/lib/couchrest/model/casted_array.rb +22 -34
  13. data/lib/couchrest/model/configuration.rb +2 -0
  14. data/lib/couchrest/model/design.rb +4 -3
  15. data/lib/couchrest/model/designs/view.rb +37 -32
  16. data/lib/couchrest/model/dirty.rb +93 -19
  17. data/lib/couchrest/model/embeddable.rb +2 -14
  18. data/lib/couchrest/model/extended_attachments.rb +2 -4
  19. data/lib/couchrest/model/persistence.rb +14 -17
  20. data/lib/couchrest/model/properties.rb +46 -54
  21. data/lib/couchrest/model/property.rb +0 -3
  22. data/lib/couchrest/model/proxyable.rb +20 -4
  23. data/lib/couchrest/model/validations/uniqueness.rb +4 -1
  24. data/lib/couchrest_model.rb +2 -2
  25. data/spec/fixtures/models/article.rb +1 -1
  26. data/spec/fixtures/models/card.rb +2 -1
  27. data/spec/fixtures/models/person.rb +1 -0
  28. data/spec/fixtures/models/project.rb +3 -0
  29. data/spec/unit/assocations_spec.rb +73 -73
  30. data/spec/unit/attachment_spec.rb +34 -34
  31. data/spec/unit/base_spec.rb +102 -102
  32. data/spec/unit/casted_array_spec.rb +7 -7
  33. data/spec/unit/casted_spec.rb +7 -7
  34. data/spec/unit/configuration_spec.rb +11 -11
  35. data/spec/unit/connection_spec.rb +30 -30
  36. data/spec/unit/core_extensions/{time_parsing.rb → time_parsing_spec.rb} +21 -21
  37. data/spec/unit/design_spec.rb +38 -38
  38. data/spec/unit/designs/design_mapper_spec.rb +26 -26
  39. data/spec/unit/designs/migrations_spec.rb +13 -13
  40. data/spec/unit/designs/view_spec.rb +319 -274
  41. data/spec/unit/designs_spec.rb +39 -39
  42. data/spec/unit/dirty_spec.rb +188 -103
  43. data/spec/unit/embeddable_spec.rb +119 -117
  44. data/spec/unit/inherited_spec.rb +4 -4
  45. data/spec/unit/persistence_spec.rb +122 -122
  46. data/spec/unit/properties_spec.rb +466 -16
  47. data/spec/unit/property_protection_spec.rb +32 -32
  48. data/spec/unit/property_spec.rb +45 -436
  49. data/spec/unit/proxyable_spec.rb +140 -82
  50. data/spec/unit/subclass_spec.rb +14 -14
  51. data/spec/unit/translations_spec.rb +5 -5
  52. data/spec/unit/typecast_spec.rb +131 -131
  53. data/spec/unit/utils/migrate_spec.rb +2 -2
  54. data/spec/unit/validations_spec.rb +31 -31
  55. metadata +27 -12
  56. data/lib/couchrest/model/casted_hash.rb +0 -84
@@ -4,9 +4,12 @@ module CouchRest
4
4
  module Proxyable
5
5
  extend ActiveSupport::Concern
6
6
 
7
- def proxy_database
7
+ def proxy_database(assoc_name)
8
8
  raise StandardError, "Please set the #proxy_database_method" if self.class.proxy_database_method.nil?
9
- @proxy_database ||= self.class.prepare_database(self.send(self.class.proxy_database_method))
9
+ db_name = self.send(self.class.proxy_database_method)
10
+ db_suffix = self.class.proxy_database_suffixes[assoc_name.to_sym]
11
+ @proxy_databases ||= {}
12
+ @proxy_databases[assoc_name.to_sym] ||= self.class.prepare_database([db_name, db_suffix].compact.reject(&:blank?).join(self.class.connection[:join]))
10
13
  end
11
14
 
12
15
  module ClassMethods
@@ -15,13 +18,16 @@ module CouchRest
15
18
  # Define a collection that will use the base model for the database connection
16
19
  # details.
17
20
  def proxy_for(assoc_name, options = {})
18
- db_method = options[:database_method] || "proxy_database"
21
+ db_method = (options[:database_method] || "proxy_database").to_sym
22
+ db_suffix = options[:database_suffix] || (options[:use_suffix] ? assoc_name.to_s : nil)
19
23
  options[:class_name] ||= assoc_name.to_s.singularize.camelize
20
24
  proxy_method_names << assoc_name.to_sym unless proxy_method_names.include?(assoc_name.to_sym)
21
25
  proxied_model_names << options[:class_name] unless proxied_model_names.include?(options[:class_name])
26
+ proxy_database_suffixes[assoc_name.to_sym] = db_suffix
27
+ db_method_call = "#{db_method}(:#{assoc_name.to_s})"
22
28
  class_eval <<-EOS, __FILE__, __LINE__ + 1
23
29
  def #{assoc_name}
24
- @#{assoc_name} ||= CouchRest::Model::Proxyable::ModelProxy.new(::#{options[:class_name]}, self, self.class.to_s.underscore, #{db_method})
30
+ @#{assoc_name} ||= CouchRest::Model::Proxyable::ModelProxy.new(::#{options[:class_name]}, self, self.class.to_s.underscore, #{db_method_call})
25
31
  end
26
32
  EOS
27
33
  end
@@ -57,6 +63,10 @@ module CouchRest
57
63
  @proxied_model_names ||= []
58
64
  end
59
65
 
66
+ def proxy_database_suffixes
67
+ @proxy_database_suffixes ||= {}
68
+ end
69
+
60
70
  private
61
71
 
62
72
  # Ensure that no attempt is made to autoload a database connection
@@ -156,6 +166,12 @@ module CouchRest
156
166
  end
157
167
  end
158
168
 
169
+ private
170
+
171
+ def method_missing(m, *args, &block)
172
+ model.respond_to?(m) ? model.send(m, self, *args, &block) : super
173
+ end
174
+
159
175
  end
160
176
  end
161
177
  end
@@ -1,4 +1,7 @@
1
- # encoding: utf-8
1
+
2
+ I18n.load_path << File.join(
3
+ File.dirname(__FILE__), "locale", "en.yml"
4
+ )
2
5
 
3
6
  module CouchRest
4
7
  module Model
@@ -17,6 +17,7 @@ require "enumerator"
17
17
  require "time"
18
18
  require "digest/md5"
19
19
  require "yaml"
20
+ require "hashdiff"
20
21
 
21
22
  require "bigdecimal" # used in typecast
22
23
  require "bigdecimal/util" # used in typecast
@@ -25,6 +26,7 @@ require "couchrest"
25
26
 
26
27
  require "couchrest/model"
27
28
  require "couchrest/model/errors"
29
+ require "couchrest/model/configuration"
28
30
  require "couchrest/model/translation"
29
31
  require "couchrest/model/persistence"
30
32
  require "couchrest/model/typecast"
@@ -34,14 +36,12 @@ require "couchrest/model/property"
34
36
  require "couchrest/model/property_protection"
35
37
  require "couchrest/model/properties"
36
38
  require "couchrest/model/casted_array"
37
- require "couchrest/model/casted_hash"
38
39
  require "couchrest/model/validations"
39
40
  require "couchrest/model/callbacks"
40
41
  require "couchrest/model/document_queries"
41
42
  require "couchrest/model/extended_attachments"
42
43
  require "couchrest/model/proxyable"
43
44
  require "couchrest/model/associations"
44
- require "couchrest/model/configuration"
45
45
  require "couchrest/model/connection"
46
46
  require "couchrest/model/designs/migrations"
47
47
  require "couchrest/model/designs/design_mapper"
@@ -33,6 +33,6 @@ class Article < CouchRest::Model::Base
33
33
  before_save :generate_slug_from_title
34
34
 
35
35
  def generate_slug_from_title
36
- self['slug'] = title.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new?
36
+ self['slug'] = title.to_s.downcase.gsub(/[^a-z0-9]/,'-').squeeze('-').gsub(/^\-|\-$/,'') if new?
37
37
  end
38
38
  end
@@ -9,7 +9,8 @@ class Card < CouchRest::Model::Base
9
9
  property :last_name, :alias => :family_name
10
10
  property :read_only_value, :read_only => true
11
11
  property :cast_alias, Person, :alias => :calias
12
- property :fg_color, :default => '#000'
12
+ property :fg_color, String, :default => '#000'
13
+ property :bg_color, String, :protected => true
13
14
 
14
15
  timestamps!
15
16
 
@@ -2,6 +2,7 @@ require 'cat'
2
2
 
3
3
  class Person
4
4
  include ::CouchRest::Model::Embeddable
5
+
5
6
  property :pet, Cat
6
7
  property :name, [String]
7
8
 
@@ -1,5 +1,8 @@
1
1
  class Project < CouchRest::Model::Base
2
2
  use_database DB
3
+
4
+ disable_dirty_tracking true
5
+
3
6
  property :name, String
4
7
  timestamps!
5
8
 
@@ -12,22 +12,22 @@ describe "Assocations" do
12
12
 
13
13
  it "should return a default set of options" do
14
14
  o = SaleInvoice.merge_assoc_opts(:cat)
15
- o[:foreign_key].should eql('cat_id')
16
- o[:class_name].should eql('Cat')
17
- o[:proxy_name].should eql('cats')
18
- o[:proxy].should eql('Cat') # same as class name
15
+ expect(o[:foreign_key]).to eql('cat_id')
16
+ expect(o[:class_name]).to eql('Cat')
17
+ expect(o[:proxy_name]).to eql('cats')
18
+ expect(o[:proxy]).to eql('Cat') # same as class name
19
19
  end
20
20
 
21
21
  it "should merge with provided options" do
22
22
  o = SaleInvoice.merge_assoc_opts(:cat, :foreign_key => 'somecat_id', :proxy => 'some_cats')
23
- o[:foreign_key].should eql('somecat_id')
24
- o[:proxy].should eql('some_cats')
23
+ expect(o[:foreign_key]).to eql('somecat_id')
24
+ expect(o[:proxy]).to eql('some_cats')
25
25
  end
26
26
 
27
27
  it "should generate a proxy string if proxied" do
28
- SaleInvoice.stub(:proxy_owner_method).twice.and_return('company')
28
+ allow(SaleInvoice).to receive(:proxy_owner_method).twice.and_return('company')
29
29
  o = SaleInvoice.merge_assoc_opts(:cat)
30
- o[:proxy].should eql('self.company.cats')
30
+ expect(o[:proxy]).to eql('self.company.cats')
31
31
  end
32
32
 
33
33
  end
@@ -40,59 +40,59 @@ describe "Assocations" do
40
40
  end
41
41
 
42
42
  it "should create a foreign key property with setter and getter" do
43
- @invoice.properties.find{|p| p.name == 'client_id'}.should_not be_nil
44
- @invoice.respond_to?(:client_id).should be_true
45
- @invoice.respond_to?("client_id=").should be_true
43
+ expect(@invoice.properties.find{|p| p.name == 'client_id'}).not_to be_nil
44
+ expect(@invoice.respond_to?(:client_id)).to be_truthy
45
+ expect(@invoice.respond_to?("client_id=")).to be_truthy
46
46
  end
47
47
 
48
48
  it "should set the property and provide object when set" do
49
49
  @invoice.client = @client
50
- @invoice.client_id.should eql(@client.id)
51
- @invoice.client.should eql(@client)
50
+ expect(@invoice.client_id).to eql(@client.id)
51
+ expect(@invoice.client).to eql(@client)
52
52
  end
53
53
 
54
54
  it "should set the attribute, save and return" do
55
55
  @invoice.client = @client
56
56
  @invoice.save
57
57
  @invoice = SaleInvoice.get(@invoice.id)
58
- @invoice.client.id.should eql(@client.id)
58
+ expect(@invoice.client.id).to eql(@client.id)
59
59
  end
60
60
 
61
61
  it "should remove the association if nil is provided" do
62
62
  @invoice.client = @client
63
63
  @invoice.client = nil
64
- @invoice.client_id.should be_nil
64
+ expect(@invoice.client_id).to be_nil
65
65
  end
66
66
 
67
67
  it "should not try to search for association if foreign_key is nil" do
68
68
  @invoice.client_id = nil
69
- Client.should_not_receive(:get)
69
+ expect(Client).not_to receive(:get)
70
70
  @invoice.client
71
71
  end
72
72
 
73
73
  it "should ignore blank ids" do
74
74
  @invoice.client_id = ""
75
- @invoice.client_id.should be_nil
75
+ expect(@invoice.client_id).to be_nil
76
76
  end
77
77
 
78
78
  it "should allow replacement of object after updating key" do
79
79
  @invoice.client = @client
80
- @invoice.client.should eql(@client)
80
+ expect(@invoice.client).to eql(@client)
81
81
  @invoice.client_id = nil
82
- @invoice.client.should be_nil
82
+ expect(@invoice.client).to be_nil
83
83
  end
84
84
 
85
85
  it "should allow override of foreign key" do
86
- @invoice.respond_to?(:alternate_client).should be_true
87
- @invoice.respond_to?("alternate_client=").should be_true
88
- @invoice.properties.find{|p| p.name == 'alt_client_id'}.should_not be_nil
86
+ expect(@invoice.respond_to?(:alternate_client)).to be_truthy
87
+ expect(@invoice.respond_to?("alternate_client=")).to be_truthy
88
+ expect(@invoice.properties.find{|p| p.name == 'alt_client_id'}).not_to be_nil
89
89
  end
90
90
 
91
91
  it "should allow override of foreign key and save" do
92
92
  @invoice.alternate_client = @client
93
93
  @invoice.save
94
94
  @invoice = SaleInvoice.get(@invoice.id)
95
- @invoice.alternate_client.id.should eql(@client.id)
95
+ expect(@invoice.alternate_client.id).to eql(@client.id)
96
96
  end
97
97
 
98
98
  end
@@ -109,95 +109,95 @@ describe "Assocations" do
109
109
  end
110
110
 
111
111
  it "should create an associated property and collection proxy" do
112
- @invoice.respond_to?('entry_ids').should be_true
113
- @invoice.respond_to?('entry_ids=').should be_true
114
- @invoice.entries.class.should eql(::CouchRest::Model::CollectionOfProxy)
112
+ expect(@invoice.respond_to?('entry_ids')).to be_truthy
113
+ expect(@invoice.respond_to?('entry_ids=')).to be_truthy
114
+ expect(@invoice.entries.class).to eql(::CouchRest::Model::CollectionOfProxy)
115
115
  end
116
116
 
117
117
  it "should allow replacement of objects" do
118
118
  @invoice.entries = @entries
119
- @invoice.entries.length.should eql(3)
120
- @invoice.entry_ids.length.should eql(3)
121
- @invoice.entries.first.should eql(@entries.first)
122
- @invoice.entry_ids.first.should eql(@entries.first.id)
119
+ expect(@invoice.entries.length).to eql(3)
120
+ expect(@invoice.entry_ids.length).to eql(3)
121
+ expect(@invoice.entries.first).to eql(@entries.first)
122
+ expect(@invoice.entry_ids.first).to eql(@entries.first.id)
123
123
  end
124
124
 
125
125
  it "should allow ids to be set directly and load entries" do
126
126
  @invoice.entry_ids = @entries.collect{|i| i.id}
127
- @invoice.entries.length.should eql(3)
128
- @invoice.entries.first.should eql(@entries.first)
129
- @invoice.changed?.should be_true
127
+ expect(@invoice.entries.length).to eql(3)
128
+ expect(@invoice.entries.first).to eql(@entries.first)
129
+ expect(@invoice.changed?).to be_truthy
130
130
  end
131
131
 
132
132
  it "should ignore blank ids when set directly" do
133
133
  @invoice.entry_ids = ["", @entries.first.id]
134
- @invoice.entry_ids.length.should be(1)
134
+ expect(@invoice.entry_ids.length).to be(1)
135
135
  end
136
136
 
137
137
  it "should replace collection if ids replaced" do
138
138
  @invoice.entry_ids = @entries.collect{|i| i.id}
139
- @invoice.entries.length.should eql(3) # load once
139
+ expect(@invoice.entries.length).to eql(3) # load once
140
140
  @invoice.entry_ids = @entries[0..1].collect{|i| i.id}
141
- @invoice.entries.length.should eql(2)
141
+ expect(@invoice.entries.length).to eql(2)
142
142
  end
143
143
 
144
144
  it "should allow forced collection update if ids changed" do
145
145
  @invoice.entry_ids = @entries[0..1].collect{|i| i.id}
146
- @invoice.entries.length.should eql(2) # load once
146
+ expect(@invoice.entries.length).to eql(2) # load once
147
147
  @invoice.entry_ids << @entries[2].id
148
- @invoice.entry_ids.length.should eql(3)
149
- @invoice.entries.length.should eql(2) # cached!
150
- @invoice.entries(true).length.should eql(3)
148
+ expect(@invoice.entry_ids.length).to eql(3)
149
+ expect(@invoice.entries.length).to eql(2) # cached!
150
+ expect(@invoice.entries(true).length).to eql(3)
151
151
  end
152
152
 
153
153
  it "should empty arrays when nil collection provided" do
154
154
  @invoice.entries = @entries
155
155
  @invoice.entries = nil
156
- @invoice.entry_ids.should be_empty
157
- @invoice.entries.should be_empty
156
+ expect(@invoice.entry_ids).to be_empty
157
+ expect(@invoice.entries).to be_empty
158
158
  end
159
159
 
160
160
  it "should empty arrays when nil ids array provided" do
161
161
  @invoice.entries = @entries
162
162
  @invoice.entry_ids = nil
163
- @invoice.entry_ids.should be_empty
164
- @invoice.entries.should be_empty
163
+ expect(@invoice.entry_ids).to be_empty
164
+ expect(@invoice.entries).to be_empty
165
165
  end
166
166
 
167
167
  it "should ignore nil entries" do
168
168
  @invoice.entries = [ nil ]
169
- @invoice.entry_ids.should be_empty
170
- @invoice.entries.should be_empty
169
+ expect(@invoice.entry_ids).to be_empty
170
+ expect(@invoice.entries).to be_empty
171
171
  end
172
172
 
173
173
  # Account for dirty tracking
174
174
  describe "dirty tracking" do
175
175
  it "should register changes on replacement" do
176
176
  @invoice.entries = @entries
177
- @invoice.changed?.should be_true
177
+ expect(@invoice.changed?).to be_truthy
178
178
  end
179
179
  it "should register changes on push" do
180
- @invoice.changed?.should be_false
180
+ expect(@invoice.changed?).to be_falsey
181
181
  @invoice.entries << @entries[0]
182
- @invoice.changed?.should be_true
182
+ expect(@invoice.changed?).to be_truthy
183
183
  end
184
184
  it "should register changes on pop" do
185
185
  @invoice.entries << @entries[0]
186
186
  @invoice.save
187
- @invoice.changed?.should be_false
187
+ expect(@invoice.changed?).to be_falsey
188
188
  @invoice.entries.pop
189
- @invoice.changed?.should be_true
189
+ expect(@invoice.changed?).to be_truthy
190
190
  end
191
191
  it "should register id changes on push" do
192
192
  @invoice.entry_ids << @entries[0].id
193
- @invoice.changed?.should be_true
193
+ expect(@invoice.changed?).to be_truthy
194
194
  end
195
195
  it "should register id changes on pop" do
196
196
  @invoice.entry_ids << @entries[0].id
197
197
  @invoice.save
198
- @invoice.changed?.should be_false
198
+ expect(@invoice.changed?).to be_falsey
199
199
  @invoice.entry_ids.pop
200
- @invoice.changed?.should be_true
200
+ expect(@invoice.changed?).to be_truthy
201
201
  end
202
202
  end
203
203
 
@@ -205,53 +205,53 @@ describe "Assocations" do
205
205
 
206
206
  it "should ensure new entries to proxy are matched" do
207
207
  @invoice.entries << @entries.first
208
- @invoice.entry_ids.first.should eql(@entries.first.id)
209
- @invoice.entries.first.should eql(@entries.first)
208
+ expect(@invoice.entry_ids.first).to eql(@entries.first.id)
209
+ expect(@invoice.entries.first).to eql(@entries.first)
210
210
  @invoice.entries << @entries[1]
211
- @invoice.entries.count.should eql(2)
212
- @invoice.entry_ids.count.should eql(2)
213
- @invoice.entry_ids.last.should eql(@entries[1].id)
214
- @invoice.entries.last.should eql(@entries[1])
211
+ expect(@invoice.entries.count).to eql(2)
212
+ expect(@invoice.entry_ids.count).to eql(2)
213
+ expect(@invoice.entry_ids.last).to eql(@entries[1].id)
214
+ expect(@invoice.entries.last).to eql(@entries[1])
215
215
  end
216
216
 
217
217
  it "should support push method" do
218
218
  @invoice.entries.push(@entries.first)
219
- @invoice.entry_ids.first.should eql(@entries.first.id)
219
+ expect(@invoice.entry_ids.first).to eql(@entries.first.id)
220
220
  end
221
221
 
222
222
  it "should support []= method" do
223
223
  @invoice.entries[0] = @entries.first
224
- @invoice.entry_ids.first.should eql(@entries.first.id)
224
+ expect(@invoice.entry_ids.first).to eql(@entries.first.id)
225
225
  end
226
226
 
227
227
  it "should support unshift method" do
228
228
  @invoice.entries.unshift(@entries.first)
229
- @invoice.entry_ids.first.should eql(@entries.first.id)
229
+ expect(@invoice.entry_ids.first).to eql(@entries.first.id)
230
230
  @invoice.entries.unshift(@entries[1])
231
- @invoice.entry_ids.first.should eql(@entries[1].id)
231
+ expect(@invoice.entry_ids.first).to eql(@entries[1].id)
232
232
  end
233
233
 
234
234
  it "should support pop method" do
235
235
  @invoice.entries.push(@entries.first)
236
- @invoice.entries.pop.should eql(@entries.first)
237
- @invoice.entries.empty?.should be_true
238
- @invoice.entry_ids.empty?.should be_true
236
+ expect(@invoice.entries.pop).to eql(@entries.first)
237
+ expect(@invoice.entries.empty?).to be_truthy
238
+ expect(@invoice.entry_ids.empty?).to be_truthy
239
239
  end
240
240
 
241
241
  it "should support shift method" do
242
242
  @invoice.entries.push(@entries[0])
243
243
  @invoice.entries.push(@entries[1])
244
- @invoice.entries.shift.should eql(@entries[0])
245
- @invoice.entries.first.should eql(@entries[1])
246
- @invoice.entry_ids.first.should eql(@entries[1].id)
244
+ expect(@invoice.entries.shift).to eql(@entries[0])
245
+ expect(@invoice.entries.first).to eql(@entries[1])
246
+ expect(@invoice.entry_ids.first).to eql(@entries[1].id)
247
247
  end
248
248
 
249
249
  it "should raise error when adding un-persisted entries" do
250
- SaleEntry.find_by_description('test entry').should be_nil
250
+ expect(SaleEntry.find_by_description('test entry')).to be_nil
251
251
  entry = SaleEntry.new(:description => 'test entry', :price => 500)
252
- lambda {
252
+ expect {
253
253
  @invoice.entries << entry
254
- }.should raise_error
254
+ }.to raise_error(/Object cannot be added/)
255
255
  # In the future maybe?
256
256
  # @invoice.save.should be_true
257
257
  # SaleEntry.find_by_description('test entry').should_not be_nil
@@ -6,35 +6,35 @@ describe "Model attachments" do
6
6
  before(:each) do
7
7
  reset_test_db!
8
8
  @obj = Basic.new
9
- @obj.save.should be_true
9
+ expect(@obj.save).to be_truthy
10
10
  @file = File.open(FIXTURE_PATH + '/attachments/test.html')
11
11
  @attachment_name = 'my_attachment'
12
12
  @obj.create_attachment(:file => @file, :name => @attachment_name)
13
13
  end
14
14
 
15
15
  it 'should return false if there is no attachment' do
16
- @obj.has_attachment?('bogus').should be_false
16
+ expect(@obj.has_attachment?('bogus')).to be_falsey
17
17
  end
18
18
 
19
19
  it 'should return true if there is an attachment' do
20
- @obj.has_attachment?(@attachment_name).should be_true
20
+ expect(@obj.has_attachment?(@attachment_name)).to be_truthy
21
21
  end
22
22
 
23
23
  it 'should return true if an object with an attachment is reloaded' do
24
- @obj.save.should be_true
24
+ expect(@obj.save).to be_truthy
25
25
  reloaded_obj = Basic.get(@obj.id)
26
- reloaded_obj.has_attachment?(@attachment_name).should be_true
26
+ expect(reloaded_obj.has_attachment?(@attachment_name)).to be_truthy
27
27
  end
28
28
 
29
29
  it 'should return false if an attachment has been removed' do
30
30
  @obj.delete_attachment(@attachment_name)
31
- @obj.has_attachment?(@attachment_name).should be_false
31
+ expect(@obj.has_attachment?(@attachment_name)).to be_falsey
32
32
  end
33
33
 
34
34
  it 'should return false if an attachment has been removed and reloaded' do
35
35
  @obj.delete_attachment(@attachment_name)
36
36
  reloaded_obj = Basic.get(@obj.id)
37
- reloaded_obj.has_attachment?(@attachment_name).should be_false
37
+ expect(reloaded_obj.has_attachment?(@attachment_name)).to be_falsey
38
38
  end
39
39
 
40
40
  end
@@ -42,7 +42,7 @@ describe "Model attachments" do
42
42
  describe "creating an attachment" do
43
43
  before(:each) do
44
44
  @obj = Basic.new
45
- @obj.save.should be_true
45
+ expect(@obj.save).to be_truthy
46
46
  @file_ext = File.open(FIXTURE_PATH + '/attachments/test.html')
47
47
  @file_no_ext = File.open(FIXTURE_PATH + '/attachments/README')
48
48
  @attachment_name = 'my_attachment'
@@ -51,41 +51,41 @@ describe "Model attachments" do
51
51
 
52
52
  it "should create an attachment from file with an extension" do
53
53
  @obj.create_attachment(:file => @file_ext, :name => @attachment_name)
54
- @obj.save.should be_true
54
+ expect(@obj.save).to be_truthy
55
55
  reloaded_obj = Basic.get(@obj.id)
56
- reloaded_obj.attachments[@attachment_name].should_not be_nil
56
+ expect(reloaded_obj.attachments[@attachment_name]).not_to be_nil
57
57
  end
58
58
 
59
59
  it "should create an attachment from file without an extension" do
60
60
  @obj.create_attachment(:file => @file_no_ext, :name => @attachment_name)
61
- @obj.save.should be_true
61
+ expect(@obj.save).to be_truthy
62
62
  reloaded_obj = Basic.get(@obj.id)
63
- reloaded_obj.attachments[@attachment_name].should_not be_nil
63
+ expect(reloaded_obj.attachments[@attachment_name]).not_to be_nil
64
64
  end
65
65
 
66
66
  it 'should raise ArgumentError if :file is missing' do
67
- lambda{ @obj.create_attachment(:name => @attachment_name) }.should raise_error
67
+ expect{ @obj.create_attachment(:name => @attachment_name) }.to raise_error(ArgumentError, /:file/)
68
68
  end
69
69
 
70
70
  it 'should raise ArgumentError if :name is missing' do
71
- lambda{ @obj.create_attachment(:file => @file_ext) }.should raise_error
71
+ expect{ @obj.create_attachment(:file => @file_ext) }.to raise_error(ArgumentError, /:name/)
72
72
  end
73
73
 
74
74
  it 'should set the content-type if passed' do
75
75
  @obj.create_attachment(:file => @file_ext, :name => @attachment_name, :content_type => @content_type)
76
- @obj.attachments[@attachment_name]['content_type'].should == @content_type
76
+ expect(@obj.attachments[@attachment_name]['content_type']).to eq(@content_type)
77
77
  end
78
78
 
79
79
  it "should detect the content-type automatically" do
80
80
  @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
81
- @obj.attachments['couchdb.png']['content_type'].should == "image/png"
81
+ expect(@obj.attachments['couchdb.png']['content_type']).to eq("image/png")
82
82
  end
83
83
 
84
84
  it "should use name to detect the content-type automatically if no file" do
85
85
  file = File.open(FIXTURE_PATH + '/attachments/couchdb.png')
86
- file.stub(:path).and_return("badfilname")
86
+ allow(file).to receive(:path).and_return("badfilname")
87
87
  @obj.create_attachment(:file => File.open(FIXTURE_PATH + '/attachments/couchdb.png'), :name => "couchdb.png")
88
- @obj.attachments['couchdb.png']['content_type'].should == "image/png"
88
+ expect(@obj.attachments['couchdb.png']['content_type']).to eq("image/png")
89
89
  end
90
90
 
91
91
  end
@@ -96,37 +96,37 @@ describe "Model attachments" do
96
96
  @file = File.open(FIXTURE_PATH + '/attachments/test.html')
97
97
  @attachment_name = 'my_attachment'
98
98
  @obj.create_attachment(:file => @file, :name => @attachment_name)
99
- @obj.save.should be_true
99
+ expect(@obj.save).to be_truthy
100
100
  @file.rewind
101
101
  @content_type = 'media/mp3'
102
102
  end
103
103
 
104
104
  it 'should read an attachment that exists' do
105
- @obj.read_attachment(@attachment_name).should == @file.read
105
+ expect(@obj.read_attachment(@attachment_name)).to eq(@file.read)
106
106
  end
107
107
 
108
108
  it 'should update an attachment that exists' do
109
109
  file = File.open(FIXTURE_PATH + '/attachments/README')
110
- @file.should_not == file
110
+ expect(@file).not_to eq(file)
111
111
  @obj.update_attachment(:file => file, :name => @attachment_name)
112
112
  @obj.save
113
113
  reloaded_obj = Basic.get(@obj.id)
114
114
  file.rewind
115
- reloaded_obj.read_attachment(@attachment_name).should_not == @file.read
116
- reloaded_obj.read_attachment(@attachment_name).should == file.read
115
+ expect(reloaded_obj.read_attachment(@attachment_name)).not_to eq(@file.read)
116
+ expect(reloaded_obj.read_attachment(@attachment_name)).to eq(file.read)
117
117
  end
118
118
 
119
119
  it 'should set the content-type if passed' do
120
120
  file = File.open(FIXTURE_PATH + '/attachments/README')
121
- @file.should_not == file
121
+ expect(@file).not_to eq(file)
122
122
  @obj.update_attachment(:file => file, :name => @attachment_name, :content_type => @content_type)
123
- @obj.attachments[@attachment_name]['content_type'].should == @content_type
123
+ expect(@obj.attachments[@attachment_name]['content_type']).to eq(@content_type)
124
124
  end
125
125
 
126
126
  it 'should delete an attachment that exists' do
127
127
  @obj.delete_attachment(@attachment_name)
128
128
  @obj.save
129
- lambda{Basic.get(@obj.id).read_attachment(@attachment_name)}.should raise_error
129
+ expect{Basic.get(@obj.id).read_attachment(@attachment_name)}.to raise_error(/404 Not Found/)
130
130
  end
131
131
  end
132
132
 
@@ -136,19 +136,19 @@ describe "Model attachments" do
136
136
  @file = File.open(FIXTURE_PATH + '/attachments/test.html')
137
137
  @attachment_name = 'my_attachment'
138
138
  @obj.create_attachment(:file => @file, :name => @attachment_name)
139
- @obj.save.should be_true
139
+ expect(@obj.save).to be_truthy
140
140
  end
141
141
 
142
142
  it 'should return nil if attachment does not exist' do
143
- @obj.attachment_url('bogus').should be_nil
143
+ expect(@obj.attachment_url('bogus')).to be_nil
144
144
  end
145
145
 
146
146
  it 'should return the attachment URL as specified by CouchDB HttpDocumentApi' do
147
- @obj.attachment_url(@attachment_name).should == "#{Basic.database}/#{@obj.id}/#{@attachment_name}"
147
+ expect(@obj.attachment_url(@attachment_name)).to eq("#{Basic.database}/#{@obj.id}/#{@attachment_name}")
148
148
  end
149
149
 
150
150
  it 'should return the attachment URI' do
151
- @obj.attachment_uri(@attachment_name).should == "#{Basic.database.uri}/#{@obj.id}/#{@attachment_name}"
151
+ expect(@obj.attachment_uri(@attachment_name)).to eq("#{Basic.database.uri}/#{@obj.id}/#{@attachment_name}")
152
152
  end
153
153
  end
154
154
 
@@ -158,18 +158,18 @@ describe "Model attachments" do
158
158
  @file = File.open(FIXTURE_PATH + '/attachments/test.html')
159
159
  @attachment_name = 'my_attachment'
160
160
  @obj.create_attachment(:file => @file, :name => @attachment_name)
161
- @obj.save.should be_true
161
+ expect(@obj.save).to be_truthy
162
162
  end
163
163
 
164
164
  it 'should return an empty Hash when document does not have any attachment' do
165
165
  new_obj = Basic.new
166
- new_obj.save.should be_true
167
- new_obj.attachments.should == {}
166
+ expect(new_obj.save).to be_truthy
167
+ expect(new_obj.attachments).to eq({})
168
168
  end
169
169
 
170
170
  it 'should return a Hash with all attachments' do
171
171
  @file.rewind
172
- @obj.attachments.should == { @attachment_name =>{ "data" => "PCFET0NUWVBFIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPHRpdGxlPlRlc3Q8L3RpdGxlPgogIDwvaGVhZD4KICA8Ym9keT4KICAgIDxwPgogICAgICBUZXN0CiAgICA8L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==", "content_type" => "text/html"}}
172
+ expect(@obj.attachments).to eq({ @attachment_name =>{ "data" => "PCFET0NUWVBFIGh0bWw+CjxodG1sPgogIDxoZWFkPgogICAgPHRpdGxlPlRlc3Q8L3RpdGxlPgogIDwvaGVhZD4KICA8Ym9keT4KICAgIDxwPgogICAgICBUZXN0CiAgICA8L3A+CiAgPC9ib2R5Pgo8L2h0bWw+Cg==", "content_type" => "text/html"}})
173
173
  end
174
174
 
175
175
  end