saviour 0.2.3 → 0.3.0
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.
- checksums.yaml +4 -4
- data/.gitignore +2 -1
- data/.travis.yml +4 -13
- data/DECOMPOSE.md +66 -0
- data/Gemfile +1 -0
- data/README.md +39 -8
- data/lib/saviour/attribute_name_calculator.rb +15 -0
- data/lib/saviour/base_integrator.rb +53 -0
- data/lib/saviour/basic_model.rb +7 -0
- data/lib/saviour/config.rb +0 -1
- data/lib/saviour/file.rb +13 -34
- data/lib/saviour/life_cycle.rb +57 -0
- data/lib/saviour/source_filename_extractor.rb +21 -0
- data/lib/saviour/url_source.rb +1 -1
- data/lib/saviour/utils/class_attribute.rb +26 -0
- data/lib/saviour/version.rb +1 -1
- data/lib/saviour.rb +7 -155
- data/saviour.gemspec +1 -5
- data/spec/feature/access_to_model_and_mounted_as_spec.rb +13 -5
- data/spec/feature/versions_spec.rb +72 -49
- data/spec/models/attribute_name_calculator_spec.rb +11 -0
- data/spec/models/basic_model_spec.rb +51 -0
- data/spec/models/file_spec.rb +32 -55
- data/spec/models/url_source_spec.rb +5 -5
- data/spec/spec_helper.rb +2 -30
- data/spec/support/models.rb +7 -2
- metadata +12 -72
- data/Appraisals +0 -19
- data/gemfiles/4.0.gemfile +0 -9
- data/gemfiles/4.1.gemfile +0 -9
- data/gemfiles/4.2.gemfile +0 -9
- data/gemfiles/5.0.gemfile +0 -9
- data/lib/saviour/processors/digest.rb +0 -16
- data/spec/feature/crud_workflows_spec.rb +0 -143
- data/spec/feature/persisted_path_spec.rb +0 -34
- data/spec/feature/reload_model_spec.rb +0 -24
- data/spec/feature/validations_spec.rb +0 -171
- data/spec/models/processors/digest_spec.rb +0 -22
- data/spec/models/saviour_spec.rb +0 -80
- data/spec/support/schema.rb +0 -9
data/lib/saviour.rb
CHANGED
@@ -1,11 +1,7 @@
|
|
1
1
|
require 'fileutils'
|
2
|
-
require 'digest/md5'
|
3
|
-
require 'active_support/concern'
|
4
|
-
require 'active_support/core_ext'
|
5
|
-
require 'active_support/core_ext/module/attribute_accessors'
|
6
2
|
require 'fog/aws'
|
7
3
|
|
8
|
-
require 'saviour/
|
4
|
+
require 'saviour/utils/class_attribute'
|
9
5
|
|
10
6
|
require 'saviour/version'
|
11
7
|
require 'saviour/base_uploader'
|
@@ -15,156 +11,12 @@ require 'saviour/s3_storage'
|
|
15
11
|
require 'saviour/config'
|
16
12
|
require 'saviour/string_source'
|
17
13
|
require 'saviour/url_source'
|
14
|
+
require 'saviour/basic_model'
|
15
|
+
require 'saviour/base_integrator'
|
16
|
+
require 'saviour/attribute_name_calculator'
|
17
|
+
require 'saviour/source_filename_extractor'
|
18
|
+
require 'saviour/life_cycle'
|
18
19
|
|
19
|
-
module Saviour
|
20
|
-
class ColumnNamer
|
21
|
-
def initialize(attached_as, version = nil)
|
22
|
-
@attached_as, @version = attached_as, version
|
23
|
-
end
|
24
|
-
|
25
|
-
def name
|
26
|
-
if @version
|
27
|
-
"#{@attached_as}_#{@version}"
|
28
|
-
else
|
29
|
-
@attached_as.to_s
|
30
|
-
end
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
class ModelHooks
|
35
|
-
def initialize(model)
|
36
|
-
@model = model
|
37
|
-
end
|
38
|
-
|
39
|
-
def delete!
|
40
|
-
attached_files.each do |column, versions|
|
41
|
-
(versions + [nil]).each { |version| @model.send(column, version).delete if @model.send(column, version).exists? }
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def save!
|
46
|
-
attached_files.each do |column, versions|
|
47
|
-
base_file_changed = @model.send(column).changed?
|
48
|
-
original_content = @model.send(column).source_data if base_file_changed
|
49
|
-
|
50
|
-
versions.each do |version|
|
51
|
-
if @model.send(column, version).changed?
|
52
|
-
upload_file(column, version)
|
53
|
-
elsif base_file_changed
|
54
|
-
@model.send(column, version).assign(StringSource.new(original_content, default_version_filename(column, version)))
|
55
|
-
upload_file(column, version)
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
upload_file(column, nil) if base_file_changed
|
60
|
-
end
|
61
|
-
end
|
62
|
-
|
63
|
-
def validate!
|
64
|
-
validations.each do |column, method_or_blocks|
|
65
|
-
(attached_files[column] + [nil]).each do |version|
|
66
|
-
if @model.send(column, version).changed?
|
67
|
-
method_or_blocks.each { |method_or_block| run_validation(column, version, method_or_block) }
|
68
|
-
end
|
69
|
-
end
|
70
|
-
end
|
71
|
-
end
|
72
|
-
|
73
|
-
def default_version_filename(column, version)
|
74
|
-
filename = @model.send(column).filename_to_be_assigned
|
75
|
-
"#{::File.basename(filename, ".*")}_#{version}#{::File.extname(filename)}"
|
76
|
-
end
|
77
|
-
|
78
|
-
def upload_file(column, version)
|
79
|
-
name = ColumnNamer.new(column, version).name
|
80
|
-
Config.storage.delete(@model.read_attribute(name)) if @model.read_attribute(name)
|
81
|
-
new_path = @model.send(column, version).write
|
82
|
-
@model.update_column(name, new_path)
|
83
|
-
end
|
84
|
-
|
85
|
-
def attached_files
|
86
|
-
@model.class.attached_files || {}
|
87
|
-
end
|
88
|
-
|
89
|
-
def run_validation(column, version, method_or_block)
|
90
|
-
data = @model.send(column, version).source_data
|
91
|
-
filename = @model.send(column, version).filename_to_be_assigned
|
92
|
-
opts = {attached_as: column, version: version}
|
93
|
-
|
94
|
-
if method_or_block.respond_to?(:call)
|
95
|
-
if method_or_block.arity == 2
|
96
|
-
@model.instance_exec(data, filename, &method_or_block)
|
97
|
-
else
|
98
|
-
@model.instance_exec(data, filename, opts, &method_or_block)
|
99
|
-
end
|
100
|
-
else
|
101
|
-
if @model.method(method_or_block).arity == 2
|
102
|
-
@model.send(method_or_block, data, filename)
|
103
|
-
else
|
104
|
-
@model.send(method_or_block, data, filename, opts)
|
105
|
-
end
|
106
|
-
end
|
107
|
-
end
|
108
|
-
|
109
|
-
def validations
|
110
|
-
@model.class.__saviour_validations || {}
|
111
|
-
end
|
112
|
-
end
|
113
20
|
|
114
|
-
|
115
|
-
|
116
|
-
NoActiveRecordDetected = Class.new(StandardError)
|
117
|
-
|
118
|
-
included do
|
119
|
-
raise(NoActiveRecordDetected, "Error: ActiveRecord not detected in #{self}") unless self.ancestors.include?(ActiveRecord::Base)
|
120
|
-
|
121
|
-
class_attribute(:attached_files, :__saviour_validations)
|
122
|
-
|
123
|
-
after_destroy { ModelHooks.new(self).delete! }
|
124
|
-
after_save { ModelHooks.new(self).save! }
|
125
|
-
validate { ModelHooks.new(self).validate! }
|
126
|
-
end
|
127
|
-
|
128
|
-
def reload
|
129
|
-
self.class.attached_files.each do |attach_as, versions|
|
130
|
-
(versions + [nil]).each { |version| instance_variable_set("@__uploader_#{version}_#{attach_as}", nil) }
|
131
|
-
end
|
132
|
-
super
|
133
|
-
end
|
134
|
-
|
135
|
-
module ClassMethods
|
136
|
-
def attach_file(attach_as, uploader_klass)
|
137
|
-
self.attached_files ||= {}
|
138
|
-
versions = uploader_klass.versions || []
|
139
|
-
|
140
|
-
([nil] + versions).each do |version|
|
141
|
-
column_name = ColumnNamer.new(attach_as, version).name
|
142
|
-
|
143
|
-
if self.table_exists? && !self.column_names.include?(column_name.to_s)
|
144
|
-
raise RuntimeError, "#{self} must have a database string column named '#{column_name}'"
|
145
|
-
end
|
146
|
-
end
|
147
|
-
|
148
|
-
define_method(attach_as) do |version = nil|
|
149
|
-
instance_variable_get("@__uploader_#{version}_#{attach_as}") ||
|
150
|
-
instance_variable_set("@__uploader_#{version}_#{attach_as}", ::Saviour::File.new(uploader_klass, self, attach_as, version))
|
151
|
-
end
|
152
|
-
|
153
|
-
define_method("#{attach_as}=") do |value|
|
154
|
-
send(attach_as).assign(value)
|
155
|
-
end
|
156
|
-
|
157
|
-
define_method("#{attach_as}_changed?") do
|
158
|
-
send(attach_as).changed?
|
159
|
-
end
|
160
|
-
|
161
|
-
self.attached_files[attach_as] ||= []
|
162
|
-
self.attached_files[attach_as] += versions
|
163
|
-
end
|
164
|
-
|
165
|
-
def attach_validation(attach_as, method_name = nil, &block)
|
166
|
-
self.__saviour_validations ||= Hash.new { [] }
|
167
|
-
self.__saviour_validations[attach_as] += [method_name || block]
|
168
|
-
end
|
169
|
-
end
|
21
|
+
module Saviour
|
170
22
|
end
|
data/saviour.gemspec
CHANGED
@@ -13,15 +13,11 @@ Gem::Specification.new do |spec|
|
|
13
13
|
spec.files = `git ls-files`.split($/)
|
14
14
|
spec.require_paths = ["lib"]
|
15
15
|
|
16
|
-
spec.required_ruby_version = ">= 2.
|
16
|
+
spec.required_ruby_version = ">= 2.1.0"
|
17
17
|
|
18
|
-
spec.add_dependency "activerecord", ">= 4.0"
|
19
|
-
spec.add_dependency "activesupport", ">= 4.0"
|
20
18
|
spec.add_dependency "fog-aws"
|
21
19
|
spec.add_dependency "mime-types"
|
22
20
|
spec.add_development_dependency "bundler"
|
23
21
|
spec.add_development_dependency "rake"
|
24
22
|
spec.add_development_dependency "rspec"
|
25
|
-
spec.add_development_dependency "sqlite3"
|
26
|
-
spec.add_development_dependency "appraisal"
|
27
23
|
end
|
@@ -11,7 +11,13 @@ describe "access to model data from uploaders" do
|
|
11
11
|
}
|
12
12
|
|
13
13
|
let(:klass) {
|
14
|
-
klass = Class.new
|
14
|
+
klass = Class.new {
|
15
|
+
include Saviour::BasicModel
|
16
|
+
|
17
|
+
def id
|
18
|
+
87
|
19
|
+
end
|
20
|
+
}
|
15
21
|
klass.attach_file :file, uploader
|
16
22
|
klass
|
17
23
|
}
|
@@ -19,10 +25,12 @@ describe "access to model data from uploaders" do
|
|
19
25
|
describe "file store" do
|
20
26
|
it do
|
21
27
|
with_test_file("example.xml") do |example, name|
|
22
|
-
a = klass.
|
23
|
-
|
24
|
-
|
25
|
-
|
28
|
+
a = klass.new
|
29
|
+
a.file = example
|
30
|
+
path = a.file.write
|
31
|
+
|
32
|
+
expect(Saviour::Config.storage.exists?(path)).to be_truthy
|
33
|
+
expect(path).to eq "/store/dir/87/87-file-#{name}"
|
26
34
|
end
|
27
35
|
end
|
28
36
|
end
|
@@ -14,7 +14,7 @@ describe "saving a new file" do
|
|
14
14
|
}
|
15
15
|
|
16
16
|
let(:klass) {
|
17
|
-
a = Class.new
|
17
|
+
a = Class.new { include Saviour::BasicModel }
|
18
18
|
a.attach_file :file, uploader
|
19
19
|
a
|
20
20
|
}
|
@@ -22,9 +22,13 @@ describe "saving a new file" do
|
|
22
22
|
describe "creation following main file" do
|
23
23
|
it do
|
24
24
|
with_test_file("example.xml") do |example|
|
25
|
-
a = klass.
|
26
|
-
|
27
|
-
|
25
|
+
a = klass.new
|
26
|
+
a.file = example
|
27
|
+
Saviour::LifeCycle.new(a).save!
|
28
|
+
|
29
|
+
path = a.file(:thumb).persisted_path
|
30
|
+
expect(path).not_to be_nil
|
31
|
+
expect(Saviour::Config.storage.exists?(path)).to be_truthy
|
28
32
|
end
|
29
33
|
end
|
30
34
|
end
|
@@ -32,14 +36,16 @@ describe "saving a new file" do
|
|
32
36
|
describe "deletion" do
|
33
37
|
it do
|
34
38
|
with_test_file("example.xml") do |example|
|
35
|
-
a = klass.
|
36
|
-
a.
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
a.
|
41
|
-
|
42
|
-
|
39
|
+
a = klass.new
|
40
|
+
a.file = example
|
41
|
+
Saviour::LifeCycle.new(a).save!
|
42
|
+
|
43
|
+
expect(Saviour::Config.storage.exists?(a.file(:thumb).persisted_path)).to be_truthy
|
44
|
+
expect(Saviour::Config.storage.exists?(a.file.persisted_path)).to be_truthy
|
45
|
+
|
46
|
+
Saviour::LifeCycle.new(a).delete!
|
47
|
+
expect(Saviour::Config.storage.exists?(a.file(:thumb).persisted_path)).to be_falsey
|
48
|
+
expect(Saviour::Config.storage.exists?(a.file.persisted_path)).to be_falsey
|
43
49
|
end
|
44
50
|
end
|
45
51
|
end
|
@@ -47,13 +53,18 @@ describe "saving a new file" do
|
|
47
53
|
describe "changes following main file" do
|
48
54
|
it do
|
49
55
|
with_test_file("example.xml") do |example|
|
50
|
-
a = klass.
|
51
|
-
|
52
|
-
|
56
|
+
a = klass.new
|
57
|
+
a.file = example
|
58
|
+
Saviour::LifeCycle.new(a).save!
|
59
|
+
path = a.file(:thumb).persisted_path
|
60
|
+
expect(Saviour::Config.storage.exists?(path)).to be_truthy
|
53
61
|
|
54
62
|
with_test_file("camaloon.jpg") do |file|
|
55
|
-
a.
|
56
|
-
|
63
|
+
a.file = file
|
64
|
+
Saviour::LifeCycle.new(a).save!
|
65
|
+
path = a.file(:thumb).persisted_path
|
66
|
+
|
67
|
+
expect(Saviour::Config.storage.exists?(path)).to be_truthy
|
57
68
|
file.rewind
|
58
69
|
expect(a.file(:thumb).read).to eq file.read
|
59
70
|
end
|
@@ -75,8 +86,9 @@ describe "saving a new file" do
|
|
75
86
|
|
76
87
|
it "#url" do
|
77
88
|
with_test_file("example.xml") do |example, name|
|
78
|
-
a = klass.
|
79
|
-
|
89
|
+
a = klass.new
|
90
|
+
a.file = example
|
91
|
+
Saviour::LifeCycle.new(a).save!
|
80
92
|
|
81
93
|
versioned_name = "#{File.basename(name, ".*")}_thumb#{File.extname(name)}"
|
82
94
|
expect(a.file(:thumb).url).to eq "http://domain.com/versions/store/dir/#{versioned_name}"
|
@@ -85,8 +97,9 @@ describe "saving a new file" do
|
|
85
97
|
|
86
98
|
it "#read" do
|
87
99
|
with_test_file("text.txt") do |example|
|
88
|
-
a = klass.
|
89
|
-
a.
|
100
|
+
a = klass.new
|
101
|
+
a.file = example
|
102
|
+
Saviour::LifeCycle.new(a).save!
|
90
103
|
|
91
104
|
expect(a.file(:thumb).read).to eq "Hello world\n_for_version_thumb"
|
92
105
|
end
|
@@ -94,21 +107,24 @@ describe "saving a new file" do
|
|
94
107
|
|
95
108
|
it "#delete" do
|
96
109
|
with_test_file("example.xml") do |example|
|
97
|
-
a = klass.
|
98
|
-
|
99
|
-
|
100
|
-
expect(Saviour::Config.storage.exists?(a
|
110
|
+
a = klass.new
|
111
|
+
a.file = example
|
112
|
+
Saviour::LifeCycle.new(a).save!
|
113
|
+
expect(Saviour::Config.storage.exists?(a.file(:thumb).persisted_path)).to be_truthy
|
114
|
+
expect(Saviour::Config.storage.exists?(a.file.persisted_path)).to be_truthy
|
101
115
|
|
102
116
|
a.file(:thumb).delete
|
103
|
-
|
104
|
-
expect(Saviour::Config.storage.exists?(a
|
117
|
+
|
118
|
+
expect(Saviour::Config.storage.exists?(a.file(:thumb).persisted_path)).to be_falsey
|
119
|
+
expect(Saviour::Config.storage.exists?(a.file.persisted_path)).to be_truthy
|
105
120
|
end
|
106
121
|
end
|
107
122
|
|
108
123
|
it "#exists?" do
|
109
124
|
with_test_file("example.xml") do |example|
|
110
|
-
a = klass.
|
111
|
-
|
125
|
+
a = klass.new
|
126
|
+
a.file = example
|
127
|
+
Saviour::LifeCycle.new(a).save!
|
112
128
|
expect(a.file(:thumb).exists?).to be_truthy
|
113
129
|
end
|
114
130
|
end
|
@@ -117,18 +133,21 @@ describe "saving a new file" do
|
|
117
133
|
describe "assign specific version after first creation" do
|
118
134
|
it do
|
119
135
|
with_test_file("example.xml") do |example|
|
120
|
-
a = klass.
|
121
|
-
|
122
|
-
|
123
|
-
|
136
|
+
a = klass.new
|
137
|
+
a.file = example
|
138
|
+
Saviour::LifeCycle.new(a).save!
|
139
|
+
|
140
|
+
thumb_path = a.file(:thumb).persisted_path
|
141
|
+
expect(Saviour::Config.storage.exists?(thumb_path)).to be_truthy
|
142
|
+
expect(thumb_path).to eq "/versions/store/dir/#{File.basename(example, ".*")}_thumb.xml"
|
124
143
|
|
125
144
|
with_test_file("camaloon.jpg") do |ex2, filename|
|
126
145
|
a.file(:thumb).assign(ex2)
|
146
|
+
Saviour::LifeCycle.new(a).save!
|
147
|
+
thumb_path = a.file(:thumb).persisted_path
|
127
148
|
|
128
|
-
expect(
|
129
|
-
|
130
|
-
expect(Saviour::Config.storage.exists?(a[:file_thumb])).to be_truthy
|
131
|
-
expect(a[:file_thumb]).to eq "/versions/store/dir/#{File.basename(filename, ".*")}.jpg"
|
149
|
+
expect(Saviour::Config.storage.exists?(thumb_path)).to be_truthy
|
150
|
+
expect(thumb_path).to eq "/versions/store/dir/#{File.basename(filename, ".*")}.jpg"
|
132
151
|
end
|
133
152
|
end
|
134
153
|
end
|
@@ -147,19 +166,23 @@ describe "saving a new file" do
|
|
147
166
|
|
148
167
|
it "runs the processors for that version only" do
|
149
168
|
with_test_file("example.xml") do |example|
|
150
|
-
a = klass.
|
151
|
-
|
152
|
-
|
153
|
-
|
169
|
+
a = klass.new
|
170
|
+
a.file = example
|
171
|
+
Saviour::LifeCycle.new(a).save!
|
172
|
+
thumb_path = a.file(:thumb).persisted_path
|
173
|
+
|
174
|
+
expect(Saviour::Config.storage.exists?(thumb_path)).to be_truthy
|
175
|
+
expect(thumb_path).to eq "/versions/store/dir/#{File.basename(example, ".*")}_thumb.xml"
|
154
176
|
|
155
177
|
with_test_file("camaloon.jpg") do |ex2, filename|
|
156
178
|
a.file(:thumb).assign(ex2)
|
157
179
|
|
158
|
-
|
180
|
+
Saviour::LifeCycle.new(a).save!
|
181
|
+
thumb_path = a.file(:thumb).persisted_path
|
159
182
|
|
160
|
-
expect(Saviour::Config.storage.exists?(
|
161
|
-
expect(
|
162
|
-
expect(Saviour::Config.storage.read(
|
183
|
+
expect(Saviour::Config.storage.exists?(thumb_path)).to be_truthy
|
184
|
+
expect(thumb_path).to eq "/versions/store/dir/#{File.basename(filename, ".*")}.jpg"
|
185
|
+
expect(Saviour::Config.storage.read(thumb_path)).to eq "modified_content"
|
163
186
|
end
|
164
187
|
end
|
165
188
|
end
|
@@ -168,16 +191,16 @@ describe "saving a new file" do
|
|
168
191
|
|
169
192
|
describe "respects version assignation vs main file assignation on conflict" do
|
170
193
|
it do
|
171
|
-
a = klass.
|
194
|
+
a = klass.new
|
172
195
|
|
173
196
|
with_test_file("example.xml") do |file1, fname1|
|
174
197
|
with_test_file("camaloon.jpg") do |file2, fname2|
|
175
198
|
a.file.assign(file1)
|
176
199
|
a.file(:thumb).assign(file2)
|
177
|
-
a.save!
|
200
|
+
Saviour::LifeCycle.new(a).save!
|
178
201
|
|
179
|
-
expect(a
|
180
|
-
expect(a
|
202
|
+
expect(a.file.persisted_path).to eq "/store/dir/#{fname1}"
|
203
|
+
expect(a.file(:thumb).persisted_path).to eq "/versions/store/dir/#{fname2}"
|
181
204
|
end
|
182
205
|
end
|
183
206
|
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour::AttributeNameCalculator do
|
4
|
+
it "returns the attached_as value" do
|
5
|
+
expect(Saviour::AttributeNameCalculator.new("preview_file").name).to eq "preview_file"
|
6
|
+
end
|
7
|
+
|
8
|
+
it "appends the version if provided" do
|
9
|
+
expect(Saviour::AttributeNameCalculator.new("preview_file", "thumb").name).to eq "preview_file_thumb"
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Saviour do
|
4
|
+
describe ".attached_files" do
|
5
|
+
it "includes a mapping of the currently attached files and their versions" do
|
6
|
+
uploader = Class.new(Saviour::BaseUploader) do
|
7
|
+
store_dir { "/store/dir" }
|
8
|
+
|
9
|
+
version(:thumb)
|
10
|
+
version(:thumb_2)
|
11
|
+
end
|
12
|
+
|
13
|
+
klass = Class.new do
|
14
|
+
include Saviour::BasicModel
|
15
|
+
attach_file :file, uploader
|
16
|
+
end
|
17
|
+
|
18
|
+
expect(klass.attached_files).to eq({file: [:thumb, :thumb_2]})
|
19
|
+
|
20
|
+
klass2 = Class.new do
|
21
|
+
include Saviour::BasicModel
|
22
|
+
attach_file :file, Saviour::BaseUploader
|
23
|
+
end
|
24
|
+
|
25
|
+
expect(klass2.attached_files).to eq({file: []})
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
it "doens't mess with default File constant" do
|
30
|
+
# Constant lookup in ruby works by lexical scope, so we can't create classes dynamically like above.
|
31
|
+
expect(TestForSaviourFileResolution.new.foo).to be_falsey
|
32
|
+
end
|
33
|
+
|
34
|
+
it "shares model definitions with subclasses" do
|
35
|
+
uploader = Class.new(Saviour::BaseUploader) do
|
36
|
+
store_dir { "/store/dir" }
|
37
|
+
version(:thumb)
|
38
|
+
end
|
39
|
+
|
40
|
+
klass = Class.new do
|
41
|
+
include Saviour::BasicModel
|
42
|
+
attach_file :file, uploader
|
43
|
+
end
|
44
|
+
expect(klass.attached_files).to eq({file: [:thumb]})
|
45
|
+
|
46
|
+
klass2 = Class.new(klass)
|
47
|
+
expect(klass2.attached_files).to eq({file: [:thumb]})
|
48
|
+
|
49
|
+
expect(klass2.new.file).to respond_to :exists?
|
50
|
+
end
|
51
|
+
end
|