bulldog 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
data/CHANGELOG CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.1.1 2010-06-30
2
+
3
+ * Create output directory when recording frames if necessary.
4
+ * Only add Bulldog callbacks in classes that need them.
5
+ * Fix comparison of attachments with non-attachment classes.
6
+ * Don't create blank file when saving record with a missing file.
7
+
1
8
  == 0.1.0 2010-06-23
2
9
 
3
10
  * Add Bulldog.path_root, for specifying per-environment roots.
data/lib/bulldog.rb CHANGED
@@ -117,5 +117,5 @@ module Bulldog
117
117
  self.ffmpeg_path = 'ffmpeg'
118
118
  end
119
119
 
120
- ActiveRecord::Base.send :include, Bulldog::HasAttachment
120
+ ActiveRecord::Base.send :extend, Bulldog::HasAttachment
121
121
  ActiveRecord::Base.send :include, Bulldog::Validations
@@ -11,10 +11,7 @@ module Bulldog
11
11
  end
12
12
 
13
13
  def initialize(record, name, stream)
14
- @record = record
15
- @name = name
16
- @stream = stream
17
- @value = stream && stream.target
14
+ super
18
15
  @examination_result = nil
19
16
  end
20
17
 
@@ -9,7 +9,7 @@ module Bulldog
9
9
  @name = name
10
10
  @stream = stream
11
11
  @value = stream && stream.target
12
- @saved = value.is_a?(SavedFile)
12
+ @saved = @value.is_a?(SavedFile) || @value.is_a?(MissingFile)
13
13
  end
14
14
 
15
15
  attr_reader :record, :name, :stream, :value
@@ -39,7 +39,8 @@ module Bulldog
39
39
  # same state as the given Attachment.
40
40
  #
41
41
  def ==(other)
42
- record == other.record &&
42
+ other.is_a?(Bulldog::Attachment::Maybe) &&
43
+ record == other.record &&
43
44
  name == other.name &&
44
45
  value == other.value &&
45
46
  saved? == other.saved?
@@ -1,160 +1,180 @@
1
1
  module Bulldog
2
2
  module HasAttachment
3
- def self.included(base)
4
- base.extend ClassMethods
5
- base.instance_variable_set(:@attachment_reflections, {})
3
+ #
4
+ # Declare that this model has an attachment.
5
+ #
6
+ # TODO: example that shows all the options.
7
+ #
8
+ def has_attachment(name, &block)
9
+ unless include?(InstanceMethods)
10
+ extend ClassMethods
11
+ include InstanceMethods
12
+ end
6
13
 
7
- # We need to store the attachment changes ourselves, since
8
- # they're unavailable in an after_save.
9
- base.before_save :store_original_attachments
10
- base.after_save :save_attachments
11
- base.after_save :clear_original_attachments
14
+ reflection = attachment_reflections[name] || Reflection.new(self, name)
15
+ reflection.configure(&block)
16
+ attachment_reflections[name] = reflection
17
+ define_attachment_accessors(reflection.name)
18
+ define_attachment_attribute_methods(reflection.name)
19
+ end
12
20
 
13
- base.before_save :update_attachment_timestamps
14
- base.after_destroy :destroy_attachments
21
+ module InstanceMethods
22
+ def self.included(base)
23
+ base.instance_variable_set(:@attachment_reflections, {})
15
24
 
16
- # Force initialization of attachments, as #destroy will freeze
17
- # the attributes afterwards.
18
- base.before_destroy :initialize_remaining_attachments
25
+ # We need to store the attachment changes ourselves, since
26
+ # they're unavailable in an after_save.
27
+ base.before_save :store_original_attachments
28
+ base.after_save :save_attachments
29
+ base.after_save :clear_original_attachments
19
30
 
20
- %w[validation save create update].each do |event|
21
- base.send("before_#{event}", "process_attachments_for_before_#{event}")
22
- base.send("after_#{event}", "process_attachments_for_after_#{event}")
31
+ base.before_save :update_attachment_timestamps
32
+ base.after_destroy :destroy_attachments
33
+
34
+ # Force initialization of attachments, as #destroy will freeze
35
+ # the attributes afterwards.
36
+ base.before_destroy :initialize_remaining_attachments
37
+
38
+ %w[validation save create update].each do |event|
39
+ base.send("before_#{event}", "process_attachments_for_before_#{event}")
40
+ base.send("after_#{event}", "process_attachments_for_after_#{event}")
41
+ end
23
42
  end
24
- end
25
43
 
26
- def save_attachments
27
- attachment_reflections.each do |name, reflection|
28
- original_attachment = @original_attachments[name] and
29
- original_attachment.destroy
30
- _attachment_for(name).save
44
+ def save_attachments
45
+ attachment_reflections.each do |name, reflection|
46
+ original_attachment = @original_attachments[name] and
47
+ original_attachment.destroy
48
+ _attachment_for(name).save
49
+ end
31
50
  end
32
- end
33
51
 
34
- def destroy_attachments
35
- attachment_reflections.each do |name, reflection|
36
- _attachment_for(name).destroy
52
+ def destroy_attachments
53
+ attachment_reflections.each do |name, reflection|
54
+ _attachment_for(name).destroy
55
+ end
37
56
  end
38
- end
39
57
 
40
- def update_attachment_timestamps
41
- attachment_reflections.each do |name, reflection|
42
- next unless send("#{name}_changed?")
43
- setter = "#{name}_updated_at="
44
- if respond_to?(setter)
45
- send(setter, Time.now)
58
+ def update_attachment_timestamps
59
+ attachment_reflections.each do |name, reflection|
60
+ next unless send("#{name}_changed?")
61
+ setter = "#{name}_updated_at="
62
+ if respond_to?(setter)
63
+ send(setter, Time.now)
64
+ end
46
65
  end
47
66
  end
48
- end
49
67
 
50
- def process_attachment(name, event, *args)
51
- reflection = attachment_reflections[name] or
52
- raise ArgumentError, "no such attachment: #{name}"
53
- _attachment_for(name).process(event, *args)
54
- end
68
+ def process_attachment(name, event, *args)
69
+ reflection = attachment_reflections[name] or
70
+ raise ArgumentError, "no such attachment: #{name}"
71
+ _attachment_for(name).process(event, *args)
72
+ end
55
73
 
56
- def attachment_reflection_for(name)
57
- self.class.attachment_reflections[name]
58
- end
74
+ def attachment_reflection_for(name)
75
+ self.class.attachment_reflections[name]
76
+ end
59
77
 
60
- private # -------------------------------------------------------
78
+ private # -------------------------------------------------------
61
79
 
62
- # Prefixed with '_', as it would collide with paperclip otherwise.
63
- def _attachment_for(name)
64
- read_attribute(name) or
65
- initialize_attachment(name)
66
- end
80
+ # Prefixed with '_', as it would collide with paperclip otherwise.
81
+ def _attachment_for(name)
82
+ read_attribute(name) or
83
+ initialize_attachment(name)
84
+ end
67
85
 
68
- def initialize_attachment(name)
69
- if new_record?
70
- value = nil
71
- else
72
- reflection = attachment_reflection_for(name)
73
- file_name_column = reflection.column_name_for_stored_attribute(:file_name)
74
- file_name = file_name_column ? send(file_name_column) : nil
75
- if file_name_column && file_name.nil?
86
+ def initialize_attachment(name)
87
+ if new_record?
76
88
  value = nil
77
89
  else
78
- template = reflection.path_template
79
- style = reflection.styles[:original]
80
- original_path = Interpolation.interpolate(template, self, name, style, :basename => file_name)
81
- if File.exist?(original_path)
82
- value = SavedFile.new(original_path, :file_name => file_name)
90
+ reflection = attachment_reflection_for(name)
91
+ file_name_column = reflection.column_name_for_stored_attribute(:file_name)
92
+ file_name = file_name_column ? send(file_name_column) : nil
93
+ if file_name_column && file_name.nil?
94
+ value = nil
83
95
  else
84
- if file_name_column
85
- value = MissingFile.new(:file_name => file_name)
96
+ template = reflection.path_template
97
+ style = reflection.styles[:original]
98
+ original_path = Interpolation.interpolate(template, self, name, style, :basename => file_name)
99
+ if File.exist?(original_path)
100
+ value = SavedFile.new(original_path, :file_name => file_name)
86
101
  else
87
- value = nil
102
+ if file_name_column
103
+ value = MissingFile.new(:file_name => file_name)
104
+ else
105
+ value = nil
106
+ end
88
107
  end
89
108
  end
90
109
  end
110
+
111
+ attachment = make_attachment_for(name, value)
112
+ write_attribute_without_dirty(name, attachment)
113
+ attachment.read_storable_attributes
114
+ attachment
91
115
  end
92
116
 
93
- attachment = make_attachment_for(name, value)
94
- write_attribute_without_dirty(name, attachment)
95
- attachment.read_storable_attributes
96
- attachment
97
- end
117
+ def assign_attachment(name, value)
118
+ old_attachment = _attachment_for(name)
119
+ unless old_attachment.value == value
120
+ old_attachment.unload
121
+ new_attachment = make_attachment_for(name, value)
122
+ new_attachment.load
123
+ write_attribute(name, new_attachment)
124
+ end
125
+ end
98
126
 
99
- def assign_attachment(name, value)
100
- old_attachment = _attachment_for(name)
101
- unless old_attachment.value == value
102
- old_attachment.unload
103
- new_attachment = make_attachment_for(name, value)
104
- new_attachment.load
105
- write_attribute(name, new_attachment)
127
+ def make_attachment_for(name, value)
128
+ return Attachment.none(self, name) if value.nil?
129
+ stream = Stream.new(value)
130
+ reflection = attachment_reflection_for(name)
131
+ type = reflection.detect_attachment_type(self, stream)
132
+ Attachment.of_type(type, self, name, stream)
106
133
  end
107
- end
108
134
 
109
- def make_attachment_for(name, value)
110
- return Attachment.none(self, name) if value.nil?
111
- stream = Stream.new(value)
112
- reflection = attachment_reflection_for(name)
113
- type = reflection.detect_attachment_type(self, stream)
114
- Attachment.of_type(type, self, name, stream)
115
- end
135
+ def store_original_attachments
136
+ @original_attachments = {}
137
+ attachment_reflections.each do |name, reflection|
138
+ if send("#{name}_changed?")
139
+ @original_attachments[name] = send("#{name}_was")
140
+ end
141
+ end
142
+ end
116
143
 
117
- def store_original_attachments
118
- @original_attachments = {}
119
- attachment_reflections.each do |name, reflection|
120
- if send("#{name}_changed?")
121
- @original_attachments[name] = send("#{name}_was")
144
+ def clear_original_attachments
145
+ # This can be unset if the record is resaved between store and
146
+ # clear (e.g., in an after_save: store, save, store, clear, clear).
147
+ if instance_variable_defined?(:@original_attachments)
148
+ remove_instance_variable :@original_attachments
122
149
  end
123
150
  end
124
- end
125
151
 
126
- def clear_original_attachments
127
- # Somehow this can be unset sometimes. TODO: Work out how.
128
- if instance_variable_defined?(:@original_attachments)
129
- remove_instance_variable :@original_attachments
152
+ def process_attachments_for_event(event, *args)
153
+ self.class.attachment_reflections.each do |name, reflection|
154
+ _attachment_for(reflection.name).process(event, *args)
155
+ end
130
156
  end
131
- end
132
157
 
133
- def process_attachments_for_event(event, *args)
134
- self.class.attachment_reflections.each do |name, reflection|
135
- _attachment_for(reflection.name).process(event, *args)
158
+ def initialize_remaining_attachments
159
+ self.attachment_reflections.each do |name, reflection|
160
+ _attachment_for(name) # force initialization
161
+ end
136
162
  end
137
- end
138
163
 
139
- def initialize_remaining_attachments
140
- self.attachment_reflections.each do |name, reflection|
141
- _attachment_for(name) # force initialization
164
+ %w[validation save create update].each do |event|
165
+ module_eval <<-EOS
166
+ def process_attachments_for_before_#{event}
167
+ process_attachments_for_event(:before_#{event})
168
+ end
169
+ def process_attachments_for_after_#{event}
170
+ process_attachments_for_event(:after_#{event})
171
+ end
172
+ EOS
142
173
  end
143
- end
144
174
 
145
- %w[validation save create update].each do |event|
146
- module_eval <<-EOS
147
- def process_attachments_for_before_#{event}
148
- process_attachments_for_event(:before_#{event})
149
- end
150
- def process_attachments_for_after_#{event}
151
- process_attachments_for_event(:after_#{event})
152
- end
153
- EOS
175
+ delegate :attachment_reflections, :to => 'self.class'
154
176
  end
155
177
 
156
- delegate :attachment_reflections, :to => 'self.class'
157
-
158
178
  module ClassMethods
159
179
  def attachment_reflections
160
180
  @attachment_reflections ||=
@@ -168,19 +188,6 @@ module Bulldog
168
188
  end
169
189
  end
170
190
 
171
- #
172
- # Declare that this model has an attachment.
173
- #
174
- # TODO: example that shows all the options.
175
- #
176
- def has_attachment(name, &block)
177
- reflection = attachment_reflections[name] || Reflection.new(self, name)
178
- reflection.configure(&block)
179
- attachment_reflections[name] = reflection
180
- define_attachment_accessors(reflection.name)
181
- define_attachment_attribute_methods(reflection.name)
182
- end
183
-
184
191
  def define_attachment_accessors(name)
185
192
  module_eval <<-EOS, __FILE__, __LINE__
186
193
  def #{name}
@@ -77,6 +77,7 @@ module Bulldog
77
77
  output_path = output_file(style.name)
78
78
  end
79
79
 
80
+ FileUtils.mkdir_p File.dirname(output_path)
80
81
  operate '-y', output_path
81
82
  if block
82
83
  @still_frame_callbacks << lambda{instance_exec(output_path, &block)}
@@ -1,5 +1,5 @@
1
1
  module Bulldog
2
- VERSION = [0, 1, 0]
2
+ VERSION = [0, 1, 1]
3
3
 
4
4
  class << VERSION
5
5
  include Comparable
@@ -335,6 +335,17 @@ describe HasAttachment do
335
335
  @thing.photo_content_type == "image/jpeg"
336
336
  @thing.photo_file_size.should == File.size(test_path('test.jpg'))
337
337
  end
338
+
339
+ describe "when the record is saved" do
340
+ before do
341
+ instantiate
342
+ end
343
+
344
+ it "should not create any files" do
345
+ @thing.save
346
+ File.should_not exist(@thing.photo.path(:original))
347
+ end
348
+ end
338
349
  end
339
350
  end
340
351
 
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 0
9
- version: 0.1.0
8
+ - 1
9
+ version: 0.1.1
10
10
  platform: ruby
11
11
  authors:
12
12
  - George Ogata
@@ -14,7 +14,7 @@ autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
16
 
17
- date: 2010-06-23 00:00:00 -04:00
17
+ date: 2010-06-30 00:00:00 -04:00
18
18
  default_executable:
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency