dragonfly 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of dragonfly might be problematic. Click here for more details.

Files changed (157) hide show
  1. data/.gitignore +2 -0
  2. data/.specopts +2 -0
  3. data/.yardopts +11 -5
  4. data/Gemfile +22 -0
  5. data/Gemfile.rails.2.3.5 +13 -0
  6. data/History.md +49 -0
  7. data/README.md +18 -28
  8. data/Rakefile +24 -36
  9. data/VERSION +1 -1
  10. data/config.ru +4 -1
  11. data/dragonfly.gemspec +85 -99
  12. data/extra_docs/Analysers.md +66 -30
  13. data/extra_docs/Caching.md +22 -0
  14. data/extra_docs/Configuration.md +116 -0
  15. data/extra_docs/DataStorage.md +114 -14
  16. data/extra_docs/Encoding.md +62 -37
  17. data/extra_docs/GeneralUsage.md +118 -0
  18. data/extra_docs/Generators.md +92 -0
  19. data/extra_docs/Heroku.md +51 -0
  20. data/extra_docs/Index.md +8 -9
  21. data/extra_docs/MimeTypes.md +18 -17
  22. data/extra_docs/Models.md +251 -0
  23. data/extra_docs/Processing.md +94 -70
  24. data/extra_docs/Rack.md +53 -0
  25. data/extra_docs/Rails2.md +44 -0
  26. data/extra_docs/Rails3.md +51 -0
  27. data/extra_docs/Sinatra.md +21 -0
  28. data/extra_docs/URLs.md +114 -0
  29. data/features/images.feature +6 -7
  30. data/features/no_processing.feature +0 -6
  31. data/features/rails_2.3.5.feature +1 -1
  32. data/features/rails_3.0.0.rc.feature +8 -0
  33. data/features/steps/dragonfly_steps.rb +14 -12
  34. data/features/steps/rails_steps.rb +20 -9
  35. data/features/support/env.rb +10 -11
  36. data/fixtures/files/app/views/albums/new.html.erb +4 -4
  37. data/fixtures/files/app/views/albums/show.html.erb +1 -1
  38. data/fixtures/files/features/manage_album_images.feature +1 -1
  39. data/fixtures/files/features/step_definitions/{album_steps.rb → image_steps.rb} +4 -3
  40. data/fixtures/files/features/support/paths.rb +2 -0
  41. data/fixtures/files/features/text_images.feature +7 -0
  42. data/fixtures/rails_3.0.0.rc/template.rb +21 -0
  43. data/irbrc.rb +2 -1
  44. data/lib/dragonfly.rb +4 -16
  45. data/lib/dragonfly/{active_record_extensions.rb → active_model_extensions.rb} +1 -1
  46. data/lib/dragonfly/active_model_extensions/attachment.rb +146 -0
  47. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/class_methods.rb +5 -6
  48. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/instance_methods.rb +1 -1
  49. data/lib/dragonfly/{active_record_extensions → active_model_extensions}/validations.rb +5 -9
  50. data/lib/dragonfly/analyser.rb +59 -0
  51. data/lib/dragonfly/analysis/file_command_analyser.rb +1 -1
  52. data/lib/dragonfly/analysis/r_magick_analyser.rb +46 -31
  53. data/lib/dragonfly/app.rb +138 -173
  54. data/lib/dragonfly/config/heroku.rb +19 -0
  55. data/lib/dragonfly/config/r_magick.rb +37 -0
  56. data/lib/dragonfly/config/{rails_defaults.rb → rails.rb} +6 -7
  57. data/lib/dragonfly/configurable.rb +30 -27
  58. data/lib/dragonfly/core_ext/object.rb +1 -1
  59. data/lib/dragonfly/data_storage/file_data_store.rb +59 -26
  60. data/lib/dragonfly/data_storage/mongo_data_store.rb +65 -0
  61. data/lib/dragonfly/data_storage/s3data_store.rb +31 -12
  62. data/lib/dragonfly/encoder.rb +13 -0
  63. data/lib/dragonfly/encoding/r_magick_encoder.rb +10 -19
  64. data/lib/dragonfly/endpoint.rb +43 -0
  65. data/lib/dragonfly/function_manager.rb +65 -0
  66. data/lib/dragonfly/{processing/r_magick_text_processor.rb → generation/r_magick_generator.rb} +25 -11
  67. data/lib/dragonfly/generator.rb +9 -0
  68. data/lib/dragonfly/job.rb +290 -0
  69. data/lib/dragonfly/job_builder.rb +39 -0
  70. data/lib/dragonfly/job_definitions.rb +26 -0
  71. data/lib/dragonfly/job_endpoint.rb +17 -0
  72. data/lib/dragonfly/loggable.rb +28 -0
  73. data/lib/dragonfly/middleware.rb +21 -14
  74. data/lib/dragonfly/processing/r_magick_processor.rb +71 -48
  75. data/lib/dragonfly/processor.rb +9 -0
  76. data/lib/dragonfly/r_magick_utils.rb +24 -0
  77. data/lib/dragonfly/rails/images.rb +10 -7
  78. data/lib/dragonfly/routed_endpoint.rb +42 -0
  79. data/lib/dragonfly/serializer.rb +32 -0
  80. data/lib/dragonfly/simple_cache.rb +23 -0
  81. data/lib/dragonfly/simple_endpoint.rb +64 -0
  82. data/lib/dragonfly/temp_object.rb +77 -45
  83. data/spec/argument_matchers.rb +7 -17
  84. data/spec/dragonfly/active_model_extensions/active_model_setup.rb +97 -0
  85. data/spec/dragonfly/active_model_extensions/active_record_setup.rb +85 -0
  86. data/spec/dragonfly/{active_record_extensions → active_model_extensions}/model_spec.rb +282 -244
  87. data/spec/dragonfly/active_model_extensions/spec_helper.rb +11 -0
  88. data/spec/dragonfly/analyser_spec.rb +123 -0
  89. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +2 -2
  90. data/spec/dragonfly/analysis/r_magick_analyser_spec.rb +10 -1
  91. data/spec/dragonfly/app_spec.rb +175 -69
  92. data/spec/dragonfly/configurable_spec.rb +14 -0
  93. data/spec/dragonfly/data_storage/data_store_spec.rb +36 -9
  94. data/spec/dragonfly/data_storage/file_data_store_spec.rb +61 -38
  95. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +18 -0
  96. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +34 -39
  97. data/spec/dragonfly/deprecation_spec.rb +20 -0
  98. data/spec/dragonfly/function_manager_spec.rb +154 -0
  99. data/spec/dragonfly/generation/r_magick_generator_spec.rb +119 -0
  100. data/spec/dragonfly/job_builder_spec.rb +37 -0
  101. data/spec/dragonfly/job_definitions_spec.rb +35 -0
  102. data/spec/dragonfly/job_endpoint_spec.rb +66 -0
  103. data/spec/dragonfly/job_spec.rb +605 -0
  104. data/spec/dragonfly/loggable_spec.rb +80 -0
  105. data/spec/dragonfly/middleware_spec.rb +37 -17
  106. data/spec/dragonfly/processing/r_magick_processor_spec.rb +182 -166
  107. data/spec/dragonfly/routed_endpoint_spec.rb +48 -0
  108. data/spec/dragonfly/serializer_spec.rb +61 -0
  109. data/spec/dragonfly/simple_cache_spec.rb +27 -0
  110. data/spec/dragonfly/simple_endpoint_spec.rb +78 -0
  111. data/spec/dragonfly/temp_object_spec.rb +154 -119
  112. data/spec/simple_matchers.rb +22 -0
  113. data/spec/spec_helper.rb +28 -4
  114. data/yard/templates/default/layout/html/layout.erb +18 -11
  115. metadata +89 -190
  116. data/config.rb +0 -5
  117. data/extra_docs/ActiveRecord.md +0 -196
  118. data/extra_docs/ExampleUseCases.md +0 -189
  119. data/extra_docs/GettingStarted.md +0 -114
  120. data/extra_docs/Shortcuts.md +0 -118
  121. data/extra_docs/UsingWithRails.md +0 -81
  122. data/features/rails_3.0.0.beta3.feature +0 -7
  123. data/fixtures/rails_3.0.0.beta3/template.rb +0 -16
  124. data/lib/dragonfly/active_record_extensions/attachment.rb +0 -170
  125. data/lib/dragonfly/analyser_list.rb +0 -9
  126. data/lib/dragonfly/analysis/base.rb +0 -10
  127. data/lib/dragonfly/belongs_to_app.rb +0 -24
  128. data/lib/dragonfly/config/heroku_rails_images.rb +0 -23
  129. data/lib/dragonfly/config/r_magick_images.rb +0 -69
  130. data/lib/dragonfly/config/r_magick_text.rb +0 -25
  131. data/lib/dragonfly/config/rails_images.rb +0 -13
  132. data/lib/dragonfly/data_storage/base.rb +0 -21
  133. data/lib/dragonfly/data_storage/base64_data_store.rb +0 -23
  134. data/lib/dragonfly/data_storage/transparent_data_store.rb +0 -21
  135. data/lib/dragonfly/delegatable.rb +0 -14
  136. data/lib/dragonfly/delegator.rb +0 -62
  137. data/lib/dragonfly/encoder_list.rb +0 -9
  138. data/lib/dragonfly/encoding/base.rb +0 -14
  139. data/lib/dragonfly/encoding/transparent_encoder.rb +0 -14
  140. data/lib/dragonfly/extended_temp_object.rb +0 -120
  141. data/lib/dragonfly/parameters.rb +0 -163
  142. data/lib/dragonfly/processing/base.rb +0 -10
  143. data/lib/dragonfly/processor_list.rb +0 -9
  144. data/lib/dragonfly/url_handler.rb +0 -147
  145. data/spec/dragonfly/active_record_extensions/attachment_spec.rb +0 -8
  146. data/spec/dragonfly/active_record_extensions/migration.rb +0 -42
  147. data/spec/dragonfly/active_record_extensions/models.rb +0 -6
  148. data/spec/dragonfly/active_record_extensions/spec_helper.rb +0 -24
  149. data/spec/dragonfly/belongs_to_app_spec.rb +0 -55
  150. data/spec/dragonfly/delegatable_spec.rb +0 -32
  151. data/spec/dragonfly/delegator_spec.rb +0 -145
  152. data/spec/dragonfly/extended_temp_object_spec.rb +0 -71
  153. data/spec/dragonfly/parameters_spec.rb +0 -298
  154. data/spec/dragonfly/processing/r_magick_text_processor_spec.rb +0 -84
  155. data/spec/dragonfly/url_handler_spec.rb +0 -247
  156. data/spec/dragonfly_spec.rb +0 -16
  157. data/spec/ginger_scenarios.rb +0 -13
@@ -1,163 +0,0 @@
1
- require 'rack'
2
-
3
- module Dragonfly
4
- class Parameters
5
-
6
- # Exceptions
7
- class InvalidParameters < RuntimeError; end
8
- class InvalidShortcut < RuntimeError; end
9
-
10
- # Class methods
11
- class << self
12
-
13
- include Configurable
14
-
15
- configurable_attr :default_processing_method
16
- configurable_attr :default_processing_options, {}
17
- configurable_attr :default_format
18
- configurable_attr :default_encoding, {}
19
-
20
- def new_with_defaults(attributes={})
21
- new({
22
- :processing_method => default_processing_method,
23
- :processing_options => default_processing_options,
24
- :format => default_format,
25
- :encoding => default_encoding
26
- }.merge(attributes))
27
- end
28
-
29
- def add_shortcut(*args, &block)
30
- if block
31
- block_shortcuts_of_length(args.length).unshift([args, block])
32
- else
33
- shortcut_name, attributes = args
34
- simple_shortcuts[shortcut_name] = attributes
35
- end
36
- end
37
- configuration_method :add_shortcut
38
-
39
- def hash_from_shortcut(*args)
40
- if attributes = matching_simple_shortcut(args)
41
- attributes
42
- elsif attributes = matching_block_shortcut(args)
43
- attributes
44
- else
45
- raise InvalidShortcut, "No shortcut was found matching (#{args.map{|a| a.inspect }.join(', ')})"
46
- end
47
- end
48
- configuration_method :hash_from_shortcut
49
-
50
- def from_shortcut(*args)
51
- new_with_defaults(hash_from_shortcut(*args))
52
- end
53
-
54
- def from_args(*args)
55
- if args.empty? then new_with_defaults
56
- elsif args.length == 1 && args.first.is_a?(Hash) then new_with_defaults(args.first)
57
- elsif args.length == 1 && args.first.is_a?(Parameters) then args.first.dup
58
- else from_shortcut(*args)
59
- end
60
- end
61
-
62
- private
63
-
64
- def simple_shortcuts
65
- @simple_shortcuts ||= {}
66
- end
67
-
68
- # block_shortcuts is actually a hash (keyed on the number of
69
- # arguments) of arrays (of argument lists)
70
- def block_shortcuts
71
- @block_shortcuts ||= {}
72
- end
73
-
74
- def block_shortcuts_of_length(arg_length)
75
- block_shortcuts[arg_length] ||= []
76
- end
77
-
78
- def matching_simple_shortcut(args)
79
- if args.length == 1 && args.first.is_a?(Symbol)
80
- simple_shortcuts[args.first]
81
- end
82
- end
83
-
84
- def matching_block_shortcut(args)
85
- block_shortcuts_of_length(args.length).each do |(args_to_match, block)|
86
- if all_args_match?(args, args_to_match)
87
- # If the block shortcut arg is a single regexp, then also yield the match data
88
- if args_to_match.length == 1 && args_to_match.first.is_a?(Regexp)
89
- match_data = args_to_match.first.match(args.first)
90
- return block.call(args.first, match_data)
91
- # ...otherwise just yield the args
92
- else
93
- return block.call(*args)
94
- end
95
- end
96
- end
97
- nil
98
- end
99
-
100
- def all_args_match?(args, args_to_match)
101
- (0...args.length).inject(true){|current_result, i| current_result &&= args_to_match[i] === args[i] }
102
- end
103
-
104
- end
105
-
106
- # Instance methods
107
-
108
- def initialize(attributes={})
109
- attributes = attributes.dup
110
- self.uid = attributes.delete(:uid)
111
- self.processing_method = attributes.delete(:processing_method)
112
- self.processing_options = attributes.delete(:processing_options) || {}
113
- self.format = attributes.delete(:format)
114
- self.encoding = attributes.delete(:encoding) || {}
115
- raise ArgumentError, "Parameters doesn't recognise the following parameters: #{attributes.keys.join(', ')}" if attributes.any?
116
- end
117
-
118
- attr_accessor :uid, :processing_method, :processing_options, :format, :encoding
119
-
120
- def [](attribute)
121
- send(attribute)
122
- end
123
-
124
- def []=(attribute, value)
125
- send("#{attribute}=", value)
126
- end
127
-
128
- def ==(other_parameters)
129
- self.to_hash == other_parameters.to_hash
130
- end
131
-
132
- def generate_sha(salt, sha_length)
133
- Digest::SHA1.hexdigest("#{to_sorted_array}#{salt}")[0...sha_length]
134
- end
135
-
136
- def unique_signature
137
- generate_sha('I like cheese', 10)
138
- end
139
-
140
- def to_hash
141
- {
142
- :uid => uid,
143
- :processing_method => processing_method,
144
- :processing_options => processing_options,
145
- :format => format,
146
- :encoding => encoding
147
- }
148
- end
149
-
150
- private
151
-
152
- def to_sorted_array
153
- [
154
- uid,
155
- format.to_s,
156
- processing_method.to_s,
157
- processing_options.sort{|a,b| a[0].to_s <=> b[0].to_s },
158
- encoding.sort{|a,b| a[0].to_s <=> b[0].to_s }
159
- ]
160
- end
161
-
162
- end
163
- end
@@ -1,10 +0,0 @@
1
- module Dragonfly
2
- module Processing
3
- class Base
4
-
5
- include BelongsToApp
6
- include Delegatable
7
-
8
- end
9
- end
10
- end
@@ -1,9 +0,0 @@
1
- module Dragonfly
2
- class ProcessorList
3
- include Delegator
4
-
5
- def initialize(app)
6
- @app = app
7
- end
8
- end
9
- end
@@ -1,147 +0,0 @@
1
- require 'digest/sha1'
2
- require 'rack'
3
-
4
- module Dragonfly
5
- class UrlHandler
6
-
7
- # Exceptions
8
- class IncorrectSHA < RuntimeError; end
9
- class SHANotGiven < RuntimeError; end
10
- class UnknownUrl < RuntimeError; end
11
-
12
- include Rack::Utils
13
- include Configurable
14
-
15
- MAPPINGS = {
16
- :processing_method => 'm',
17
- :processing_options => 'o',
18
- :encoding => 'e',
19
- :sha => 's'
20
- }
21
-
22
- configurable_attr :protect_from_dos_attacks, true
23
- configurable_attr :secret, 'This is a secret!'
24
- configurable_attr :sha_length, 16
25
- configurable_attr :path_prefix, ''
26
-
27
- def initialize(parameters_class = Parameters)
28
- @parameters_class = parameters_class
29
- end
30
-
31
- def url_for(uid, *args)
32
- parameters = parameters_class.from_args(*args)
33
- parameters.uid = uid
34
- parameters_to_url(parameters)
35
- end
36
-
37
- def url_to_parameters(path, query_string)
38
- path = unescape(path)
39
- validate_format!(path)
40
- path = remove_path_prefix(path)
41
- query = parse_nested_query(query_string)
42
- attributes = {
43
- :uid => extract_uid(path, query),
44
- :processing_method => extract_processing_method(path, query),
45
- :processing_options => extract_processing_options(path, query),
46
- :format => extract_format(path, query),
47
- :encoding => extract_encoding(path, query)
48
- }.reject{|k,v| v.nil? }
49
- parameters = parameters_class.new(attributes)
50
- validate_parameters(parameters, query)
51
- parameters
52
- end
53
-
54
- def parameters_to_url(parameters)
55
- query_string = [:processing_method, :processing_options, :encoding].map do |attribute|
56
- build_query(MAPPINGS[attribute] => parameters[attribute]) unless parameters[attribute].blank?
57
- end.compact.join('&')
58
- sha_string = "&#{MAPPINGS[:sha]}=#{sha_from_parameters(parameters)}" if protect_from_dos_attacks?
59
- ext = ".#{parameters.format}" if parameters.format
60
- url = "#{path_prefix}/#{escape_except_for_slashes(parameters.uid)}#{ext}?#{query_string}#{sha_string}"
61
- url.sub!(/\?$/,'')
62
- url
63
- end
64
-
65
- private
66
-
67
- def remove_path_prefix(path)
68
- path.sub(path_prefix, '')
69
- end
70
-
71
- def extract_uid(path, query)
72
- path.sub(/^\//,'').sub(/\.[^.]+$/, '')
73
- end
74
-
75
- def extract_processing_method(path, query)
76
- query[MAPPINGS[:processing_method]]
77
- end
78
-
79
- def extract_processing_options(path, query)
80
- processing_options = query[MAPPINGS[:processing_options]]
81
- symbolize_keys(processing_options) if processing_options
82
- end
83
-
84
- def extract_format(path, query)
85
- bits = path.sub(/^\//,'').split('.')
86
- bits.last if bits.length > 1
87
- end
88
-
89
- def extract_encoding(path, query)
90
- encoding = query[MAPPINGS[:encoding]]
91
- symbolize_keys(encoding) if encoding
92
- end
93
-
94
- attr_reader :parameters_class
95
-
96
- def symbolize_keys(hash)
97
- hash.inject({}) do |memo, (key, value)|
98
- memo[key.to_sym] = hash[key]
99
- memo
100
- end
101
- end
102
-
103
- def validate_parameters(parameters, query)
104
- if protect_from_dos_attacks?
105
- sha = query[MAPPINGS[:sha]]
106
- raise SHANotGiven, "You need to give a SHA" if sha.nil?
107
- raise IncorrectSHA, "The SHA parameter you gave is incorrect" if sha_from_parameters(parameters) != sha
108
- end
109
- end
110
-
111
- def protect_from_dos_attacks?
112
- protect_from_dos_attacks
113
- end
114
-
115
- def sha_from_parameters(parameters)
116
- parameters.generate_sha(secret, sha_length)
117
- end
118
-
119
-
120
- # Annoyingly, the 'build_query' in Rack::Utils doesn't seem to work
121
- # properly for nested parameters/arrays
122
- # Taken from http://github.com/sinatra/sinatra/commit/52658061d1205753a8afd2801845a910a6c01ffd
123
- def build_query(value, prefix = nil)
124
- case value
125
- when Array
126
- value.map { |v|
127
- build_query(v, "#{prefix}[]")
128
- } * "&"
129
- when Hash
130
- value.map { |k, v|
131
- build_query(v, prefix ? "#{prefix}[#{escape(k)}]" : escape(k))
132
- } * "&"
133
- else
134
- "#{prefix}=#{escape(value)}"
135
- end
136
- end
137
-
138
- def escape_except_for_slashes(string)
139
- string.split('/').map{|s| escape(s) }.join('/')
140
- end
141
-
142
- def validate_format!(path)
143
- raise UnknownUrl, "path '#{path}' not found" unless path =~ %r(^#{path_prefix}/[^.]+)
144
- end
145
-
146
- end
147
- end
@@ -1,8 +0,0 @@
1
- require File.dirname(__FILE__) + '/spec_helper'
2
-
3
- describe Dragonfly::ActiveRecordExtensions::Attachment do
4
-
5
- # See model_spec - tests are less brittle if doing mini integration tests
6
- # at the model level
7
-
8
- end
@@ -1,42 +0,0 @@
1
- # Seems to blow up on Rails 3 without this
2
- begin
3
- require 'active_support/all'
4
- rescue LoadError => e
5
- puts "Couldn't load activesupport: #{e}"
6
- end
7
-
8
- class MigrationForTest < ActiveRecord::Migration
9
-
10
- def self.up
11
- create_table :items, :force => true do |t|
12
- t.string :title
13
- t.string :preview_image_uid
14
- t.string :preview_image_some_analyser_method
15
- t.integer :preview_image_size
16
- t.string :preview_image_name
17
- t.string :preview_image_ext
18
- t.string :preview_image_blah_blah
19
- t.string :other_image_uid
20
- t.string :yet_another_image_uid
21
- t.string :otra_imagen_uid
22
- t.string :trailer_video_uid
23
- t.timestamps
24
- end
25
-
26
- create_table :cars do |t|
27
- t.string :image_uid
28
- t.string :reliant_image_uid
29
- t.string :type
30
- end
31
-
32
- create_table :photos do |t|
33
- t.string :image_uid
34
- end
35
-
36
- end
37
-
38
- def self.down
39
- drop_table :items
40
- end
41
-
42
- end
@@ -1,6 +0,0 @@
1
- class Item < ActiveRecord::Base
2
- end
3
- class Car < ActiveRecord::Base
4
- end
5
- class Photo < ActiveRecord::Base
6
- end
@@ -1,24 +0,0 @@
1
- require File.dirname(__FILE__) + '/../../spec_helper'
2
-
3
- require 'ginger'
4
- require 'active_record'
5
-
6
- DB_FILE = File.expand_path(File.dirname(__FILE__)+'/db.sqlite3')
7
-
8
- %w{migration models}.each do |file|
9
- require "#{File.dirname(__FILE__)}/#{file}"
10
- end
11
-
12
- Spec::Runner.configure do |config|
13
-
14
- config.before(:all) do
15
- FileUtils.rm_f(DB_FILE)
16
- ActiveRecord::Base.establish_connection(
17
- :adapter => "sqlite3",
18
- :database => DB_FILE
19
- )
20
- MigrationForTest.verbose = false
21
- MigrationForTest.up
22
- end
23
-
24
- end
@@ -1,55 +0,0 @@
1
- require File.dirname(__FILE__) + '/../spec_helper'
2
-
3
- class Testoast
4
- include Dragonfly::BelongsToApp
5
- end
6
-
7
- describe Dragonfly::BelongsToApp do
8
-
9
- before(:each) do
10
- @object = Testoast.new
11
- end
12
-
13
- describe "when the app is not set" do
14
- it "should raise an error if the app is accessed" do
15
- lambda{
16
- @object.app
17
- }.should raise_error(Dragonfly::BelongsToApp::NotConfigured)
18
- end
19
- it "should say it's not set" do
20
- @object.app_set?.should be_false
21
- end
22
- it "should still return a log" do
23
- @object.log.should be_a(Logger)
24
- end
25
- it "should cache the log" do
26
- @object.log.should == @object.log
27
- end
28
- it "should return the app's log if it's subsequently set" do
29
- @object.log.should be_a(Logger)
30
- @object.app = (app = mock('app', :log => mock))
31
- @object.log.should == app.log
32
- end
33
- end
34
-
35
- describe "when the app is set" do
36
- before(:each) do
37
- @app = mock('app', :log => mock)
38
- @object.app = @app
39
- end
40
-
41
- it "should return the app" do
42
- @object.app.should == @app
43
- end
44
-
45
- it "should return the app's log" do
46
- @object.log.should == @app.log
47
- end
48
-
49
- it "should say it's set" do
50
- @object.app_set?.should be_true
51
- end
52
-
53
- end
54
-
55
- end