couchrest_model 2.1.0.rc1 → 2.2.0.beta1

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 (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