carrierwave-neo4j 2.0.0 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +5 -5
- data/.gitignore +3 -0
- data/CHANGELOG.md +35 -0
- data/Gemfile +0 -2
- data/README.md +64 -4
- data/Rakefile +11 -0
- data/carrierwave-neo4j.gemspec +9 -7
- data/lib/carrierwave/neo4j.rb +177 -41
- data/lib/carrierwave/neo4j/uploader_converter.rb +16 -6
- data/lib/carrierwave/neo4j/version.rb +1 -1
- data/spec/fixtures/neo4j.png +0 -0
- data/spec/fixtures/ong.jpg +0 -0
- data/spec/helpers/database_cleaner.rb +29 -0
- data/spec/helpers/fake_book_migration.rb +13 -0
- data/spec/helpers/fake_migrations.rb +12 -0
- data/spec/helpers/fake_schema_migration.rb +13 -0
- data/spec/helpers/fake_user_migration.rb +13 -0
- data/spec/helpers/filesystem_cleaner.rb +12 -0
- data/spec/neo4j_realistic_spec.rb +104 -0
- data/spec/neo4j_sanity_spec.rb +137 -0
- data/spec/neo4j_spec.rb +148 -29
- data/spec/spec_helper.rb +23 -5
- metadata +91 -26
- data/spec/fixtures/tarja.jpg +0 -0
Binary file
|
Binary file
|
@@ -0,0 +1,29 @@
|
|
1
|
+
|
2
|
+
require "neo4j"
|
3
|
+
|
4
|
+
class DatabaseCleaner
|
5
|
+
include Neo4j::Migrations::Helpers
|
6
|
+
|
7
|
+
def self.clean
|
8
|
+
DatabaseCleaner.new.clean_db
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.avoid_validation
|
12
|
+
# migrations and db cleanup have to happen outside of validations
|
13
|
+
# or they never succeed
|
14
|
+
Neo4j::Migrations.currently_running_migrations = true
|
15
|
+
yield
|
16
|
+
Neo4j::Migrations.currently_running_migrations = false
|
17
|
+
end
|
18
|
+
|
19
|
+
def clean_db
|
20
|
+
execute("match (n) detach delete n;")
|
21
|
+
execute("call db.constraints").each do |constraint|
|
22
|
+
execute "drop #{constraint[:description]}"
|
23
|
+
end
|
24
|
+
execute("call db.indexes").each do |index|
|
25
|
+
execute "drop #{index[:description]}"
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
require 'helpers/fake_schema_migration'
|
3
|
+
require 'helpers/fake_user_migration'
|
4
|
+
require 'helpers/fake_book_migration'
|
5
|
+
|
6
|
+
class FakeMigrations
|
7
|
+
def self.migrate(direction)
|
8
|
+
FakeSchemaMigration.create.migrate(direction)
|
9
|
+
FakeUserMigration.create.migrate(direction)
|
10
|
+
FakeBookMigration.create.migrate(direction)
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
|
2
|
+
require "neo4j"
|
3
|
+
|
4
|
+
class FakeSchemaMigration < Neo4j::Migrations::Base
|
5
|
+
|
6
|
+
def self.create
|
7
|
+
FakeSchemaMigration.new(:fake_schema_migration)
|
8
|
+
end
|
9
|
+
|
10
|
+
def up
|
11
|
+
add_constraint :"Neo4j::Migrations::SchemaMigration", :migration_id, force: true
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,104 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
# RealisticUploader and Book exist to provide a basic test harness with
|
4
|
+
# standard Ruby code and no metaprogramming of any sort. Because that
|
5
|
+
# stuff is really hard to trust, even when you're sure you got it right.
|
6
|
+
|
7
|
+
class RealisticUploader < CarrierWave::Uploader::Base
|
8
|
+
include CarrierWave::MiniMagick
|
9
|
+
|
10
|
+
storage :file
|
11
|
+
|
12
|
+
def store_dir
|
13
|
+
"uploads/#{model.class.to_s.underscore}/#{mounted_as}/#{model.id}"
|
14
|
+
end
|
15
|
+
|
16
|
+
def extension_whitelist
|
17
|
+
%w(jpg jpeg gif png)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
class Book
|
22
|
+
include Neo4j::ActiveNode
|
23
|
+
property :cover, type: String
|
24
|
+
mount_uploader :cover, RealisticUploader
|
25
|
+
end
|
26
|
+
|
27
|
+
describe CarrierWave::Neo4j do
|
28
|
+
after do
|
29
|
+
Book.destroy_all
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "#uploader" do
|
33
|
+
let(:book) { Book.new }
|
34
|
+
subject { book.cover }
|
35
|
+
|
36
|
+
context "when nothing is assigned" do
|
37
|
+
it { should be_blank }
|
38
|
+
end
|
39
|
+
|
40
|
+
context "when a file is stored to a store_dir" do
|
41
|
+
before do
|
42
|
+
book.cover = File.open(file_path("ong.jpg"))
|
43
|
+
book.save
|
44
|
+
book.reload
|
45
|
+
end
|
46
|
+
|
47
|
+
it { should be_an_instance_of RealisticUploader }
|
48
|
+
its(:current_path) { should == public_path("uploads/book/cover/#{book.id}/ong.jpg") }
|
49
|
+
end
|
50
|
+
|
51
|
+
context "when a db lookup uses `#find`" do
|
52
|
+
before do
|
53
|
+
book.cover = File.open(file_path("ong.jpg"))
|
54
|
+
book.save
|
55
|
+
@found = Book.find(book.id)
|
56
|
+
end
|
57
|
+
|
58
|
+
it "has a basic identifier" do
|
59
|
+
expect(@found.cover_identifier).to eq "ong.jpg"
|
60
|
+
end
|
61
|
+
|
62
|
+
subject { @found.cover }
|
63
|
+
|
64
|
+
it { should be_an_instance_of RealisticUploader }
|
65
|
+
its(:url) { should == "/uploads/book/cover/#{book.id}/ong.jpg"}
|
66
|
+
its(:current_path) { should == public_path("uploads/book/cover/#{book.id}/ong.jpg") }
|
67
|
+
end
|
68
|
+
|
69
|
+
context "when a db look up does not use `#find`" do
|
70
|
+
before do
|
71
|
+
book.cover = File.open(file_path("ong.jpg"))
|
72
|
+
book.save
|
73
|
+
@found = Book.find_by_id(book.id)
|
74
|
+
end
|
75
|
+
|
76
|
+
it "has a basic identifier" do
|
77
|
+
expect(@found.cover_identifier).to eq "ong.jpg"
|
78
|
+
end
|
79
|
+
|
80
|
+
subject { @found.cover }
|
81
|
+
|
82
|
+
# There is no way around this. `#url` and `#current_path` depend on the
|
83
|
+
# retrieval of the file from the store but there the only callback
|
84
|
+
# available is `:after_find` which does not fire on `#find_by` queries.
|
85
|
+
it { should be_an_instance_of RealisticUploader }
|
86
|
+
its(:url) { should be_nil }
|
87
|
+
its(:current_path) { should be_nil }
|
88
|
+
|
89
|
+
it "is retrieved with `#reload_from_database!`" do
|
90
|
+
@found.reload_from_database!
|
91
|
+
expect(@found.cover.url).to eq("/uploads/book/cover/#{@found.id}/ong.jpg")
|
92
|
+
expect(@found.cover.current_path).to eq(public_path("uploads/book/cover/#{@found.id}/ong.jpg"))
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
context "with CarrierWave::MiniMagick" do
|
97
|
+
it "has width and height" do
|
98
|
+
book.cover = File.open(file_path("ong.jpg"))
|
99
|
+
expect(book.cover.width).to eq 273
|
100
|
+
expect(book.cover.height).to eq 273
|
101
|
+
end
|
102
|
+
end
|
103
|
+
end
|
104
|
+
end
|
@@ -0,0 +1,137 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
# This spec mirrors the specs found in the CarrierWave::Orm::ActiveRecord spec:
|
4
|
+
# https://github.com/carrierwaveuploader/carrierwave/blob/master/spec/orm/activerecord_spec.rb
|
5
|
+
#
|
6
|
+
# Use it to sanity-check behaviour since ActiveGraph and ActiveRecord are
|
7
|
+
# NOT symmetrical.
|
8
|
+
|
9
|
+
class DefaultUploader < CarrierWave::Uploader::Base ; end
|
10
|
+
|
11
|
+
def reset_class
|
12
|
+
Object.send(:remove_const, "User") rescue nil
|
13
|
+
Object.const_set("User", Class.new())
|
14
|
+
User.class_eval do
|
15
|
+
include Neo4j::ActiveNode
|
16
|
+
property :image, type: String
|
17
|
+
mount_uploader :image, DefaultUploader
|
18
|
+
end
|
19
|
+
User
|
20
|
+
end
|
21
|
+
|
22
|
+
describe CarrierWave::Neo4j do
|
23
|
+
before do
|
24
|
+
reset_class
|
25
|
+
@user = User.new
|
26
|
+
end
|
27
|
+
|
28
|
+
after do
|
29
|
+
User.destroy_all
|
30
|
+
end
|
31
|
+
|
32
|
+
describe "sanity checks" do
|
33
|
+
|
34
|
+
describe "#mount_uploader" do
|
35
|
+
before do
|
36
|
+
User.mount_uploader(:image, DefaultUploader)
|
37
|
+
@user = User.new
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns valid JSON when to_json is called when image is nil" do
|
41
|
+
expect(@user[:image]).to be_blank
|
42
|
+
hash = JSON.parse(@user.to_json)
|
43
|
+
expect(hash.keys).to include("user")
|
44
|
+
# ActiveRecord returns the user hash directly but Neo4j's `.to_json`
|
45
|
+
# requires that we select the user hash explicitly
|
46
|
+
user_hash = hash["user"]
|
47
|
+
expect(user_hash.keys).to include("image")
|
48
|
+
expect(user_hash["image"].keys).to include("url")
|
49
|
+
expect(user_hash["image"]["url"]).to be_nil
|
50
|
+
end
|
51
|
+
|
52
|
+
it "returns valid JSON when to_json is called when image is present" do
|
53
|
+
@user.image = File.open(file_path("ong.jpg"))
|
54
|
+
@user.save!
|
55
|
+
@user.reload
|
56
|
+
# again, ActiveRecord does not require the sub-select with `["user"]`
|
57
|
+
expect(JSON.parse(@user.to_json)["user"]["image"]).to eq({"url" => "/uploads/ong.jpg"})
|
58
|
+
end
|
59
|
+
|
60
|
+
it "does not return anything when a stub image is assigned" do
|
61
|
+
# ActiveRecord does permit square bracket assignment to a column
|
62
|
+
# Neo4j does not
|
63
|
+
@user[:image] = 'ong.jpg'
|
64
|
+
@user.save!
|
65
|
+
@user.reload
|
66
|
+
expect(@user.image).to be_blank
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
describe "#image" do
|
71
|
+
end
|
72
|
+
|
73
|
+
describe "#save" do
|
74
|
+
it "should do nothing when no file has been assigned" do
|
75
|
+
expect(@user.save).to be_truthy
|
76
|
+
expect(@user.image).to be_blank
|
77
|
+
end
|
78
|
+
|
79
|
+
it "should assign the filename to the database" do
|
80
|
+
@user.image = File.open(file_path("ong.jpg"))
|
81
|
+
expect(@user.save).to be_truthy
|
82
|
+
@user.reload
|
83
|
+
# under ActiveRecord these would be equal
|
84
|
+
expect(@user[:image]).not_to eq('ong.jpg')
|
85
|
+
expect(@user[:image].identifier).to eq('ong.jpg')
|
86
|
+
expect(@user.image_identifier).to eq('ong.jpg')
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
90
|
+
describe "#update" do
|
91
|
+
it "resets cached value on record reload" do
|
92
|
+
@user.image = File.open(file_path("ong.jpg"))
|
93
|
+
@user.save!
|
94
|
+
|
95
|
+
expect(@user.reload.image).to be_present
|
96
|
+
|
97
|
+
other = User.find(@user.id)
|
98
|
+
other.image = nil
|
99
|
+
other.save!
|
100
|
+
|
101
|
+
expect(@user.reload.image).to be_blank
|
102
|
+
end
|
103
|
+
|
104
|
+
it "does not respect `update_column`" do
|
105
|
+
@user.image = File.open(file_path("ong.jpg"))
|
106
|
+
@user.save!
|
107
|
+
|
108
|
+
# ActiveRecord would respect `update_column`
|
109
|
+
User.find(@user.id).update_column(:image, nil)
|
110
|
+
|
111
|
+
expect(@user.reload.image).to be_present
|
112
|
+
other = User.find(@user.id)
|
113
|
+
expect(other.image).to be_present
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
describe "#destroy" do
|
118
|
+
end
|
119
|
+
|
120
|
+
describe "#remote_image_url=" do
|
121
|
+
before do
|
122
|
+
stub_request(:get, "www.example.com/test.jpg").to_return(body: File.read(file_path("ong.jpg")))
|
123
|
+
end
|
124
|
+
|
125
|
+
it "marks image as changed when setting remote_image_url" do
|
126
|
+
expect(@user.image_changed?).to be_falsey
|
127
|
+
@user.remote_image_url = 'http://www.example.com/test.jpg'
|
128
|
+
expect(@user.image_changed?).to be_truthy
|
129
|
+
expect(File.exist?(public_path('uploads/test.jpg'))).to be_falsey
|
130
|
+
@user.save!
|
131
|
+
@user.reload
|
132
|
+
expect(File.exist?(public_path('uploads/test.jpg'))).to be_truthy
|
133
|
+
expect(@user.image_changed?).to be_falsey
|
134
|
+
end
|
135
|
+
end
|
136
|
+
end
|
137
|
+
end
|
data/spec/neo4j_spec.rb
CHANGED
@@ -12,10 +12,10 @@ class User
|
|
12
12
|
property :image, type: String
|
13
13
|
end
|
14
14
|
|
15
|
-
class DefaultUploader < CarrierWave::Uploader::Base; end
|
15
|
+
class DefaultUploader < CarrierWave::Uploader::Base ; end
|
16
16
|
|
17
17
|
class PngUploader < CarrierWave::Uploader::Base
|
18
|
-
def
|
18
|
+
def extension_whitelist
|
19
19
|
%w(png)
|
20
20
|
end
|
21
21
|
end
|
@@ -24,14 +24,21 @@ class ProcessingErrorUploader < CarrierWave::Uploader::Base
|
|
24
24
|
process :end_on_an_era
|
25
25
|
|
26
26
|
def end_on_an_era
|
27
|
-
raise CarrierWave::ProcessingError, "Bye
|
27
|
+
raise CarrierWave::ProcessingError, "Bye OngDB"
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class DownloadErrorUploader < CarrierWave::Uploader::Base
|
32
|
+
def download!(file, headers = {})
|
33
|
+
raise CarrierWave::DownloadError
|
28
34
|
end
|
29
35
|
end
|
30
36
|
|
31
37
|
describe CarrierWave::Neo4j do
|
32
|
-
let(:user_class)
|
33
|
-
let(:user_class_png)
|
34
|
-
let(:user_class_error)
|
38
|
+
let(:user_class) { reset_class }
|
39
|
+
let(:user_class_png) { reset_class(PngUploader) }
|
40
|
+
let(:user_class_error) { reset_class(ProcessingErrorUploader) }
|
41
|
+
let(:user_download_error) { reset_class(DownloadErrorUploader) }
|
35
42
|
let(:user) { user_class.new }
|
36
43
|
|
37
44
|
after do
|
@@ -39,8 +46,8 @@ describe CarrierWave::Neo4j do
|
|
39
46
|
end
|
40
47
|
|
41
48
|
describe "#image" do
|
42
|
-
let(:
|
43
|
-
subject {
|
49
|
+
let(:user) { user_class.new }
|
50
|
+
subject { user.image }
|
44
51
|
|
45
52
|
context "when nothing is assigned" do
|
46
53
|
it { should be_blank }
|
@@ -48,9 +55,9 @@ describe CarrierWave::Neo4j do
|
|
48
55
|
|
49
56
|
context "when an empty string is assigned" do
|
50
57
|
before do
|
51
|
-
|
52
|
-
|
53
|
-
|
58
|
+
user.image = ""
|
59
|
+
user.save
|
60
|
+
user.reload
|
54
61
|
end
|
55
62
|
|
56
63
|
it { should be_blank }
|
@@ -58,30 +65,61 @@ describe CarrierWave::Neo4j do
|
|
58
65
|
|
59
66
|
context "when a filename is stored" do
|
60
67
|
before do
|
61
|
-
|
62
|
-
|
63
|
-
|
68
|
+
user.image = File.open(file_path("ong.jpg"))
|
69
|
+
user.save
|
70
|
+
user.reload
|
64
71
|
end
|
65
72
|
|
66
73
|
it { should be_an_instance_of DefaultUploader }
|
67
|
-
its(:current_path) { should == public_path("uploads/
|
74
|
+
its(:current_path) { should == public_path("uploads/ong.jpg") }
|
75
|
+
end
|
76
|
+
|
77
|
+
context "when a model is retrieved from the db" do
|
78
|
+
before do
|
79
|
+
user.image = File.open(file_path("ong.jpg"))
|
80
|
+
user.save
|
81
|
+
@found = user_class.find(user.uuid)
|
82
|
+
end
|
83
|
+
|
84
|
+
subject { @found.image }
|
85
|
+
|
86
|
+
it "has a basic identifier" do
|
87
|
+
expect(@found.image_identifier).to eq "ong.jpg"
|
88
|
+
end
|
89
|
+
|
90
|
+
it { should be_an_instance_of DefaultUploader }
|
91
|
+
its(:url) { should == "/uploads/ong.jpg"}
|
92
|
+
its(:current_path) { should == public_path("uploads/ong.jpg") }
|
68
93
|
end
|
69
94
|
end
|
70
95
|
|
71
96
|
describe "#save" do
|
97
|
+
context "when image= is assigned and the user is saved" do
|
98
|
+
let(:user) { user_class.new }
|
99
|
+
|
100
|
+
before do
|
101
|
+
user.image = File.open(file_path("ong.jpg"))
|
102
|
+
user.save
|
103
|
+
end
|
104
|
+
|
105
|
+
it "writes the file to disk" do
|
106
|
+
expect(File.exist?(public_path('uploads/ong.jpg'))).to be_truthy
|
107
|
+
end
|
108
|
+
end
|
109
|
+
|
72
110
|
context "when remove_image? is true" do
|
73
|
-
let(:
|
111
|
+
let(:user) { user_class.new }
|
74
112
|
|
75
113
|
before do
|
76
|
-
|
77
|
-
|
114
|
+
user.image = File.open(file_path("ong.jpg"))
|
115
|
+
user.save
|
78
116
|
|
79
|
-
|
80
|
-
|
81
|
-
|
117
|
+
user.remove_image = true
|
118
|
+
user.save
|
119
|
+
user.reload
|
82
120
|
end
|
83
121
|
|
84
|
-
subject {
|
122
|
+
subject { user }
|
85
123
|
|
86
124
|
its(:image) { should be_blank }
|
87
125
|
end
|
@@ -89,7 +127,7 @@ describe CarrierWave::Neo4j do
|
|
89
127
|
context "when validating integrity" do
|
90
128
|
subject do
|
91
129
|
user = user_class_png.new
|
92
|
-
user.image = File.open(file_path("
|
130
|
+
user.image = File.open(file_path("ong.jpg"))
|
93
131
|
user
|
94
132
|
end
|
95
133
|
|
@@ -99,7 +137,17 @@ describe CarrierWave::Neo4j do
|
|
99
137
|
context "when validating processing" do
|
100
138
|
subject do
|
101
139
|
user = user_class_error.new
|
102
|
-
user.image = File.open(file_path("
|
140
|
+
user.image = File.open(file_path("ong.jpg"))
|
141
|
+
user
|
142
|
+
end
|
143
|
+
|
144
|
+
it { should_not be_valid }
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'when validating download' do
|
148
|
+
subject do
|
149
|
+
user = user_download_error.new
|
150
|
+
user.remote_image_url = 'http://www.example.com/missing.jpg'
|
103
151
|
user
|
104
152
|
end
|
105
153
|
|
@@ -107,18 +155,89 @@ describe CarrierWave::Neo4j do
|
|
107
155
|
end
|
108
156
|
end
|
109
157
|
|
158
|
+
describe "#update" do
|
159
|
+
let(:user) { user_class.new }
|
160
|
+
|
161
|
+
before do
|
162
|
+
user.image = File.open(file_path("ong.jpg"))
|
163
|
+
user.save
|
164
|
+
end
|
165
|
+
|
166
|
+
it "does not flag the uploader for removal" do
|
167
|
+
user.image = File.open(file_path("neo4j.png"))
|
168
|
+
user.save
|
169
|
+
expect(user.remove_image?).to be_falsey
|
170
|
+
end
|
171
|
+
|
172
|
+
it "stores the updated file" do
|
173
|
+
user.image = File.open(file_path("neo4j.png"))
|
174
|
+
user.save
|
175
|
+
expect(user.image.current_path).to eq public_path('uploads/neo4j.png')
|
176
|
+
expect(user.image.url).to eq '/uploads/neo4j.png'
|
177
|
+
end
|
178
|
+
|
179
|
+
it "writes the updated file to disk" do
|
180
|
+
user.image = File.open(file_path("neo4j.png"))
|
181
|
+
user.save
|
182
|
+
expect(File.exist?(public_path('uploads/neo4j.png'))).to be_truthy
|
183
|
+
end
|
184
|
+
end
|
185
|
+
|
110
186
|
describe "#destroy" do
|
111
|
-
let(:
|
187
|
+
let(:user) { user_class.new }
|
112
188
|
|
113
189
|
before do
|
114
|
-
|
115
|
-
|
190
|
+
user.image = File.open(file_path("ong.jpg"))
|
191
|
+
user.save
|
116
192
|
end
|
117
193
|
|
118
194
|
it "also destroys the image" do
|
119
|
-
|
120
|
-
|
195
|
+
file_path = user.image.path
|
196
|
+
expect(user.image.current_path).to eq public_path('uploads/ong.jpg')
|
197
|
+
expect { user.destroy }.to change {
|
198
|
+
File.exist? file_path
|
121
199
|
}.from(true).to(false)
|
122
200
|
end
|
123
201
|
end
|
202
|
+
|
203
|
+
describe "#reload_from_database" do
|
204
|
+
context "when used without mutation" do
|
205
|
+
before do
|
206
|
+
user.image = File.open(file_path("ong.jpg"))
|
207
|
+
user.save
|
208
|
+
@reloaded = user.reload_from_database
|
209
|
+
end
|
210
|
+
|
211
|
+
subject { @reloaded.image }
|
212
|
+
|
213
|
+
it "has an id and image identifier" do
|
214
|
+
expect(@reloaded.id).to eq user.id
|
215
|
+
expect(@reloaded.image_identifier).to eq "ong.jpg"
|
216
|
+
end
|
217
|
+
|
218
|
+
it { should be_an_instance_of DefaultUploader }
|
219
|
+
its(:url) { should == "/uploads/ong.jpg"}
|
220
|
+
its(:current_path) { should == public_path("uploads/ong.jpg") }
|
221
|
+
end
|
222
|
+
end
|
223
|
+
|
224
|
+
describe "#reload_from_database!" do
|
225
|
+
context "when used with mutation" do
|
226
|
+
before do
|
227
|
+
user.image = File.open(file_path("ong.jpg"))
|
228
|
+
user.save
|
229
|
+
user.reload_from_database!
|
230
|
+
end
|
231
|
+
|
232
|
+
subject { user.image }
|
233
|
+
|
234
|
+
it "has an image identifier" do
|
235
|
+
expect(user.image_identifier).to eq "ong.jpg"
|
236
|
+
end
|
237
|
+
|
238
|
+
it { should be_an_instance_of DefaultUploader }
|
239
|
+
its(:url) { should == "/uploads/ong.jpg"}
|
240
|
+
its(:current_path) { should == public_path("uploads/ong.jpg") }
|
241
|
+
end
|
242
|
+
end
|
124
243
|
end
|