bulldog 0.0.5 → 0.0.6
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.
- data/CHANGELOG +5 -0
- data/VERSION +1 -1
- data/bulldog.gemspec +2 -1
- data/lib/bulldog/attachment/base.rb +5 -0
- data/lib/bulldog/attachment/image.rb +5 -0
- data/lib/bulldog/attachment/maybe.rb +38 -5
- data/lib/bulldog/attachment/video.rb +7 -0
- data/lib/bulldog/has_attachment.rb +2 -2
- data/lib/bulldog/stream.rb +7 -0
- data/spec/data/test.ogg +0 -0
- data/spec/unit/attachment/image_spec.rb +36 -0
- data/spec/unit/attachment/maybe_spec.rb +23 -1
- data/spec/unit/attachment/video_spec.rb +36 -0
- data/spec/unit/stream_spec.rb +57 -17
- metadata +2 -1
data/CHANGELOG
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.6
|
data/bulldog.gemspec
CHANGED
@@ -5,7 +5,7 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{bulldog}
|
8
|
-
s.version = "0.0.
|
8
|
+
s.version = "0.0.6"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["George Ogata"]
|
@@ -62,6 +62,7 @@ Flexible file attachments for active record.
|
|
62
62
|
"spec/data/empty.txt",
|
63
63
|
"spec/data/test.jpg",
|
64
64
|
"spec/data/test.mov",
|
65
|
+
"spec/data/test.ogg",
|
65
66
|
"spec/data/test.pdf",
|
66
67
|
"spec/data/test.png",
|
67
68
|
"spec/data/test2.jpg",
|
@@ -66,9 +66,12 @@ module Bulldog
|
|
66
66
|
end
|
67
67
|
|
68
68
|
#
|
69
|
-
#
|
69
|
+
# Load the attachment.
|
70
70
|
#
|
71
|
-
|
71
|
+
# Called just after initializing the attachment, or after a
|
72
|
+
# reload on the new attachment.
|
73
|
+
#
|
74
|
+
def load
|
72
75
|
storable_attributes.each do |name, storable_attribute|
|
73
76
|
if (column_name = reflection.column_name_for_stored_attribute(name))
|
74
77
|
value = storable_attribute.value_for(self, :original)
|
@@ -78,16 +81,46 @@ module Bulldog
|
|
78
81
|
end
|
79
82
|
|
80
83
|
#
|
81
|
-
#
|
84
|
+
# Unload the attachment.
|
85
|
+
#
|
86
|
+
# Called before a reload on the old attachment, or before a
|
87
|
+
# destroy.
|
82
88
|
#
|
83
|
-
def
|
84
|
-
storable_attributes.each do |name,
|
89
|
+
def unload
|
90
|
+
storable_attributes.each do |name, storable_attribute|
|
85
91
|
if (column_name = reflection.column_name_for_stored_attribute(name))
|
86
92
|
record.send("#{column_name}=", nil)
|
87
93
|
end
|
94
|
+
if storable_attribute.memoize?
|
95
|
+
send("memoized_#{name}").clear
|
96
|
+
end
|
88
97
|
end
|
89
98
|
end
|
90
99
|
|
100
|
+
#
|
101
|
+
# Refresh the attachment. This includes anything read from the
|
102
|
+
# file, such as stored attributes, and dimensions.
|
103
|
+
#
|
104
|
+
# Use this to update the record if the underlying file has been
|
105
|
+
# modified outside of Bulldog. Note that the file has to be
|
106
|
+
# initialized from a saved file for this to work.
|
107
|
+
#
|
108
|
+
# Example:
|
109
|
+
#
|
110
|
+
# article = Article.create(:photo => photo_file)
|
111
|
+
# article = Article.find(article.id)
|
112
|
+
#
|
113
|
+
# # ... file is modified by an outside force ...
|
114
|
+
#
|
115
|
+
# article.photo.reload
|
116
|
+
# article.photo.dimensions # now reflects the new dimensions
|
117
|
+
#
|
118
|
+
def reload
|
119
|
+
unload
|
120
|
+
stream.reload
|
121
|
+
load
|
122
|
+
end
|
123
|
+
|
91
124
|
#
|
92
125
|
# Set the stored attributes in the attachment from the values in
|
93
126
|
# the record.
|
@@ -80,6 +80,13 @@ module Bulldog
|
|
80
80
|
|
81
81
|
storable_attribute :duration , :per_style => true, :memoize => true
|
82
82
|
|
83
|
+
def unload
|
84
|
+
super
|
85
|
+
instance_variables.grep(/@original_/).each do |name|
|
86
|
+
instance_variable_set(name, nil)
|
87
|
+
end
|
88
|
+
end
|
89
|
+
|
83
90
|
protected # ---------------------------------------------------
|
84
91
|
|
85
92
|
#
|
@@ -99,9 +99,9 @@ module Bulldog
|
|
99
99
|
def assign_attachment(name, value)
|
100
100
|
old_attachment = _attachment_for(name)
|
101
101
|
unless old_attachment.value == value
|
102
|
-
old_attachment.
|
102
|
+
old_attachment.unload
|
103
103
|
new_attachment = make_attachment_for(name, value)
|
104
|
-
new_attachment.
|
104
|
+
new_attachment.load
|
105
105
|
write_attribute(name, new_attachment)
|
106
106
|
end
|
107
107
|
end
|
data/lib/bulldog/stream.rb
CHANGED
data/spec/data/test.ogg
ADDED
Binary file
|
@@ -125,4 +125,40 @@ describe Attachment::Image do
|
|
125
125
|
end
|
126
126
|
end
|
127
127
|
end
|
128
|
+
|
129
|
+
describe "#reload" do
|
130
|
+
before do
|
131
|
+
thing = Thing.create(:photo => test_image_file('test.jpg'))
|
132
|
+
@thing = Thing.find(thing.id)
|
133
|
+
end
|
134
|
+
|
135
|
+
it "should update the stored attributes from the file" do
|
136
|
+
# Prime the cached values.
|
137
|
+
@thing.photo_width.should == 40
|
138
|
+
@thing.photo_height.should == 30
|
139
|
+
@thing.photo_aspect_ratio.should be_close(4.0/3, 1e-5)
|
140
|
+
@thing.photo_dimensions.should == '40x30'
|
141
|
+
|
142
|
+
FileUtils.cp(test_path('test2.jpg'), @thing.photo.path(:original))
|
143
|
+
@thing.photo.reload
|
144
|
+
@thing.photo_width.should == 2
|
145
|
+
@thing.photo_height.should == 2
|
146
|
+
@thing.photo_aspect_ratio.should == 1
|
147
|
+
@thing.photo_dimensions.should == '2x2'
|
148
|
+
end
|
149
|
+
|
150
|
+
it "should update the original dimensions from the file" do
|
151
|
+
@thing.photo.dimensions(:original).should == [40, 30]
|
152
|
+
FileUtils.cp(test_path('test2.jpg'), @thing.photo.path(:original))
|
153
|
+
@thing.photo.reload
|
154
|
+
@thing.photo.dimensions(:original).should == [2, 2]
|
155
|
+
end
|
156
|
+
|
157
|
+
it "should update the dimensions for each style from the file" do
|
158
|
+
@thing.photo.dimensions(:double).should == [80, 60]
|
159
|
+
FileUtils.cp(test_path('test2.jpg'), @thing.photo.path(:original))
|
160
|
+
@thing.photo.reload
|
161
|
+
@thing.photo.dimensions(:double).should == [60, 60]
|
162
|
+
end
|
163
|
+
end
|
128
164
|
end
|
@@ -1,7 +1,10 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
3
|
describe Attachment::Maybe do
|
4
|
-
use_model_class(:Thing,
|
4
|
+
use_model_class(:Thing,
|
5
|
+
:photo_file_name => :string,
|
6
|
+
:photo_file_size => :integer,
|
7
|
+
:photo_content_type => :string)
|
5
8
|
|
6
9
|
before do
|
7
10
|
spec = self
|
@@ -123,4 +126,23 @@ describe Attachment::Maybe do
|
|
123
126
|
end
|
124
127
|
end
|
125
128
|
end
|
129
|
+
|
130
|
+
describe "#reload" do
|
131
|
+
before do
|
132
|
+
thing = Thing.create(:photo => test_file('test.png'))
|
133
|
+
@thing = Thing.find(thing.id)
|
134
|
+
end
|
135
|
+
|
136
|
+
it "should update the file size stored attribute from the file" do
|
137
|
+
FileUtils.cp(test_path('test2.jpg'), @thing.photo.path(:original))
|
138
|
+
@thing.photo.reload
|
139
|
+
@thing.photo_file_size.should == File.size(test_path('test2.jpg'))
|
140
|
+
end
|
141
|
+
|
142
|
+
it "should reload the content type stored attribute from the file" do
|
143
|
+
FileUtils.cp(test_path('test.png'), @thing.photo.path(:original))
|
144
|
+
@thing.photo.reload
|
145
|
+
@thing.photo_content_type.should =~ %r'image/png'
|
146
|
+
end
|
147
|
+
end
|
126
148
|
end
|
@@ -173,4 +173,40 @@ describe Attachment::Video do
|
|
173
173
|
end
|
174
174
|
end
|
175
175
|
end
|
176
|
+
|
177
|
+
describe "#reload" do
|
178
|
+
before do
|
179
|
+
thing = Thing.create(:video => test_video_file('test.mov'))
|
180
|
+
@thing = Thing.find(thing.id)
|
181
|
+
end
|
182
|
+
|
183
|
+
it "should update the stored attributes from the file" do
|
184
|
+
# Prime the cached values.
|
185
|
+
@thing.video_width.should == 640
|
186
|
+
@thing.video_height.should == 480
|
187
|
+
@thing.video_aspect_ratio.should be_close(4.0/3, 1e-5)
|
188
|
+
@thing.video_dimensions.should == '640x480'
|
189
|
+
|
190
|
+
FileUtils.cp(test_path('test.ogg'), @thing.video.path(:original))
|
191
|
+
@thing.video.reload
|
192
|
+
@thing.video_width.should == 176
|
193
|
+
@thing.video_height.should == 144
|
194
|
+
@thing.video_aspect_ratio.should == 176.0/144
|
195
|
+
@thing.video_dimensions.should == '176x144'
|
196
|
+
end
|
197
|
+
|
198
|
+
it "should update the original dimensions from the file" do
|
199
|
+
@thing.video.dimensions(:original).should == [640, 480]
|
200
|
+
FileUtils.cp(test_path('test.ogg'), @thing.video.path(:original))
|
201
|
+
@thing.video.reload
|
202
|
+
@thing.video.dimensions(:original).should == [176, 144]
|
203
|
+
end
|
204
|
+
|
205
|
+
it "should update the dimensions for each style from the file" do
|
206
|
+
@thing.video.dimensions(:half).should == [320, 240]
|
207
|
+
FileUtils.cp(test_path('test.ogg'), @thing.video.path(:original))
|
208
|
+
@thing.video.reload
|
209
|
+
@thing.video.dimensions(:half).should == [292, 240]
|
210
|
+
end
|
211
|
+
end
|
176
212
|
end
|
data/spec/unit/stream_spec.rb
CHANGED
@@ -82,6 +82,40 @@ describe Stream do
|
|
82
82
|
end
|
83
83
|
end
|
84
84
|
end
|
85
|
+
|
86
|
+
describe "#reload" do
|
87
|
+
if options[:reloadable]
|
88
|
+
it "should make #size return the new size of the file" do
|
89
|
+
stream = stream('content')
|
90
|
+
update_target(stream, 'new content')
|
91
|
+
stream.reload
|
92
|
+
stream.size.should == 'new content'.size
|
93
|
+
end
|
94
|
+
|
95
|
+
it "should make #content_type return the new content type of the file" do
|
96
|
+
jpg_data = File.read(test_path('test.jpg'))
|
97
|
+
png_data = File.read(test_path('test.png'))
|
98
|
+
stream = stream(jpg_data)
|
99
|
+
stream.content_type.should =~ %r'\Aimage/jpeg'
|
100
|
+
update_target(stream, png_data)
|
101
|
+
stream.reload
|
102
|
+
stream.content_type.should =~ %r'\Aimage/png'
|
103
|
+
end
|
104
|
+
else
|
105
|
+
it "should not change the result of #size" do
|
106
|
+
stream = stream('content')
|
107
|
+
stream.reload
|
108
|
+
stream.size.should == 'content'.size
|
109
|
+
end
|
110
|
+
|
111
|
+
it "should not change the result of #content_type" do
|
112
|
+
jpg_data = File.read(test_path('test.jpg'))
|
113
|
+
stream = stream(jpg_data)
|
114
|
+
stream.reload
|
115
|
+
stream.content_type.should =~ %r'\Aimage/jpeg'
|
116
|
+
end
|
117
|
+
end
|
118
|
+
end
|
85
119
|
end
|
86
120
|
|
87
121
|
describe 'for a small uploaded file' do
|
@@ -100,28 +134,28 @@ describe Stream do
|
|
100
134
|
it_should_behave_like_all_streams :file_name => :original_path
|
101
135
|
|
102
136
|
def object(content)
|
103
|
-
|
104
|
-
|
137
|
+
tempfile = Tempfile.new('bulldog-spec')
|
138
|
+
tempfile.print(content)
|
139
|
+
class << tempfile
|
105
140
|
attr_accessor :original_path
|
106
141
|
end
|
107
|
-
|
142
|
+
tempfile
|
108
143
|
end
|
109
144
|
end
|
110
145
|
|
111
|
-
describe
|
146
|
+
describe Stream::ForStringIO do
|
112
147
|
it_should_behave_like_all_streams
|
113
148
|
|
114
149
|
def object(content)
|
115
|
-
|
116
|
-
|
117
|
-
class << tempfile
|
150
|
+
stringio = StringIO.new(content)
|
151
|
+
class << stringio
|
118
152
|
attr_accessor :original_path
|
119
153
|
end
|
120
|
-
|
154
|
+
stringio
|
121
155
|
end
|
122
156
|
end
|
123
157
|
|
124
|
-
describe
|
158
|
+
describe Stream::ForTempfile do
|
125
159
|
it_should_behave_like_all_streams
|
126
160
|
|
127
161
|
def object(content)
|
@@ -131,7 +165,7 @@ describe Stream do
|
|
131
165
|
end
|
132
166
|
end
|
133
167
|
|
134
|
-
describe
|
168
|
+
describe "Stream::ForFile (opened for writing)" do
|
135
169
|
it_should_behave_like_all_streams :file_name => :basename
|
136
170
|
|
137
171
|
def object(content)
|
@@ -152,7 +186,7 @@ describe Stream do
|
|
152
186
|
end
|
153
187
|
end
|
154
188
|
|
155
|
-
describe
|
189
|
+
describe "Stream::ForFile (opened for writing)" do
|
156
190
|
it_should_behave_like_all_streams :file_name => :basename
|
157
191
|
|
158
192
|
def object(content)
|
@@ -162,17 +196,21 @@ describe Stream do
|
|
162
196
|
end
|
163
197
|
end
|
164
198
|
|
165
|
-
describe
|
166
|
-
it_should_behave_like_all_streams :file_name => :file_name
|
199
|
+
describe Stream::ForSavedFile do
|
200
|
+
it_should_behave_like_all_streams :file_name => :file_name, :reloadable => true
|
167
201
|
|
168
202
|
def object(content)
|
169
203
|
path = "#{temporary_directory}/file"
|
170
204
|
open(path, 'w'){|f| f.print content}
|
171
205
|
SavedFile.new(path)
|
172
206
|
end
|
207
|
+
|
208
|
+
def update_target(stream, content)
|
209
|
+
open(stream.target.path, 'w'){|f| f.print content}
|
210
|
+
end
|
173
211
|
end
|
174
212
|
|
175
|
-
describe
|
213
|
+
describe Stream::ForMissingFile do
|
176
214
|
it_should_behave_like_all_streams :file_name => :file_name
|
177
215
|
|
178
216
|
def object(content)
|
@@ -210,12 +248,14 @@ describe Stream do
|
|
210
248
|
end
|
211
249
|
end
|
212
250
|
|
213
|
-
describe
|
251
|
+
describe Stream::ForIO do
|
214
252
|
it_should_behave_like_all_streams
|
215
253
|
|
216
254
|
def object(content)
|
217
|
-
|
218
|
-
|
255
|
+
readable, writable = IO.pipe
|
256
|
+
writable.print content
|
257
|
+
writable.close
|
258
|
+
autoclose_stream(readable)
|
219
259
|
end
|
220
260
|
|
221
261
|
describe "#path" do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: bulldog
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- George Ogata
|
@@ -98,6 +98,7 @@ files:
|
|
98
98
|
- spec/data/empty.txt
|
99
99
|
- spec/data/test.jpg
|
100
100
|
- spec/data/test.mov
|
101
|
+
- spec/data/test.ogg
|
101
102
|
- spec/data/test.pdf
|
102
103
|
- spec/data/test.png
|
103
104
|
- spec/data/test2.jpg
|