bulldog 0.1.0 → 0.1.1

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