dragonfly 0.9.15 → 1.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 (203) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +1 -8
  3. data/.travis.yml +11 -0
  4. data/Gemfile +1 -0
  5. data/History.md +52 -2
  6. data/LICENSE +1 -1
  7. data/README.md +38 -95
  8. data/dev/grid.jpg +0 -0
  9. data/dev/irbrc.rb +27 -0
  10. data/dev/rails_template.rb +38 -0
  11. data/dev/test.ru +56 -0
  12. data/dev/test_rails +19 -0
  13. data/dragonfly.gemspec +3 -21
  14. data/lib/dragonfly.rb +45 -44
  15. data/lib/dragonfly/app.rb +175 -96
  16. data/lib/dragonfly/configurable.rb +71 -170
  17. data/lib/dragonfly/content.rb +211 -0
  18. data/lib/dragonfly/core_ext/object.rb +1 -6
  19. data/lib/dragonfly/file_data_store.rb +197 -0
  20. data/lib/dragonfly/image_magick/analysers/image_properties.rb +23 -0
  21. data/lib/dragonfly/image_magick/generators/convert.rb +19 -0
  22. data/lib/dragonfly/image_magick/generators/plain.rb +26 -0
  23. data/lib/dragonfly/image_magick/generators/plasma.rb +25 -0
  24. data/lib/dragonfly/image_magick/generators/text.rb +127 -0
  25. data/lib/dragonfly/image_magick/plugin.rb +83 -0
  26. data/lib/dragonfly/image_magick/processors/convert.rb +29 -0
  27. data/lib/dragonfly/image_magick/processors/encode.rb +18 -0
  28. data/lib/dragonfly/image_magick/processors/thumb.rb +76 -0
  29. data/lib/dragonfly/job.rb +118 -134
  30. data/lib/dragonfly/job_endpoint.rb +2 -0
  31. data/lib/dragonfly/memory_data_store.rb +34 -0
  32. data/lib/dragonfly/middleware.rb +5 -3
  33. data/lib/dragonfly/{active_model_extensions.rb → model.rb} +5 -3
  34. data/lib/dragonfly/{active_model_extensions → model}/attachment.rb +40 -35
  35. data/lib/dragonfly/{active_model_extensions → model}/attachment_class_methods.rb +36 -40
  36. data/lib/dragonfly/model/class_methods.rb +109 -0
  37. data/lib/dragonfly/{active_model_extensions → model}/instance_methods.rb +2 -2
  38. data/lib/dragonfly/{active_model_extensions → model}/validations.rb +17 -12
  39. data/lib/dragonfly/railtie.rb +8 -6
  40. data/lib/dragonfly/register.rb +27 -0
  41. data/lib/dragonfly/response.rb +47 -52
  42. data/lib/dragonfly/routed_endpoint.rb +4 -0
  43. data/lib/dragonfly/serializer.rb +15 -5
  44. data/lib/dragonfly/server.rb +56 -29
  45. data/lib/dragonfly/shell.rb +12 -23
  46. data/lib/dragonfly/spec/data_store_examples.rb +64 -0
  47. data/lib/dragonfly/temp_object.rb +32 -47
  48. data/lib/dragonfly/url_attributes.rb +19 -22
  49. data/lib/dragonfly/url_mapper.rb +3 -0
  50. data/lib/dragonfly/utils.rb +12 -0
  51. data/lib/dragonfly/version.rb +1 -1
  52. data/lib/dragonfly/whitelist.rb +19 -0
  53. data/lib/rails/generators/dragonfly/USAGE +8 -0
  54. data/lib/rails/generators/dragonfly/dragonfly_generator.rb +24 -0
  55. data/lib/rails/generators/dragonfly/templates/initializer.rb.erb +27 -0
  56. data/samples/gif.gif +0 -0
  57. data/spec/dragonfly/app_spec.rb +270 -64
  58. data/spec/dragonfly/configurable_spec.rb +142 -418
  59. data/spec/dragonfly/content_spec.rb +353 -0
  60. data/spec/dragonfly/cookie_monster_spec.rb +2 -1
  61. data/spec/dragonfly/file_data_store_spec.rb +301 -0
  62. data/spec/dragonfly/image_magick/analysers/image_properties_spec.rb +20 -0
  63. data/spec/dragonfly/image_magick/generators/convert_spec.rb +19 -0
  64. data/spec/dragonfly/image_magick/generators/plain_spec.rb +50 -0
  65. data/spec/dragonfly/image_magick/generators/plasma_spec.rb +32 -0
  66. data/spec/dragonfly/image_magick/generators/text_spec.rb +77 -0
  67. data/spec/dragonfly/image_magick/plugin_spec.rb +131 -0
  68. data/spec/dragonfly/image_magick/processors/convert_spec.rb +56 -0
  69. data/spec/dragonfly/image_magick/processors/thumb_spec.rb +173 -0
  70. data/spec/dragonfly/job_endpoint_spec.rb +30 -73
  71. data/spec/dragonfly/job_spec.rb +280 -608
  72. data/spec/dragonfly/memory_data_store_spec.rb +20 -0
  73. data/spec/dragonfly/middleware_spec.rb +47 -27
  74. data/spec/dragonfly/{active_model_extensions → model}/model_spec.rb +331 -555
  75. data/spec/dragonfly/model/validations_spec.rb +196 -0
  76. data/spec/dragonfly/register_spec.rb +35 -0
  77. data/spec/dragonfly/routed_endpoint_spec.rb +6 -6
  78. data/spec/dragonfly/serializer_spec.rb +13 -15
  79. data/spec/dragonfly/server_spec.rb +122 -46
  80. data/spec/dragonfly/shell_spec.rb +43 -24
  81. data/spec/dragonfly/temp_object_spec.rb +69 -94
  82. data/spec/dragonfly/url_attributes_spec.rb +49 -0
  83. data/spec/dragonfly/utils_spec.rb +32 -0
  84. data/spec/dragonfly/whitelist_spec.rb +30 -0
  85. data/spec/dragonfly_spec.rb +43 -0
  86. data/spec/fixtures/deprecated_stored_content/eggs.bonus +1 -0
  87. data/spec/fixtures/deprecated_stored_content/eggs.bonus.meta +1 -0
  88. data/spec/functional/configuration_spec.rb +19 -0
  89. data/spec/functional/model_urls_spec.rb +43 -41
  90. data/spec/functional/remote_on_the_fly_spec.rb +14 -16
  91. data/spec/functional/shell_commands_spec.rb +24 -14
  92. data/spec/functional/to_response_spec.rb +10 -10
  93. data/spec/functional/urls_spec.rb +5 -3
  94. data/spec/spec_helper.rb +23 -28
  95. data/spec/support/argument_matchers.rb +7 -8
  96. data/spec/support/image_matchers.rb +14 -36
  97. data/spec/support/model_helpers.rb +97 -0
  98. data/spec/support/simple_matchers.rb +12 -0
  99. metadata +92 -393
  100. data/.yardopts +0 -29
  101. data/Rakefile +0 -36
  102. data/config.ru +0 -14
  103. data/docs.watchr +0 -1
  104. data/extra_docs/Analysers.md +0 -68
  105. data/extra_docs/Caching.md +0 -23
  106. data/extra_docs/Configuration.md +0 -149
  107. data/extra_docs/Couch.md +0 -49
  108. data/extra_docs/DataStorage.md +0 -226
  109. data/extra_docs/Encoding.md +0 -67
  110. data/extra_docs/ExampleUseCases.md +0 -116
  111. data/extra_docs/GeneralUsage.md +0 -105
  112. data/extra_docs/Generators.md +0 -68
  113. data/extra_docs/Heroku.md +0 -50
  114. data/extra_docs/ImageMagick.md +0 -136
  115. data/extra_docs/Index.md +0 -33
  116. data/extra_docs/MimeTypes.md +0 -40
  117. data/extra_docs/Models.md +0 -441
  118. data/extra_docs/Mongo.md +0 -42
  119. data/extra_docs/Processing.md +0 -77
  120. data/extra_docs/Rack.md +0 -52
  121. data/extra_docs/Rails2.md +0 -57
  122. data/extra_docs/Rails3.md +0 -56
  123. data/extra_docs/ServingRemotely.md +0 -104
  124. data/extra_docs/Sinatra.md +0 -25
  125. data/extra_docs/URLs.md +0 -203
  126. data/features/images.feature +0 -47
  127. data/features/no_processing.feature +0 -14
  128. data/features/rails.feature +0 -8
  129. data/features/steps/common_steps.rb +0 -8
  130. data/features/steps/dragonfly_steps.rb +0 -66
  131. data/features/steps/rails_steps.rb +0 -40
  132. data/features/support/env.rb +0 -13
  133. data/features/support/setup.rb +0 -41
  134. data/fixtures/rails/files/app/models/album.rb +0 -6
  135. data/fixtures/rails/files/app/views/albums/new.html.erb +0 -7
  136. data/fixtures/rails/files/app/views/albums/show.html.erb +0 -6
  137. data/fixtures/rails/files/config/initializers/dragonfly.rb +0 -4
  138. data/fixtures/rails/files/features/manage_album_images.feature +0 -38
  139. data/fixtures/rails/files/features/step_definitions/helper_steps.rb +0 -7
  140. data/fixtures/rails/files/features/step_definitions/image_steps.rb +0 -25
  141. data/fixtures/rails/files/features/step_definitions/web_steps.rb +0 -189
  142. data/fixtures/rails/files/features/support/paths.rb +0 -17
  143. data/fixtures/rails/files/features/text_images.feature +0 -7
  144. data/fixtures/rails/template.rb +0 -20
  145. data/irbrc.rb +0 -19
  146. data/lib/dragonfly/active_model_extensions/class_methods.rb +0 -98
  147. data/lib/dragonfly/analyser.rb +0 -58
  148. data/lib/dragonfly/analysis/file_command_analyser.rb +0 -33
  149. data/lib/dragonfly/analysis/image_magick_analyser.rb +0 -6
  150. data/lib/dragonfly/config/heroku.rb +0 -26
  151. data/lib/dragonfly/config/image_magick.rb +0 -6
  152. data/lib/dragonfly/config/rails.rb +0 -20
  153. data/lib/dragonfly/data_storage.rb +0 -11
  154. data/lib/dragonfly/data_storage/couch_data_store.rb +0 -83
  155. data/lib/dragonfly/data_storage/file_data_store.rb +0 -144
  156. data/lib/dragonfly/data_storage/mongo_data_store.rb +0 -96
  157. data/lib/dragonfly/data_storage/s3data_store.rb +0 -168
  158. data/lib/dragonfly/encoder.rb +0 -13
  159. data/lib/dragonfly/encoding/image_magick_encoder.rb +0 -6
  160. data/lib/dragonfly/function_manager.rb +0 -67
  161. data/lib/dragonfly/generation/image_magick_generator.rb +0 -6
  162. data/lib/dragonfly/generator.rb +0 -9
  163. data/lib/dragonfly/image_magick/analyser.rb +0 -53
  164. data/lib/dragonfly/image_magick/config.rb +0 -44
  165. data/lib/dragonfly/image_magick/encoder.rb +0 -57
  166. data/lib/dragonfly/image_magick/generator.rb +0 -147
  167. data/lib/dragonfly/image_magick/processor.rb +0 -114
  168. data/lib/dragonfly/image_magick/utils.rb +0 -46
  169. data/lib/dragonfly/image_magick_utils.rb +0 -4
  170. data/lib/dragonfly/job_builder.rb +0 -39
  171. data/lib/dragonfly/job_definitions.rb +0 -30
  172. data/lib/dragonfly/loggable.rb +0 -28
  173. data/lib/dragonfly/processing/image_magick_processor.rb +0 -6
  174. data/lib/dragonfly/processor.rb +0 -9
  175. data/lib/dragonfly/rails/images.rb +0 -32
  176. data/lib/dragonfly/simple_cache.rb +0 -23
  177. data/spec/dragonfly/active_model_extensions/spec_helper.rb +0 -95
  178. data/spec/dragonfly/analyser_spec.rb +0 -123
  179. data/spec/dragonfly/analysis/file_command_analyser_spec.rb +0 -49
  180. data/spec/dragonfly/data_storage/couch_data_store_spec.rb +0 -84
  181. data/spec/dragonfly/data_storage/file_data_store_spec.rb +0 -308
  182. data/spec/dragonfly/data_storage/mongo_data_store_spec.rb +0 -81
  183. data/spec/dragonfly/data_storage/s3_data_store_spec.rb +0 -277
  184. data/spec/dragonfly/data_storage/shared_data_store_examples.rb +0 -77
  185. data/spec/dragonfly/function_manager_spec.rb +0 -154
  186. data/spec/dragonfly/image_magick/analyser_spec.rb +0 -73
  187. data/spec/dragonfly/image_magick/encoder_spec.rb +0 -46
  188. data/spec/dragonfly/image_magick/generator_spec.rb +0 -178
  189. data/spec/dragonfly/image_magick/processor_spec.rb +0 -293
  190. data/spec/dragonfly/job_builder_spec.rb +0 -37
  191. data/spec/dragonfly/job_definitions_spec.rb +0 -57
  192. data/spec/dragonfly/loggable_spec.rb +0 -80
  193. data/spec/dragonfly/simple_cache_spec.rb +0 -27
  194. data/spec/dragonfly/url_attributes.rb +0 -47
  195. data/spec/functional/deprecations_spec.rb +0 -51
  196. data/spec/functional/image_magick_app_spec.rb +0 -27
  197. data/spec/test_imagemagick.ru +0 -49
  198. data/yard/handlers/configurable_attr_handler.rb +0 -38
  199. data/yard/setup.rb +0 -15
  200. data/yard/templates/default/fulldoc/html/css/common.css +0 -109
  201. data/yard/templates/default/layout/html/layout.erb +0 -93
  202. data/yard/templates/default/module/html/configuration_summary.erb +0 -31
  203. data/yard/templates/default/module/setup.rb +0 -17
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'dragonfly/spec/data_store_examples'
3
+
4
+ describe Dragonfly::MemoryDataStore do
5
+
6
+ before(:each) do
7
+ @data_store = Dragonfly::MemoryDataStore.new
8
+ end
9
+
10
+ it_should_behave_like 'data_store'
11
+
12
+ it "allows setting the uid" do
13
+ uid = @data_store.write(Dragonfly::Content.new(test_app, "Hello"), :uid => 'some_uid')
14
+ uid.should == 'some_uid'
15
+ data, meta = @data_store.read(uid)
16
+ data.should == 'Hello'
17
+ end
18
+
19
+ end
20
+
@@ -11,37 +11,57 @@ describe Dragonfly::Middleware do
11
11
  Rack::MockRequest.new(app).get(url)
12
12
  end
13
13
 
14
- before(:each) do
15
- @stack = Rack::Builder.new do
16
- use Dragonfly::Middleware, :images
17
- run dummy_rack_app
14
+ describe "using the default app" do
15
+ before(:each) do
16
+ @stack = Rack::Builder.new do
17
+ use Dragonfly::Middleware
18
+ run dummy_rack_app
19
+ end
18
20
  end
19
- end
20
21
 
21
- it "should pass through if the app returns X-Cascade: pass" do
22
- Dragonfly[:images].should_receive(:call).and_return(
23
- [404, {"Content-Type" => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
24
- )
25
- response = make_request(@stack, '/media/hello.png?howare=you')
26
- response.body.should == 'dummy_rack_app body'
27
- response.status.should == 200
28
- end
22
+ it "should pass through if the app returns X-Cascade: pass" do
23
+ Dragonfly.app.should_receive(:call).and_return(
24
+ [404, {"Content-Type" => 'text/plain', 'X-Cascade' => 'pass'}, ['Not found']]
25
+ )
26
+ response = make_request(@stack, '/media/hello.png?howare=you')
27
+ response.body.should == 'dummy_rack_app body'
28
+ response.status.should == 200
29
+ end
30
+
31
+ it "should return a 404 if the app returns a 404" do
32
+ Dragonfly.app.should_receive(:call).and_return(
33
+ [404, {"Content-Type" => 'text/plain'}, ['Not found']]
34
+ )
35
+ response = make_request(@stack, '/media/hello.png?howare=you')
36
+ response.status.should == 404
37
+ end
29
38
 
30
- it "should return a 404 if the app returns a 404" do
31
- Dragonfly[:images].should_receive(:call).and_return(
32
- [404, {"Content-Type" => 'text/plain'}, ['Not found']]
33
- )
34
- response = make_request(@stack, '/media/hello.png?howare=you')
35
- response.status.should == 404
39
+ it "should return as per the dragonfly app if the app returns a 200" do
40
+ Dragonfly.app.should_receive(:call).and_return(
41
+ [200, {"Content-Type" => 'text/plain'}, ['ABCD']]
42
+ )
43
+ response = make_request(@stack, '/media/hello.png?howare=you')
44
+ response.status.should == 200
45
+ response.body.should == 'ABCD'
46
+ end
36
47
  end
37
48
 
38
- it "should return as per the dragonfly app if the app returns a 200" do
39
- Dragonfly[:images].should_receive(:call).and_return(
40
- [200, {"Content-Type" => 'text/plain'}, ['ABCD']]
41
- )
42
- response = make_request(@stack, '/media/hello.png?howare=you')
43
- response.status.should == 200
44
- response.body.should == 'ABCD'
49
+ describe "using a custom app" do
50
+ before(:each) do
51
+ @stack = Rack::Builder.new do
52
+ use Dragonfly::Middleware, :images
53
+ run dummy_rack_app
54
+ end
55
+ end
56
+
57
+ it "should use the specified dragonfly app" do
58
+ Dragonfly.app.should_not_receive(:call)
59
+ Dragonfly.app(:images).should_receive(:call).and_return([
60
+ 200, {"Content-Type" => 'text/plain'}, ['booboo']
61
+ ])
62
+ response = make_request(@stack, '/media/hello.png?howare=you')
63
+ response.body.should == 'booboo'
64
+ end
45
65
  end
46
-
66
+
47
67
  end
@@ -1,98 +1,77 @@
1
- require 'dragonfly/active_model_extensions/spec_helper'
1
+ require 'spec_helper'
2
2
 
3
- describe Item do
3
+ # This spec is more of a functional spec for all of the model bits put together
4
+ describe "models" do
4
5
 
5
- def set_up_item_class(app=test_app)
6
- app.define_macro(MyModel, :image_accessor)
7
- Item.class_eval do
8
- image_accessor :preview_image
9
- end
6
+ before do
7
+ Dragonfly.app.use_datastore(:memory)
10
8
  end
11
9
 
12
- # See extra setup in models / initializer files
10
+ describe "using the module" do
11
+ it "adds 'dragonfly_accessor'" do
12
+ klass = Class.new do
13
+ extend Dragonfly::Model
14
+ dragonfly_accessor :hello
15
+ end
16
+ end
17
+ end
13
18
 
14
19
  describe "defining accessors" do
15
20
 
16
- let(:app1){ Dragonfly[:img] }
17
- let(:app2){ Dragonfly[:vid] }
18
-
19
- describe "attachment classes" do
20
- before(:each) do
21
- app1.define_macro(MyModel, :image_accessor)
22
- app2.define_macro(MyModel, :video_accessor)
23
- Item.class_eval do
24
- image_accessor :preview_image
25
- video_accessor :trailer_video
26
- end
27
- @classes = Item.dragonfly_attachment_classes
28
- @class1, @class2 = @classes
29
- end
30
-
31
- it "should return the attachment classes" do
32
- @class1.superclass.should == Dragonfly::ActiveModelExtensions::Attachment
33
- @class2.superclass.should == Dragonfly::ActiveModelExtensions::Attachment
21
+ before(:each) do
22
+ @app1, @app2 = Dragonfly.app(:img), Dragonfly.app(:vid)
23
+ app1, app2 = @app1, @app2
24
+ @model_class = new_model_class do
25
+ dragonfly_accessor :preview_image, :app => app1
26
+ dragonfly_accessor :trailer_video, :app => app2
34
27
  end
28
+ @classes = @model_class.dragonfly_attachment_classes
29
+ @class1, @class2 = @classes
30
+ end
35
31
 
36
- it "should associate the correct app with each class" do
37
- @class1.app.should == app1
38
- @class2.app.should == app2
39
- end
32
+ it "should return the attachment classes" do
33
+ @class1.superclass.should == Dragonfly::Model::Attachment
34
+ @class2.superclass.should == Dragonfly::Model::Attachment
35
+ end
40
36
 
41
- it "should associate the correct attribute with each class" do
42
- @class1.attribute.should == :preview_image
43
- @class2.attribute.should == :trailer_video
44
- end
37
+ it "should associate the correct app with each class" do
38
+ @class1.app.should == @app1
39
+ @class2.app.should == @app2
40
+ end
45
41
 
46
- it "should associate the correct model class with each class" do
47
- @class1.model_class.should == Item
48
- @class2.model_class.should == Item
49
- end
42
+ it "should associate the correct attribute with each class" do
43
+ @class1.attribute.should == :preview_image
44
+ @class2.attribute.should == :trailer_video
50
45
  end
51
46
 
52
- describe "included modules (e.g. Mongoid::Document)" do
47
+ it "should associate the correct model class with each class" do
48
+ @class1.model_class.should == @model_class
49
+ @class2.model_class.should == @model_class
50
+ end
53
51
 
54
- it "should work" do
55
- mongoid_document = Module.new
56
- app1.define_macro_on_include(mongoid_document, :dog_accessor)
57
- model_class = Class.new do
58
- def self.before_save(*args); end
59
- def self.before_destroy(*args); end
60
- include mongoid_document
61
- dog_accessor :doogie
62
- end
63
- klass = model_class.dragonfly_attachment_classes.first
64
- klass.app.should == app1
65
- klass.attribute.should == :doogie
52
+ it "should allow passing the app name as the :app value" do
53
+ klass = new_model_class do
54
+ dragonfly_accessor :egg_nog, :app => :vid
66
55
  end
56
+ klass.dragonfly_attachment_classes.first.app.should == @app2
57
+ end
67
58
 
68
- it "should work with two apps" do
69
- mongoid_document = Module.new
70
- app1.define_macro_on_include(mongoid_document, :image_accessor)
71
- app2.define_macro_on_include(mongoid_document, :video_accessor)
72
- model_class = Class.new do
73
- def self.before_save(*args); end
74
- def self.before_destroy(*args); end
75
- include mongoid_document
76
- image_accessor :doogie
77
- video_accessor :boogie
78
- end
79
- model_class.dragonfly_attachment_classes[0].app.should == app1
80
- model_class.dragonfly_attachment_classes[1].app.should == app2
59
+ it "should default the app to the default app" do
60
+ klass = new_model_class do
61
+ dragonfly_accessor :egg_nog
81
62
  end
82
-
63
+ klass.dragonfly_attachment_classes.first.app.should == Dragonfly.app
83
64
  end
84
-
85
65
  end
86
66
 
87
67
  describe "correctly defined" do
88
68
 
89
69
  before(:each) do
90
70
  @app = test_app
91
- @app.define_macro(MyModel, :image_accessor)
92
- Item.class_eval do
93
- image_accessor :preview_image
71
+ @item_class = new_model_class('Item', :preview_image_uid, :preview_image_size) do
72
+ dragonfly_accessor :preview_image
94
73
  end
95
- @item = Item.new
74
+ @item = @item_class.new
96
75
  end
97
76
 
98
77
  it "should provide a reader" do
@@ -111,7 +90,7 @@ describe Item do
111
90
  @item.preview_image_uid.should be_nil
112
91
  end
113
92
  it "should not try to store anything on save" do
114
- @app.datastore.should_not_receive(:store)
93
+ @app.datastore.should_not_receive(:write)
115
94
  @item.save!
116
95
  end
117
96
  it "should not try to destroy anything on save" do
@@ -140,8 +119,8 @@ describe Item do
140
119
  before(:each) do
141
120
  @item.preview_image_uid = 'some_known_uid'
142
121
  end
143
- it "should not try to retrieve any data" do
144
- @app.datastore.should_not_receive(:retrieve)
122
+ it "should not try to read any data" do
123
+ @app.datastore.should_not_receive(:read)
145
124
  @item.save!
146
125
  end
147
126
  it "should not try to destroy any data" do
@@ -149,7 +128,7 @@ describe Item do
149
128
  @item.save!
150
129
  end
151
130
  it "should not try to store any data" do
152
- @app.datastore.should_not_receive(:store)
131
+ @app.datastore.should_not_receive(:write)
153
132
  @item.save!
154
133
  end
155
134
  end
@@ -159,13 +138,13 @@ describe Item do
159
138
  @item.preview_image = "DATASTRING"
160
139
  end
161
140
  it "the reader should return an attachment" do
162
- @item.preview_image.should be_a(Dragonfly::ActiveModelExtensions::Attachment)
141
+ @item.preview_image.should be_a(Dragonfly::Model::Attachment)
163
142
  end
164
143
  it "the uid should be nil" do
165
144
  @item.preview_image_uid.should be_nil
166
145
  end
167
146
  it "should store the image when saved" do
168
- @app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), hash_including)
147
+ @app.datastore.should_receive(:write).with(content_with_data("DATASTRING"), hash_including)
169
148
  @item.save!
170
149
  end
171
150
  it "should not try to destroy anything on destroy" do
@@ -179,8 +158,8 @@ describe Item do
179
158
  before(:each) do
180
159
  @item.preview_image_uid = 'some_known_uid'
181
160
  end
182
- it "should not try to retrieve any data" do
183
- @app.datastore.should_not_receive(:retrieve)
161
+ it "should not try to read any data" do
162
+ @app.datastore.should_not_receive(:read)
184
163
  @item.save!
185
164
  end
186
165
  it "should not try to destroy any data" do
@@ -188,7 +167,7 @@ describe Item do
188
167
  @item.save!
189
168
  end
190
169
  it "should not try to store any data" do
191
- @app.datastore.should_not_receive(:store)
170
+ @app.datastore.should_not_receive(:write)
192
171
  @item.save!
193
172
  end
194
173
  end
@@ -199,7 +178,7 @@ describe Item do
199
178
 
200
179
  before(:each) do
201
180
  @item.preview_image = "DATASTRING"
202
- @app.datastore.should_receive(:store).with(a_temp_object_with_data("DATASTRING"), hash_including).once.and_return('some_uid')
181
+ @app.datastore.should_receive(:write).with(content_with_data("DATASTRING"), hash_including).once.and_return('some_uid')
203
182
  @item.save!
204
183
  end
205
184
 
@@ -207,7 +186,7 @@ describe Item do
207
186
  @item.preview_image_uid.should == 'some_uid'
208
187
  end
209
188
  it "should not try to store anything if saved again" do
210
- @app.datastore.should_not_receive(:store)
189
+ @app.datastore.should_not_receive(:write)
211
190
  @item.save!
212
191
  end
213
192
 
@@ -231,7 +210,7 @@ describe Item do
231
210
 
232
211
  describe "when accessed by a new model object" do
233
212
  before(:each) do
234
- @item = Item.find(@item.id)
213
+ @item = @item_class.find(@item.id)
235
214
  end
236
215
  it "should destroy the data on destroy" do
237
216
  @app.datastore.should_receive(:destroy).with(@item.preview_image_uid)
@@ -242,7 +221,7 @@ describe Item do
242
221
  describe "when something new is assigned" do
243
222
  before(:each) do
244
223
  @item.preview_image = "ANEWDATASTRING"
245
- @app.datastore.stub!(:store).and_return('some_uid')
224
+ @app.datastore.stub(:write).and_return('some_uid')
246
225
  end
247
226
  it "should set the uid to nil" do
248
227
  @item.preview_image_uid.should be_nil
@@ -264,7 +243,7 @@ describe Item do
264
243
  @item.save!
265
244
  end
266
245
  it "should store the new data when saved" do
267
- @app.datastore.should_receive(:store).with(a_temp_object_with_data("ANEWDATASTRING"), hash_including)
246
+ @app.datastore.should_receive(:write).with(content_with_data("ANEWDATASTRING"), hash_including)
268
247
  @item.save!
269
248
  end
270
249
  it "should destroy the old data on destroy" do
@@ -319,29 +298,15 @@ describe Item do
319
298
 
320
299
  end
321
300
 
322
- describe "destroy errors" do
323
- it "should log a warning if the data wasn't found on destroy" do
324
- @app.datastore.should_receive(:destroy).with('some_uid').and_raise(Dragonfly::DataStorage::DataNotFound)
325
- @app.log.should_receive(:warn)
326
- @item.destroy
327
- end
328
-
329
- it "should log a warning if the data wasn't found on destroy" do
330
- @app.datastore.should_receive(:destroy).with('some_uid').and_raise(Dragonfly::DataStorage::DestroyError)
331
- @app.log.should_receive(:warn)
332
- @item.destroy
333
- end
334
- end
335
-
336
301
  end
337
302
 
338
303
  describe "other types of assignment" do
339
304
  before(:each) do
340
- @app.generator.add :egg do
341
- "Gungedin"
305
+ @app.add_generator :egg do |content|
306
+ content.update "Gungedin"
342
307
  end
343
- @app.processor.add :doogie do |temp_object|
344
- temp_object.data.upcase
308
+ @app.add_processor :doogie do |content|
309
+ content.update content.data.upcase
345
310
  end
346
311
  end
347
312
 
@@ -363,8 +328,9 @@ describe Item do
363
328
 
364
329
  describe "assigning with another attachment" do
365
330
  before(:each) do
366
- Item.class_eval do
367
- image_accessor :other_image
331
+ @item_class.class_eval do
332
+ attr_accessor :other_image_uid
333
+ dragonfly_accessor :other_image
368
334
  end
369
335
  end
370
336
  it "should work like assigning the job" do
@@ -377,11 +343,8 @@ describe Item do
377
343
 
378
344
  describe "assigning by means of a bang method" do
379
345
  before(:each) do
380
- @app.processor.add :double do |temp_object|
381
- temp_object.data * 2
382
- end
383
- @app.encoder.add do |temp_object, format|
384
- temp_object.data.downcase + format.to_s
346
+ @app.add_processor :double do |content|
347
+ content.update content.data * 2
385
348
  end
386
349
  @item.preview_image = "HELLO"
387
350
  end
@@ -393,14 +356,10 @@ describe Item do
393
356
  @item.preview_image.process!(:double)
394
357
  @item.preview_image_size.should == 10
395
358
  end
396
- it "should work for encode" do
397
- @item.preview_image.encode!(:egg)
398
- @item.preview_image.data.should == 'helloegg'
399
- end
400
359
  it "should work repeatedly" do
401
- @item.preview_image.process!(:double).encode!(:egg)
402
- @item.preview_image.data.should == 'hellohelloegg'
403
- @item.preview_image_size.should == 13
360
+ @item.preview_image.process!(:double).process!(:double)
361
+ @item.preview_image.data.should == 'HELLOHELLOHELLOHELLO'
362
+ @item.preview_image_size.should == 20
404
363
  end
405
364
  end
406
365
  end
@@ -419,200 +378,29 @@ describe Item do
419
378
 
420
379
  end
421
380
 
422
- describe "validations" do
423
-
424
- before(:all) do
425
- @app = test_app
426
- @app.define_macro(MyModel, :image_accessor)
427
- end
428
-
429
- describe "validates_presence_of" do
430
-
431
- before(:all) do
432
- Item.class_eval do
433
- image_accessor :preview_image
434
- validates_presence_of :preview_image
435
- end
436
- end
437
-
438
- it "should be valid if set" do
439
- Item.new(:preview_image => "1234567890").should be_valid
440
- end
441
-
442
- it "should be invalid if not set" do
443
- Item.new.should_not be_valid
444
- end
445
-
446
- end
447
-
448
- describe "validates_size_of" do
449
-
450
- before(:all) do
451
- Item.class_eval do
452
- image_accessor :preview_image
453
- validates_size_of :preview_image, :within => (6..10)
454
- end
455
- end
456
-
457
- it "should be valid if ok" do
458
- Item.new(:preview_image => "1234567890").should be_valid
459
- end
460
-
461
- it "should be invalid if too small" do
462
- Item.new(:preview_image => "12345").should_not be_valid
463
- end
464
-
465
- end
466
-
467
- describe "validates_property" do
468
-
469
- before(:each) do
470
- @item = Item.new(:preview_image => "1234567890")
471
- end
472
-
473
- before(:all) do
474
- custom_analyser = Class.new do
475
- def mime_type(temp_object)
476
- case temp_object.data
477
- when "WRONG TYPE" then 'wrong/type'
478
- when "OTHER TYPE" then nil
479
- else 'how/special'
480
- end
481
- end
482
-
483
- def number_of_Gs(temp_object)
484
- temp_object.data.count('G')
485
- end
486
- end
487
- @app.analyser.register(custom_analyser)
488
-
489
- Item.class_eval do
490
- validates_property :mime_type, :of => :preview_image, :in => ['how/special', 'how/crazy'], :if => :its_friday
491
- validates_property :mime_type, :of => [:other_image, :yet_another_image], :as => 'how/special'
492
- validates_property :number_of_Gs, :of => :preview_image, :in => (0..2)
493
- validates_property :mime_type, :of => :otra_imagen, :in => ['que/pasa', 'illo/tio'], :message => "tipo de contenido incorrecto. Que chungo tio"
494
-
495
- image_accessor :preview_image
496
- image_accessor :other_image
497
- image_accessor :yet_another_image
498
- image_accessor :otra_imagen
499
-
500
- def its_friday
501
- true
502
- end
503
-
504
- end
505
- end
506
-
507
- it "should be valid if nil, if not validated on presence (even with validates_property)" do
508
- @item.other_image = nil
509
- @item.should be_valid
510
- end
511
-
512
- it "should be invalid if the property is nil" do
513
- @item.preview_image = "OTHER TYPE"
514
- @item.should_not be_valid
515
- @item.errors[:preview_image].should == ["mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was 'application/octet-stream'"]
516
- end
517
-
518
- it "should be invalid if the property is wrong" do
519
- @item.preview_image = "WRONG TYPE"
520
- @item.should_not be_valid
521
- @item.errors[:preview_image].should == ["mime type is incorrect. It needs to be one of 'how/special', 'how/crazy', but was 'wrong/type'"]
522
- end
523
-
524
- it "should work for a range" do
525
- @item.preview_image = "GOOGLE GUM"
526
- @item.should_not be_valid
527
- @item.errors[:preview_image].should == ["number of gs is incorrect. It needs to be between 0 and 2, but was '3'"]
528
- end
529
-
530
- it "should validate individually" do
531
- @item.other_image = "1234567"
532
- @item.yet_another_image = "WRONG TYPE"
533
- @item.should_not be_valid
534
- @item.errors[:other_image].should == []
535
- @item.errors[:yet_another_image].should == ["mime type is incorrect. It needs to be 'how/special', but was 'wrong/type'"]
536
- end
537
-
538
- it "should include standard extra options like 'if' on mime type validation" do
539
- @item.should_receive(:its_friday).and_return(false)
540
- @item.preview_image = "WRONG TYPE"
541
- @item.should be_valid
542
- end
543
-
544
- it "should allow case sensitivity to be turned off when :as is specified" do
545
- @item.should_receive(:its_friday).and_return(false)
546
- Item.class_eval do
547
- validates_property :mime_type, :of => :preview_image, :as => 'WronG/TypE', :case_sensitive => false
548
- end
549
- @item.preview_image = "WRONG TYPE"
550
- @item.should be_valid
551
- end
552
-
553
- it "should allow case sensitivity to be turned off when :in is specified" do
554
- @item.should_receive(:its_friday).and_return(false)
555
- Item.class_eval do
556
- validates_property :mime_type, :of => :preview_image, :in => ['WronG/TypE'], :case_sensitive => false
557
- end
558
- @item.preview_image = "WRONG TYPE"
559
- @item.should be_valid
560
- end
561
-
562
- it "should require either :as or :in as an argument" do
563
- lambda{
564
- Item.class_eval do
565
- validates_property :mime_type, :of => :preview_image
566
- end
567
- }.should raise_error(ArgumentError)
568
- end
569
-
570
- it "should require :of as an argument" do
571
- lambda{
572
- Item.class_eval do
573
- validates_property :mime_type, :as => 'hi/there'
574
- end
575
- }.should raise_error(ArgumentError)
576
- end
577
-
578
- it "should allow for custom messages" do
579
- @item.otra_imagen = "WRONG TYPE"
580
- @item.should_not be_valid
581
- @item.errors[:otra_imagen].should == ["tipo de contenido incorrecto. Que chungo tio"]
582
- end
583
-
584
- it "should allow for custom messages including access to the property name and expected/allowed values" do
585
- @item.should_receive(:its_friday).and_return(false) # hack to get rid of other validation
586
- Item.class_eval do
587
- validates_property :mime_type, :of => :preview_image, :as => 'one/thing',
588
- :message => proc{|actual, model| "Unlucky #{model.title}! Was #{actual}" }
589
- end
590
- @item.title = 'scubby'
591
- @item.preview_image = "WRONG TYPE"
592
- @item.should_not be_valid
593
- @item.errors[:preview_image].should == ["Unlucky scubby! Was wrong/type"]
594
- end
595
-
596
- end
597
-
598
- end
599
-
600
381
  describe "extra properties" do
601
382
 
602
383
  before(:each) do
603
384
  @app = test_app
604
- custom_analyser = Class.new do
605
- def some_analyser_method(temp_object)
606
- "abc" + temp_object.data[0..0]
607
- end
608
- def number_of_As(temp_object); temp_object.data.count('A'); end
385
+ @app.add_analyser :some_analyser_method do |content|
386
+ "abc" + content.data[0..0]
387
+ end
388
+ @app.add_analyser :number_of_As do |content|
389
+ content.data.count('A')
609
390
  end
610
- @app.analyser.register(custom_analyser)
611
- @app.define_macro(MyModel, :image_accessor)
612
- Item.class_eval do
613
- image_accessor :preview_image
391
+
392
+ @item_class = new_model_class('Item',
393
+ :preview_image_uid,
394
+ :preview_image_some_analyser_method,
395
+ :preview_image_blah_blah,
396
+ :preview_image_size,
397
+ :preview_image_name,
398
+ :other_image_uid
399
+ ) do
400
+ dragonfly_accessor :preview_image
401
+ dragonfly_accessor :other_image
614
402
  end
615
- @item = Item.new
403
+ @item = @item_class.new
616
404
  end
617
405
 
618
406
  describe "magic attributes" do
@@ -652,32 +440,17 @@ describe Item do
652
440
 
653
441
  it "should store the original file name if it exists" do
654
442
  data = 'jasdlkf sadjl'
655
- data.stub!(:original_filename).and_return('hello.png')
443
+ data.stub(:original_filename).and_return('hello.png')
656
444
  @item.preview_image = data
657
445
  @item.preview_image_name.should == 'hello.png'
658
446
  end
659
447
 
660
- end
661
-
662
- describe "meta from magic attributes" do
663
-
664
- it "should store the meta for the original file name if it exists" do
665
- data = 'jasdlkf sadjl'
666
- data.stub!(:original_filename).and_return('hello.png')
667
- @item.preview_image = data
668
- @item.preview_image.meta[:name].should == 'hello.png'
669
- end
670
-
671
- it "should include magic attributes in the saved meta" do
672
- @item.preview_image = '123'
673
- @item.save!
674
- @app.fetch(@item.preview_image_uid).meta[:some_analyser_method].should == 'abc1'
675
- end
676
-
677
- it "should include the size in the saved meta" do
448
+ it "sets to nil if the analysis method blows up" do
449
+ @app.add_analyser :some_analyser_method do |content|
450
+ raise "oh dear"
451
+ end
678
452
  @item.preview_image = '123'
679
- @item.save!
680
- @app.fetch(@item.preview_image_uid).meta[:size].should == 3
453
+ @item.preview_image_some_analyser_method.should be_nil
681
454
  end
682
455
 
683
456
  end
@@ -706,16 +479,14 @@ describe Item do
706
479
 
707
480
  describe "from a new model object" do
708
481
  before(:each) do
709
- @app.datastore.stub!(:store).and_return('my_uid')
710
- item = Item.create!(:preview_image => 'DATASTRING')
711
- @item = Item.find(item.id)
482
+ item = @item_class.create!(:preview_image => 'DATASTRING')
483
+ @item = @item_class.find(item.id)
712
484
  end
713
485
  it "should load the content then delegate the method" do
714
- @app.datastore.should_receive(:retrieve).with('my_uid').and_return(['DATASTRING', {}])
715
486
  @item.preview_image.number_of_As.should == 2
716
487
  end
717
488
  it "should use the magic attribute if there is one, and not load the content" do
718
- @app.datastore.should_not_receive(:retrieve)
489
+ @app.datastore.should_not_receive(:read)
719
490
  @item.should_receive(:preview_image_some_analyser_method).at_least(:once).and_return('result yo')
720
491
  @item.preview_image.some_analyser_method.should == 'result yo'
721
492
  end
@@ -748,23 +519,10 @@ describe Item do
748
519
  end
749
520
  end
750
521
 
751
- describe "job shortcuts" do
752
- before(:each) do
753
- @app.job :bacon do
754
- process :breakfast
755
- end
756
- @item = Item.new :preview_image => 'gurg'
757
- end
758
- it "should add job shortcuts for that app" do
759
- job = @item.preview_image.bacon
760
- job.steps.first.should be_a(Dragonfly::Job::Process)
761
- end
762
- end
763
-
764
522
  describe "setting things on the attachment" do
765
523
 
766
524
  before(:each) do
767
- @item = Item.new
525
+ @item = @item_class.new
768
526
  end
769
527
 
770
528
  describe "name" do
@@ -787,29 +545,19 @@ describe Item do
787
545
  end
788
546
 
789
547
  describe "meta" do
790
- before(:each) do
791
- @item.preview_image = "Hello all"
792
- @item.preview_image.meta = {:slime => 'balls'}
793
- end
794
- it "should allow for setting the meta" do
795
- @item.preview_image.meta.should == {:slime => 'balls'}
796
- end
797
- it "should allow for updating the meta" do
798
- @item.preview_image.meta[:numb] = 'nuts'
799
- @item.preview_image.meta.should == {:slime => 'balls', :numb => 'nuts'}
548
+ before :each do
549
+ @item.preview_image = 'hello'
800
550
  end
801
- it "should return the meta" do
802
- (@item.preview_image.meta = {:doogs => 'boogs'}).should == {:doogs => 'boogs'}
551
+ it "should include meta info about the model by default" do
552
+ @item.preview_image.meta.should include_hash('model_class' => 'Item', 'model_attachment' => 'preview_image')
803
553
  end
804
- it "should save it correctly" do
805
- @item.save!
806
- item = Item.find(@item.id)
807
- item.preview_image.meta.should include_hash(:slime => 'balls')
554
+ it "provides accessors" do
555
+ @item.preview_image.meta = {'slime' => 'balls'}
556
+ @item.preview_image.meta.should == {'slime' => 'balls'}
808
557
  end
809
- it "should include meta info about the model" do
810
- @item.save!
811
- item = Item.find(@item.id)
812
- item.preview_image.meta.should include_hash(:model_class => 'Item', :model_attachment => :preview_image)
558
+ it "provides add_meta" do
559
+ @item.preview_image.add_meta('sum' => 'ting').should == @item.preview_image
560
+ @item.preview_image.meta['sum'].should == 'ting'
813
561
  end
814
562
  end
815
563
 
@@ -821,25 +569,23 @@ describe Item do
821
569
 
822
570
  before(:all) do
823
571
  @app = test_app
824
- @app2 = test_app
825
- @app.define_macro(MyModel, :image_accessor)
826
- @app2.define_macro(MyModel, :egg_accessor)
827
- Car.class_eval do
828
- image_accessor :image
572
+ @app2 = test_app(:two)
573
+ @car_class = new_model_class('Car', :image_uid, :reliant_image_uid) do
574
+ dragonfly_accessor :image
829
575
  end
830
- Photo.class_eval do
831
- egg_accessor :image
576
+ @photo_class = new_model_class('Photo', :image_uid) do
577
+ dragonfly_accessor :image, :app => :two
832
578
  end
833
579
 
834
- @base_class = Car
835
- class ReliantRobin < Car; image_accessor :reliant_image; end
580
+ @base_class = @car_class
581
+ class ReliantRobin < @car_class; dragonfly_accessor :reliant_image; end
836
582
  @subclass = ReliantRobin
837
- class ReliantRobinWithModule < Car
583
+ class ReliantRobinWithModule < @car_class
838
584
  include Module.new
839
- image_accessor :reliant_image
585
+ dragonfly_accessor :reliant_image
840
586
  end
841
587
  @subclass_with_module = ReliantRobinWithModule
842
- @unrelated_class = Photo
588
+ @unrelated_class = @photo_class
843
589
  end
844
590
 
845
591
  it "should allow assigning base class accessors" do
@@ -861,7 +607,7 @@ describe Item do
861
607
  @subclass_with_module.create! :reliant_image => 'blah'
862
608
  end
863
609
  it "should return the correct attachment classes for the base class" do
864
- @base_class.dragonfly_attachment_classes.should match_attachment_classes([[Car, :image, @app]])
610
+ @base_class.dragonfly_attachment_classes.should match_attachment_classes([[@car_class, :image, @app]])
865
611
  end
866
612
  it "should return the correct attachment classes for the subclass" do
867
613
  @subclass.dragonfly_attachment_classes.should match_attachment_classes([[ReliantRobin, :image, @app], [ReliantRobin, :reliant_image, @app]])
@@ -870,14 +616,16 @@ describe Item do
870
616
  @subclass_with_module.dragonfly_attachment_classes.should match_attachment_classes([[ReliantRobinWithModule, :image, @app], [ReliantRobinWithModule, :reliant_image, @app]])
871
617
  end
872
618
  it "should return the correct attachment classes for a class from a different hierarchy" do
873
- @unrelated_class.dragonfly_attachment_classes.should match_attachment_classes([[Photo, :image, @app2]])
619
+ @unrelated_class.dragonfly_attachment_classes.should match_attachment_classes([[@photo_class, :image, @app2]])
874
620
  end
875
621
  end
876
622
 
877
623
  describe "setting the url" do
878
624
  before(:each) do
879
- set_up_item_class
880
- @item = Item.new
625
+ @item_class = new_model_class('Item', :preview_image_uid, :preview_image_name) do
626
+ dragonfly_accessor :preview_image
627
+ end
628
+ @item = @item_class.new
881
629
  stub_request(:get, "http://some.url/yo.png").to_return(:body => "aaaaayo")
882
630
  end
883
631
 
@@ -892,7 +640,7 @@ describe Item do
892
640
  it "should have set the name" do
893
641
  @item.preview_image_url = 'http://some.url/yo.png'
894
642
  @item.preview_image_name.should == 'yo.png'
895
- @item.preview_image.meta[:name].should == 'yo.png'
643
+ @item.preview_image.meta['name'].should == 'yo.png'
896
644
  end
897
645
  [nil, ""].each do |value|
898
646
  it "should do nothing if set with #{value.inspect}" do
@@ -904,8 +652,10 @@ describe Item do
904
652
 
905
653
  describe "removing the accessor with e.g. a form" do
906
654
  before(:each) do
907
- set_up_item_class
908
- @item = Item.new
655
+ @item_class = new_model_class('Item', :preview_image_uid) do
656
+ dragonfly_accessor :preview_image
657
+ end
658
+ @item = @item_class.new
909
659
  @item.preview_image = "something"
910
660
  end
911
661
 
@@ -958,14 +708,14 @@ describe Item do
958
708
 
959
709
  before(:each) do
960
710
  @app = test_app
961
- @app.define_macro(MyModel, :image_accessor)
711
+ @item_class = new_model_class('Item', :preview_image_uid, :title)
962
712
  end
963
713
 
964
714
  describe "as a block" do
965
715
 
966
716
  def set_after_assign(*args, &block)
967
- Item.class_eval do
968
- image_accessor :preview_image do
717
+ @item_class.class_eval do
718
+ dragonfly_accessor :preview_image do
969
719
  after_assign(*args, &block)
970
720
  end
971
721
  end
@@ -974,28 +724,28 @@ describe Item do
974
724
  it "should call it after assign" do
975
725
  x = nil
976
726
  set_after_assign{ x = 3 }
977
- Item.new.preview_image = "hello"
727
+ @item_class.new.preview_image = "hello"
978
728
  x.should == 3
979
729
  end
980
730
 
981
731
  it "should not call it after unassign" do
982
732
  x = nil
983
733
  set_after_assign{ x = 3 }
984
- Item.new.preview_image = nil
734
+ @item_class.new.preview_image = nil
985
735
  x.should be_nil
986
736
  end
987
737
 
988
738
  it "should yield the attachment" do
989
739
  x = nil
990
740
  set_after_assign{|a| x = a.data }
991
- Item.new.preview_image = "discussion"
741
+ @item_class.new.preview_image = "discussion"
992
742
  x.should == "discussion"
993
743
  end
994
744
 
995
745
  it "should evaluate in the model context" do
996
746
  x = nil
997
747
  set_after_assign{ x = title.upcase }
998
- item = Item.new
748
+ item = @item_class.new
999
749
  item.title = "big"
1000
750
  item.preview_image = "jobs"
1001
751
  x.should == "BIG"
@@ -1003,7 +753,7 @@ describe Item do
1003
753
 
1004
754
  it "should allow passing a symbol for calling a model method" do
1005
755
  set_after_assign :set_title
1006
- item = Item.new
756
+ item = @item_class.new
1007
757
  def item.set_title; self.title = 'duggen'; end
1008
758
  item.preview_image = "jobs"
1009
759
  item.title.should == "duggen"
@@ -1011,7 +761,7 @@ describe Item do
1011
761
 
1012
762
  it "should allow passing multiple symbols" do
1013
763
  set_after_assign :set_title, :upcase_title
1014
- item = Item.new
764
+ item = @item_class.new
1015
765
  def item.set_title; self.title = 'doobie'; end
1016
766
  def item.upcase_title; self.title.upcase!; end
1017
767
  item.preview_image = "jobs"
@@ -1020,7 +770,7 @@ describe Item do
1020
770
 
1021
771
  it "should not re-trigger callbacks (causing an infinite loop)" do
1022
772
  set_after_assign{|a| self.preview_image = 'dogman' }
1023
- item = Item.new
773
+ item = @item_class.new
1024
774
  item.preview_image = "hello"
1025
775
  end
1026
776
 
@@ -1031,13 +781,12 @@ describe Item do
1031
781
  describe "after_unassign" do
1032
782
  before(:each) do
1033
783
  @app = test_app
1034
- @app.define_macro(MyModel, :image_accessor)
1035
- Item.class_eval do
1036
- image_accessor :preview_image do
784
+ @item_class = new_model_class('Item', :preview_image_uid, :title) do
785
+ dragonfly_accessor :preview_image do
1037
786
  after_unassign{ self.title = 'unassigned' }
1038
787
  end
1039
788
  end
1040
- @item = Item.new :title => 'yo'
789
+ @item = @item_class.new :title => 'yo'
1041
790
  end
1042
791
 
1043
792
  it "should not call it after assign" do
@@ -1054,19 +803,18 @@ describe Item do
1054
803
  describe "copy_to" do
1055
804
  before(:each) do
1056
805
  @app = test_app
1057
- @app.define_macro(MyModel, :image_accessor)
1058
- @app.processor.add(:append) do |temp_object, string|
1059
- temp_object.data + string
806
+ @app.add_processor(:append) do |content, string|
807
+ content.update(content.data + string)
1060
808
  end
1061
- Item.class_eval do
1062
- image_accessor :preview_image do
809
+ @item_class = new_model_class('Item', :preview_image_uid, :other_image_uid, :yet_another_image_uid, :title) do
810
+ dragonfly_accessor :preview_image do
1063
811
  copy_to(:other_image){|a| a.process(:append, title) }
1064
812
  copy_to(:yet_another_image)
1065
813
  end
1066
- image_accessor :other_image
1067
- image_accessor :yet_another_image
814
+ dragonfly_accessor :other_image
815
+ dragonfly_accessor :yet_another_image
1068
816
  end
1069
- @item = Item.new :title => 'yo'
817
+ @item = @item_class.new :title => 'yo'
1070
818
  end
1071
819
 
1072
820
  it "should copy to the other image when assigned" do
@@ -1089,131 +837,108 @@ describe Item do
1089
837
 
1090
838
  end
1091
839
 
1092
- describe "storage_opts" do
840
+ describe "storage_options" do
1093
841
 
1094
- def set_storage_opts(*args, &block)
1095
- Item.class_eval do
1096
- image_accessor :preview_image do
1097
- storage_opts(*args, &block)
842
+ def set_storage_options(*args, &block)
843
+ @item_class.class_eval do
844
+ dragonfly_accessor :preview_image do
845
+ storage_options(*args, &block)
1098
846
  end
1099
847
  end
1100
848
  end
1101
849
 
1102
850
  before(:each) do
1103
851
  @app = test_app
1104
- @app.define_macro(MyModel, :image_accessor)
852
+ @item_class = new_model_class('Item', :preview_image_uid, :title)
1105
853
  end
1106
854
 
1107
855
  it "should send the specified options to the datastore on store" do
1108
- set_storage_opts :egg => 'head'
1109
- item = Item.new :preview_image => 'hello'
1110
- @app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'head'))
856
+ set_storage_options :egg => 'head'
857
+ item = @item_class.new :preview_image => 'hello'
858
+ @app.datastore.should_receive(:write).with(anything, hash_including(:egg => 'head'))
1111
859
  item.save!
1112
860
  end
1113
861
 
1114
862
  it "should allow putting in a proc" do
1115
- set_storage_opts{ {:egg => 'numb'} }
1116
- item = Item.new :preview_image => 'hello'
1117
- @app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'numb'))
863
+ set_storage_options{ {:egg => 'numb'} }
864
+ item = @item_class.new :preview_image => 'hello'
865
+ @app.datastore.should_receive(:write).with(anything, hash_including(:egg => 'numb'))
1118
866
  item.save!
1119
867
  end
1120
868
 
1121
869
  it "should yield the attachment and exec in model context" do
1122
- set_storage_opts{|a| {:egg => (a.data + title)} }
1123
- item = Item.new :title => 'lump', :preview_image => 'hello'
1124
- @app.datastore.should_receive(:store).with(anything, hash_including(:egg => 'hellolump'))
870
+ set_storage_options{|a| {:egg => (a.data + title)} }
871
+ item = @item_class.new :title => 'lump', :preview_image => 'hello'
872
+ @app.datastore.should_receive(:write).with(anything, hash_including(:egg => 'hellolump'))
1125
873
  item.save!
1126
874
  end
1127
875
 
1128
876
  it "should allow giving it a method symbol" do
1129
- set_storage_opts :special_ops
1130
- item = Item.new :preview_image => 'hello'
877
+ set_storage_options :special_ops
878
+ item = @item_class.new :preview_image => 'hello'
1131
879
  def item.special_ops; {:a => 1}; end
1132
- @app.datastore.should_receive(:store).with(anything, hash_including(:a => 1))
880
+ @app.datastore.should_receive(:write).with(anything, hash_including(:a => 1))
1133
881
  item.save!
1134
882
  end
1135
883
 
1136
884
  it "should allow setting more than once" do
1137
- Item.class_eval do
1138
- image_accessor :preview_image do
1139
- storage_opts{{ :a => title, :b => 'dumple' }}
1140
- storage_opts{{ :b => title.upcase, :c => 'digby' }}
885
+ @item_class.class_eval do
886
+ dragonfly_accessor :preview_image do
887
+ storage_options{{ :a => title, :b => 'dumple' }}
888
+ storage_options{{ :b => title.upcase, :c => 'digby' }}
1141
889
  end
1142
890
  end
1143
- item = Item.new :title => 'lump', :preview_image => 'hello'
1144
- @app.datastore.should_receive(:store).with(anything, hash_including(
891
+ item = @item_class.new :title => 'lump', :preview_image => 'hello'
892
+ @app.datastore.should_receive(:write).with(anything, hash_including(
1145
893
  :a => 'lump', :b => 'LUMP', :c => 'digby'
1146
894
  ))
1147
895
  item.save!
1148
896
  end
1149
- end
1150
-
1151
- describe "storage_path, etc." do
1152
897
 
1153
- def set_storage_path(path=nil, &block)
1154
- Item.class_eval do
1155
- image_accessor :preview_image do
1156
- storage_path(path, &block)
1157
- end
1158
- def monkey
1159
- "mr/#{title}/monkey"
898
+ it "gives a deprecation warning for storage_xxx methods" do
899
+ expect {
900
+ @item_class.class_eval do
901
+ dragonfly_accessor :preview_image do
902
+ storage_egg :fried
903
+ end
1160
904
  end
1161
- end
905
+ }.to raise_error(/deprecated/)
1162
906
  end
907
+ end
1163
908
 
1164
- before(:each) do
909
+ describe "default" do
910
+ before do
1165
911
  @app = test_app
1166
- @app.define_macro(MyModel, :image_accessor)
1167
- end
1168
-
1169
- it "should allow setting as a string" do
1170
- set_storage_path 'always/the/same'
1171
- item = Item.new :preview_image => 'bilbo'
1172
- @app.datastore.should_receive(:store).with(anything, hash_including(
1173
- :path => 'always/the/same'
1174
- ))
1175
- item.save!
912
+ @item_class = new_model_class('Item', :image_uid) do
913
+ dragonfly_accessor :image do
914
+ default SAMPLES_DIR.join('beach.jpg')
915
+ end
916
+ end
917
+ @item = @item_class.new
1176
918
  end
1177
919
 
1178
- it "should allow setting as a symbol" do
1179
- set_storage_path :monkey
1180
- item = Item.new :title => 'billy'
1181
- item.preview_image = 'bilbo'
1182
- @app.datastore.should_receive(:store).with(anything, hash_including(
1183
- :path => 'mr/billy/monkey'
1184
- ))
1185
- item.save!
920
+ it "gives a default image when not set" do
921
+ @item.image.name.should == 'beach.jpg'
922
+ @item.image.size.should == 25932
1186
923
  end
1187
924
 
1188
- it "should allow setting as a block" do
1189
- set_storage_path{|a| "#{a.data}/megs/#{title}" }
1190
- item = Item.new :title => 'billy'
1191
- item.preview_image = 'bilbo'
1192
- @app.datastore.should_receive(:store).with(anything, hash_including(
1193
- :path => 'bilbo/megs/billy'
1194
- ))
1195
- item.save!
925
+ it "acts as normal otherwise" do
926
+ @item.image = "asdf"
927
+ @item.image.data.should == "asdf"
1196
928
  end
1197
929
 
1198
- it "should work for other storage_xxx declarations" do
1199
- Item.class_eval do
1200
- image_accessor :preview_image do
1201
- storage_eggs 23
1202
- end
1203
- end
1204
- item = Item.new :preview_image => 'bilbo'
1205
- @app.datastore.should_receive(:store).with(anything, hash_including(
1206
- :eggs => 23
1207
- ))
1208
- item.save!
930
+ it "adds to the path whitelist" do
931
+ path = SAMPLES_DIR.join('beach.jpg')
932
+ @app.fetch_file_whitelist.should include File.expand_path(path)
1209
933
  end
1210
934
  end
1211
935
 
1212
936
  describe "unknown config method" do
1213
937
  it "should raise an error" do
938
+ item_class = new_model_class('Item', :preview_image_uid)
1214
939
  lambda{
1215
- Item.class_eval do
1216
- image_accessor :preview_image do
940
+ item_class.class_eval do
941
+ dragonfly_accessor :preview_image do
1217
942
  what :now?
1218
943
  end
1219
944
  end
@@ -1223,8 +948,10 @@ describe Item do
1223
948
 
1224
949
  describe "changed?" do
1225
950
  before(:each) do
1226
- set_up_item_class
1227
- @item = Item.new
951
+ @item_class = new_model_class('Item', :preview_image_uid) do
952
+ dragonfly_accessor :preview_image
953
+ end
954
+ @item = @item_class.new
1228
955
  end
1229
956
 
1230
957
  it "should be changed when assigned" do
@@ -1241,18 +968,26 @@ describe Item do
1241
968
  it "should not be changed when reloaded" do
1242
969
  @item.preview_image = 'ggg'
1243
970
  @item.save!
1244
- item = Item.find(@item.id)
971
+ item = @item_class.find(@item.id)
1245
972
  item.preview_image.should_not be_changed
1246
973
  end
1247
974
  end
1248
975
 
1249
976
  describe "retain and pending" do
1250
977
  before(:each) do
1251
- set_up_item_class(@app=test_app)
1252
- @app.analyser.add :some_analyser_method do |temp_object|
1253
- temp_object.data.upcase
978
+ @app=test_app
979
+ @app.add_analyser :some_analyser_method do |content|
980
+ content.data.upcase
1254
981
  end
1255
- @item = Item.new
982
+ @item_class = new_model_class('Item',
983
+ :preview_image_uid,
984
+ :preview_image_some_analyser_method,
985
+ :preview_image_size,
986
+ :preview_image_name
987
+ ) do
988
+ dragonfly_accessor :preview_image
989
+ end
990
+ @item = @item_class.new
1256
991
  end
1257
992
 
1258
993
  it "should return nil if there are no changes" do
@@ -1273,25 +1008,26 @@ describe Item do
1273
1008
  it "should return the saved stuff if assigned and retained" do
1274
1009
  @item.preview_image = 'hello'
1275
1010
  @item.preview_image.name = 'dog.biscuit'
1276
- @app.datastore.should_receive(:store).with do |temp_object, opts|
1277
- temp_object.data.should == 'hello'
1278
- temp_object.meta.should == {
1279
- :name => "dog.biscuit",
1280
- :some_analyser_method => "HELLO",
1281
- :size => 5,
1282
- :model_class => "Item",
1283
- :model_attachment => :preview_image
1284
- }
1011
+ @app.datastore.should_receive(:write).with do |content, opts|
1012
+ content.data.should == 'hello'
1285
1013
  end.and_return('new/uid')
1286
1014
  @item.preview_image.retain!
1287
- Dragonfly::Serializer.json_decode(@item.retained_preview_image, :symbolize_keys => true).should == {
1288
- :uid => 'new/uid',
1289
- :some_analyser_method => 'HELLO',
1290
- :size => 5,
1291
- :name => 'dog.biscuit'
1015
+ Dragonfly::Serializer.json_b64_decode(@item.retained_preview_image).should == {
1016
+ 'uid' => 'new/uid',
1017
+ 'some_analyser_method' => 'HELLO',
1018
+ 'size' => 5,
1019
+ 'name' => 'dog.biscuit'
1292
1020
  }
1293
1021
  end
1294
1022
 
1023
+ it "should rescue analysis errors" do
1024
+ @app.add_analyser(:some_analyser_method){ raise "oh no!" }
1025
+ @item.preview_image = 'hello'
1026
+ @item.preview_image.retain!
1027
+ attrs = Dragonfly::Serializer.json_b64_decode(@item.retained_preview_image)
1028
+ attrs['some_analyser_method'].should be_nil
1029
+ end
1030
+
1295
1031
  it "should return nil if assigned, retained and saved" do
1296
1032
  @item.preview_image = 'hello'
1297
1033
  @item.preview_image.retain!
@@ -1309,7 +1045,7 @@ describe Item do
1309
1045
  it "should return nil if no changes have been made" do
1310
1046
  @item.preview_image = 'hello'
1311
1047
  @item.save!
1312
- item = Item.find(@item.id)
1048
+ item = @item_class.find(@item.id)
1313
1049
  item.preview_image.retain!
1314
1050
  item.retained_preview_image.should be_nil
1315
1051
  end
@@ -1317,17 +1053,26 @@ describe Item do
1317
1053
 
1318
1054
  describe "assigning from a pending state" do
1319
1055
  before(:each) do
1320
- set_up_item_class(@app=test_app)
1321
- @app.analyser.add :some_analyser_method do |temp_object|
1322
- temp_object.data.upcase
1323
- end
1324
- @pending_string = Dragonfly::Serializer.json_encode(
1325
- :uid => 'new/uid',
1326
- :some_analyser_method => 'HELLO',
1327
- :size => 5,
1328
- :name => 'dog.biscuit'
1056
+ @app=test_app
1057
+ @app.add_analyser :some_analyser_method do |content|
1058
+ content.data.upcase
1059
+ end
1060
+ @uid = @app.store('retrieved yo')
1061
+ @pending_string = Dragonfly::Serializer.json_b64_encode(
1062
+ 'uid' => @uid,
1063
+ 'some_analyser_method' => 'HELLO',
1064
+ 'size' => 5,
1065
+ 'name' => 'dog.biscuit'
1329
1066
  )
1330
- @item = Item.new
1067
+ @item_class = new_model_class('Item',
1068
+ :preview_image_uid,
1069
+ :preview_image_size,
1070
+ :preview_image_some_analyser_method,
1071
+ :preview_image_name
1072
+ ) do
1073
+ dragonfly_accessor :preview_image
1074
+ end
1075
+ @item = @item_class.new
1331
1076
  end
1332
1077
 
1333
1078
  it "should be retained" do
@@ -1337,7 +1082,7 @@ describe Item do
1337
1082
 
1338
1083
  it "should update the attributes" do
1339
1084
  @item.retained_preview_image = @pending_string
1340
- @item.preview_image_uid.should == 'new/uid'
1085
+ @item.preview_image_uid.should == @uid
1341
1086
  @item.preview_image_some_analyser_method.should == 'HELLO'
1342
1087
  @item.preview_image_size.should == 5
1343
1088
  @item.preview_image_name.should == 'dog.biscuit'
@@ -1345,7 +1090,6 @@ describe Item do
1345
1090
 
1346
1091
  it "should be a normal fetch job" do
1347
1092
  @item.retained_preview_image = @pending_string
1348
- @app.datastore.should_receive(:retrieve).with('new/uid').and_return(Dragonfly::TempObject.new('retrieved yo'))
1349
1093
  @item.preview_image.data.should == 'retrieved yo'
1350
1094
  end
1351
1095
 
@@ -1355,17 +1099,17 @@ describe Item do
1355
1099
  end
1356
1100
 
1357
1101
  it "should raise an error if the pending string contains a non-magic attr method" do
1358
- pending_string = Dragonfly::Serializer.json_encode(
1359
- :uid => 'new/uid',
1360
- :some_analyser_method => 'HELLO',
1361
- :size => 5,
1362
- :name => 'dog.biscuit',
1363
- :something => 'else'
1102
+ pending_string = Dragonfly::Serializer.json_b64_encode(
1103
+ 'uid' => @uid,
1104
+ 'some_analyser_method' => 'HELLO',
1105
+ 'size' => 5,
1106
+ 'name' => 'dog.biscuit',
1107
+ 'something' => 'else'
1364
1108
  )
1365
1109
  item = @item
1366
1110
  lambda{
1367
1111
  item.retained_preview_image = pending_string
1368
- }.should raise_error(Dragonfly::ActiveModelExtensions::Attachment::BadAssignmentKey)
1112
+ }.should raise_error(Dragonfly::Model::Attachment::BadAssignmentKey)
1369
1113
  end
1370
1114
 
1371
1115
  [nil, "", "asdfsad"].each do |value|
@@ -1377,15 +1121,15 @@ describe Item do
1377
1121
 
1378
1122
  it "should return the pending string again" do
1379
1123
  @item.retained_preview_image = @pending_string
1380
- Dragonfly::Serializer.json_decode(@item.retained_preview_image).should ==
1381
- Dragonfly::Serializer.json_decode(@pending_string)
1124
+ Dragonfly::Serializer.json_b64_decode(@item.retained_preview_image).should ==
1125
+ Dragonfly::Serializer.json_b64_decode(@pending_string)
1382
1126
  end
1383
1127
 
1384
1128
  it "should destroy the old one on save" do
1385
1129
  @item.preview_image = 'oldone'
1386
- @app.datastore.should_receive(:store).with(a_temp_object_with_data('oldone'), anything).and_return('old/uid')
1130
+ @app.datastore.should_receive(:write).with(content_with_data('oldone'), anything).and_return('old/uid')
1387
1131
  @item.save!
1388
- item = Item.find(@item.id)
1132
+ item = @item_class.find(@item.id)
1389
1133
  item.retained_preview_image = @pending_string
1390
1134
  @app.datastore.should_receive(:destroy).with('old/uid')
1391
1135
  item.save!
@@ -1394,25 +1138,25 @@ describe Item do
1394
1138
  describe "combinations of assignment" do
1395
1139
  it "should destroy the previously retained one if something new is then assigned" do
1396
1140
  @item.retained_preview_image = @pending_string
1397
- @app.datastore.should_receive(:destroy).with('new/uid')
1141
+ @app.datastore.should_receive(:destroy).with(@uid)
1398
1142
  @item.preview_image = 'yet another new thing'
1399
1143
  end
1400
1144
 
1401
1145
  it "should destroy the previously retained one if something new is already assigned" do
1402
1146
  @item.preview_image = 'yet another new thing'
1403
- @app.datastore.should_receive(:destroy).with('new/uid')
1147
+ @app.datastore.should_receive(:destroy).with(@uid)
1404
1148
  @item.retained_preview_image = @pending_string
1405
1149
  end
1406
1150
 
1407
1151
  it "should destroy the previously retained one if nil is then assigned" do
1408
1152
  @item.retained_preview_image = @pending_string
1409
- @app.datastore.should_receive(:destroy).with('new/uid')
1153
+ @app.datastore.should_receive(:destroy).with(@uid)
1410
1154
  @item.preview_image = nil
1411
1155
  end
1412
1156
 
1413
1157
  it "should destroy the previously retained one if nil is already assigned" do
1414
1158
  @item.preview_image = nil
1415
- @app.datastore.should_receive(:destroy).with('new/uid')
1159
+ @app.datastore.should_receive(:destroy).with(@uid)
1416
1160
  @item.retained_preview_image = @pending_string
1417
1161
  end
1418
1162
 
@@ -1445,46 +1189,78 @@ describe Item do
1445
1189
 
1446
1190
  end
1447
1191
 
1448
- describe "format and mime type" do
1449
- before(:each) do
1450
- @app = test_app
1451
- @app.analyser.add :mime_type do |temp_object|
1452
- 'some/type'
1192
+ describe "xxx_stored?" do
1193
+ before do
1194
+ item_class = new_model_class('Item', :photo_uid) do
1195
+ dragonfly_accessor :photo
1453
1196
  end
1454
- set_up_item_class(@app)
1455
- @item = Item.new
1456
- @content = "doggo"
1457
- @content.stub!(:original_filename).and_return('egg.png')
1197
+ @item = item_class.new
1198
+ end
1199
+
1200
+ it "returns false if unassigned" do
1201
+ @item.photo_stored?.should be_false
1458
1202
  end
1459
- it "should trust the file extension with format if configured to" do
1460
- @item.preview_image = @content
1461
- @item.preview_image.format.should == :png
1203
+
1204
+ it "returns false if assigned but not stored" do
1205
+ @item.photo = "Asdf"
1206
+ @item.photo_stored?.should be_false
1462
1207
  end
1463
- it "should trust the file extension with mime_type if configured to" do
1464
- @item.preview_image = @content
1465
- @item.preview_image.mime_type.should == 'image/png'
1208
+
1209
+ it "returns true if stored" do
1210
+ @item.photo = "Asdf"
1211
+ @item.save!
1212
+ @item.photo_stored?.should be_true
1466
1213
  end
1467
- it "should not trust the file extension with format if configured not to" do
1468
- @app.trust_file_extensions = false
1469
- @item.preview_image = @content
1470
- @item.preview_image.format.should == nil
1214
+ end
1215
+
1216
+ describe "misc properties" do
1217
+ before(:each) do
1218
+ @item_class = new_model_class('Item', :photo_uid) do
1219
+ dragonfly_accessor :photo
1220
+ end
1221
+ @item = @item_class.new :photo => 'blug'
1471
1222
  end
1472
- it "should not trust the file extension with mime_type if configured not to" do
1473
- @app.trust_file_extensions = false
1474
- @item.preview_image = @content
1475
- @item.preview_image.mime_type.should == 'some/type'
1223
+
1224
+ it "returns the b64_data" do
1225
+ @item.photo.b64_data.should =~ /^data:/
1226
+ end
1227
+
1228
+ it "returns the mime_type" do
1229
+ @item.photo.ext = 'txt'
1230
+ @item.photo.mime_type.should == 'text/plain'
1476
1231
  end
1477
1232
  end
1478
1233
 
1479
1234
  describe "inspect" do
1480
1235
  before(:each) do
1481
- set_up_item_class
1482
- @item = Item.new :preview_image => 'blug'
1236
+ @item_class = new_model_class('Item', :preview_image_uid) do
1237
+ dragonfly_accessor :preview_image
1238
+ end
1239
+ @item = @item_class.new :preview_image => 'blug'
1483
1240
  @item.save!
1484
1241
  end
1485
1242
  it "should be awesome" do
1486
- @item.preview_image.inspect.should =~ %r{^<Dragonfly Attachment uid="[^"]+", app=:test[_\w]*>$}
1243
+ @item.preview_image.inspect.should =~ %r{^<Dragonfly Attachment uid="[^"]+", app=:default>$}
1487
1244
  end
1488
1245
  end
1489
1246
 
1247
+ describe 'overwriting instance methods' do
1248
+ let(:klass) do
1249
+ new_model_class('Item', :foo_uid) do
1250
+ dragonfly_accessor :foo
1251
+
1252
+ def foo
1253
+ super
1254
+ end
1255
+ end
1256
+ end
1257
+
1258
+ let(:item) { klass.new }
1259
+
1260
+ it 'works as expected when calling super' do
1261
+ item.foo.should be_nil
1262
+ item.foo = 'DATASTRING'
1263
+ item.foo.should be_a(Dragonfly::Model::Attachment)
1264
+ end
1265
+ end
1490
1266
  end