pageflow 13.6.0 → 14.0.0.beta1
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of pageflow might be problematic. Click here for more details.
- checksums.yaml +4 -4
- data/CHANGELOG.md +72 -5
- data/app/assets/javascripts/pageflow/dist/react-client.js +22 -27
- data/app/assets/javascripts/pageflow/dist/react-server.js +22 -27
- data/app/assets/javascripts/pageflow/editor/collections/files_collection.js +0 -1
- data/app/assets/javascripts/pageflow/editor/models/file_uploader.js +3 -1
- data/app/assets/javascripts/pageflow/editor/models/hosted_file.js +2 -7
- data/app/assets/javascripts/pageflow/editor/models/image_file.js +1 -1
- data/app/assets/javascripts/pageflow/editor/models/uploaded_file.js +12 -10
- data/app/assets/javascripts/pageflow/editor/views/configuration_editors/groups/general.js +4 -4
- data/app/assets/javascripts/pageflow/editor/views/uploader_view.js +18 -27
- data/app/assets/javascripts/pageflow/slideshow/page_split_layout.js +8 -8
- data/app/assets/javascripts/pageflow/slideshow/page_widget.js +1 -1
- data/app/assets/stylesheets/pageflow/delayed_text_fade_in.scss +10 -5
- data/app/assets/stylesheets/pageflow/editor/file_stages.scss +0 -4
- data/app/assets/stylesheets/pageflow/editor/file_thumbnails.scss +0 -4
- data/app/assets/stylesheets/pageflow/hide_text.scss +2 -2
- data/app/assets/stylesheets/pageflow/lt_ie9.scss +5 -5
- data/app/assets/stylesheets/pageflow/navigation_bar.scss +1 -0
- data/app/assets/stylesheets/pageflow/navigation_mobile.scss +4 -0
- data/app/assets/stylesheets/pageflow/page.scss +2 -2
- data/app/assets/stylesheets/pageflow/page_transitions/crossfade.scss +1 -1
- data/app/assets/stylesheets/pageflow/page_transitions/fade.scss +11 -11
- data/app/assets/stylesheets/pageflow/page_transitions/fade_to_black.scss +13 -10
- data/app/assets/stylesheets/pageflow/page_types/audio.scss +3 -3
- data/app/assets/stylesheets/pageflow/page_types/video.scss +9 -9
- data/app/assets/stylesheets/pageflow/page_types/video/content_hiding.scss +2 -2
- data/app/assets/stylesheets/pageflow/page_types/video/mobile_poster.scss +3 -3
- data/app/assets/stylesheets/pageflow/print_view.scss +8 -5
- data/app/assets/stylesheets/pageflow/slideshow.scss +6 -5
- data/app/assets/stylesheets/pageflow/themes/default/base.scss +1 -1
- data/app/assets/stylesheets/pageflow/themes/default/page.scss +3 -168
- data/app/assets/stylesheets/pageflow/themes/default/page/anchors.scss +2 -2
- data/app/assets/stylesheets/pageflow/themes/default/page/content_text_margin.scss +1 -1
- data/app/assets/stylesheets/pageflow/themes/default/page/header.scss +172 -0
- data/app/assets/stylesheets/pageflow/themes/default/page/hyphenate.scss +1 -1
- data/app/assets/stylesheets/pageflow/themes/default/page/line_lengths.scss +12 -14
- data/app/assets/stylesheets/pageflow/themes/default/player_controls/vjs_mapping.scss +6 -6
- data/app/assets/stylesheets/pageflow/themes/default/{video_wrapper.scss → uncropped_media_wrapper.scss} +1 -1
- data/app/controllers/pageflow/editor/files_controller.rb +11 -8
- data/app/helpers/pageflow/background_image_helper.rb +2 -1
- data/app/helpers/pageflow/files_helper.rb +1 -0
- data/app/helpers/pageflow/pages_helper.rb +31 -0
- data/app/helpers/pageflow/video_files_helper.rb +3 -3
- data/app/jobs/pageflow/process_file_job.rb +15 -5
- data/app/models/concerns/pageflow/hosted_file.rb +42 -33
- data/app/models/concerns/pageflow/uploaded_file.rb +10 -0
- data/app/models/pageflow/audio_file.rb +1 -1
- data/app/models/pageflow/audio_file_url_templates.rb +1 -1
- data/app/models/pageflow/draft_entry.rb +1 -1
- data/app/models/pageflow/image_file.rb +38 -52
- data/app/models/pageflow/image_file_css_background_image_urls.rb +4 -4
- data/app/models/pageflow/image_file_url_templates.rb +2 -2
- data/app/models/pageflow/positioned_file.rb +1 -1
- data/app/models/pageflow/text_track_file.rb +15 -32
- data/app/models/pageflow/text_track_file_url_templates.rb +2 -3
- data/app/models/pageflow/video_file.rb +1 -1
- data/app/models/pageflow/video_file_url_templates.rb +1 -1
- data/app/state_machines/pageflow/{image_file_state_machine.rb → processed_file_state_machine.rb} +4 -10
- data/app/views/pageflow/editor/files/_file.json.jbuilder +4 -0
- data/app/views/pageflow/entries/edit.html.erb +2 -2
- data/app/views/pageflow/entries/mobile_navigation/_page.html.erb +1 -0
- data/app/views/pageflow/entries/navigation/_page.html.erb +2 -1
- data/config/initializers/paperclip.rb +6 -0
- data/config/routes.rb +1 -1
- data/db/migrate/20181115165746_change_processed_attachment_to_attachment_on_s3_for_images.rb +16 -0
- data/db/migrate/20190306161431_copy_file_attributes_of_failed_uploads.rb +25 -0
- data/lib/pageflow/configuration.rb +23 -5
- data/lib/pageflow/configuration/defaults.rb +2 -9
- data/lib/pageflow/version.rb +1 -1
- data/spec/factories/audio_files.rb +17 -10
- data/spec/factories/hosted_files.rb +13 -11
- data/spec/factories/image_files.rb +18 -11
- data/spec/factories/text_track_files.rb +30 -10
- data/spec/factories/video_files.rb +16 -9
- metadata +9 -8
- data/app/assets/javascripts/pageflow/dist/react.js +0 -29944
- data/app/jobs/pageflow/upload_file_to_s3_job.rb +0 -25
@@ -4,12 +4,12 @@ module Pageflow
|
|
4
4
|
def call(image_file)
|
5
5
|
{
|
6
6
|
default: {
|
7
|
-
desktop: image_file.attachment.url(:large),
|
8
|
-
mobile: image_file.attachment.url(:medium)
|
7
|
+
desktop: image_file.ready? ? image_file.attachment.url(:large) : '',
|
8
|
+
mobile: image_file.ready? ? image_file.attachment.url(:medium) : ''
|
9
9
|
},
|
10
10
|
panorama: {
|
11
|
-
desktop: image_file.attachment.url(:panorama_large),
|
12
|
-
mobile: image_file.attachment.url(:panorama_medium)
|
11
|
+
desktop: image_file.ready? ? image_file.attachment.url(:panorama_large) : '',
|
12
|
+
mobile: image_file.ready? ? image_file.attachment.url(:panorama_medium) : ''
|
13
13
|
}
|
14
14
|
}
|
15
15
|
end
|
@@ -9,11 +9,11 @@ module Pageflow
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def styles
|
12
|
-
|
12
|
+
example_file.attachment_styles(example_file.attachment).keys
|
13
13
|
end
|
14
14
|
|
15
15
|
def example_file
|
16
|
-
@example_file ||= ImageFile.new(id: 0,
|
16
|
+
@example_file ||= ImageFile.new(id: 0, file_name: ':basename.jpg')
|
17
17
|
end
|
18
18
|
end
|
19
19
|
end
|
@@ -1,41 +1,24 @@
|
|
1
1
|
module Pageflow
|
2
2
|
class TextTrackFile < ApplicationRecord
|
3
3
|
include HostedFile
|
4
|
+
include ProcessedFileStateMachine
|
4
5
|
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
on_enter 'processing'
|
16
|
-
result :ok, state: 'processed'
|
17
|
-
result :error, state: 'processing_failed'
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
has_attached_file(:processed_attachment,
|
22
|
-
Pageflow.config.paperclip_s3_default_options
|
23
|
-
.merge(styles: {
|
24
|
-
vtt: {
|
25
|
-
format: 'vtt',
|
26
|
-
processors: [:pageflow_vtt],
|
27
|
-
s3_headers: {
|
28
|
-
'Content-Type' => 'text/vtt'
|
29
|
-
}
|
30
|
-
}
|
31
|
-
}))
|
32
|
-
|
33
|
-
def ready?
|
34
|
-
processed?
|
6
|
+
def attachment_styles(_attachment)
|
7
|
+
{
|
8
|
+
vtt: {
|
9
|
+
format: 'vtt',
|
10
|
+
processors: [:pageflow_vtt],
|
11
|
+
s3_headers: {
|
12
|
+
'Content-Type' => 'text/vtt'
|
13
|
+
}
|
14
|
+
}
|
15
|
+
}
|
35
16
|
end
|
36
17
|
|
37
|
-
|
38
|
-
|
18
|
+
# used in paperclip initializer to interpolate the storage path
|
19
|
+
# needs to be "processed_attachments" for text tracks for legacy reasons
|
20
|
+
def attachments_path_name
|
21
|
+
'processed_attachments'
|
39
22
|
end
|
40
23
|
|
41
24
|
def meta_data_attributes=(attributes)
|
@@ -2,15 +2,14 @@ module Pageflow
|
|
2
2
|
class TextTrackFileUrlTemplates
|
3
3
|
def call
|
4
4
|
{
|
5
|
-
vtt: UrlTemplate.from_attachment(example_file.
|
5
|
+
vtt: UrlTemplate.from_attachment(example_file.attachment, :vtt)
|
6
6
|
}
|
7
7
|
end
|
8
8
|
|
9
9
|
private
|
10
10
|
|
11
11
|
def example_file
|
12
|
-
@example_file ||= TextTrackFile.new(id: 0,
|
13
|
-
processed_attachment_file_name: ':basename.vtt')
|
12
|
+
@example_file ||= TextTrackFile.new(id: 0, file_name: ':basename.vtt')
|
14
13
|
end
|
15
14
|
end
|
16
15
|
end
|
@@ -26,7 +26,7 @@ module Pageflow
|
|
26
26
|
|
27
27
|
def example_file
|
28
28
|
@example_file ||= VideoFile.new(id: 0).tap do |video_file|
|
29
|
-
video_file.
|
29
|
+
video_file.file_name = ':basename.mp4'
|
30
30
|
video_file.poster_file_name = video_file.zencoder_poster.original_filename
|
31
31
|
end
|
32
32
|
end
|
data/app/state_machines/pageflow/{image_file_state_machine.rb → processed_file_state_machine.rb}
RENAMED
@@ -1,19 +1,17 @@
|
|
1
1
|
module Pageflow
|
2
|
-
module
|
2
|
+
module ProcessedFileStateMachine
|
3
3
|
extend ActiveSupport::Concern
|
4
4
|
|
5
5
|
included do
|
6
|
-
|
6
|
+
processing_state_machine do
|
7
7
|
extend StateMachineJob::Macro
|
8
8
|
|
9
|
-
state 'not_processed'
|
10
9
|
state 'processing'
|
11
10
|
state 'processed'
|
12
|
-
|
13
|
-
state 'processing_to_s3_failed'
|
11
|
+
state 'processing_failed'
|
14
12
|
|
15
13
|
event :process do
|
16
|
-
transition '
|
14
|
+
transition 'uploaded' => 'processing'
|
17
15
|
transition 'processing_failed' => 'processing'
|
18
16
|
end
|
19
17
|
|
@@ -29,10 +27,6 @@ module Pageflow
|
|
29
27
|
process!
|
30
28
|
end
|
31
29
|
|
32
|
-
def publish!
|
33
|
-
process!
|
34
|
-
end
|
35
|
-
|
36
30
|
def retryable?
|
37
31
|
processing_failed?
|
38
32
|
end
|
@@ -28,8 +28,8 @@
|
|
28
28
|
<div class="editor" id="editor_menu_container">
|
29
29
|
</div>
|
30
30
|
|
31
|
-
<%=
|
32
|
-
<%=
|
31
|
+
<%= form_tag '#', :multipart => true, :id => 'upload' do %>
|
32
|
+
<%= file_field_tag :file, :multiple => true %>
|
33
33
|
<% end %>
|
34
34
|
|
35
35
|
<script>
|
@@ -1,5 +1,6 @@
|
|
1
1
|
<li class="<%= page_navigation_css_class(page) %>">
|
2
2
|
<%= link_to "##{page.perma_id}", data: {link: page.id, chapter_id: page.chapter_id} do %>
|
3
3
|
<%= image_tag('', data: {src: asset_path(page.thumbnail_url(:thumbnail_overview_mobile))}) %>
|
4
|
+
<%= page.title %>
|
4
5
|
<% end %>
|
5
6
|
</li>
|
@@ -1,6 +1,7 @@
|
|
1
1
|
<li class="<%= page_navigation_css_class(page) %>">
|
2
2
|
<%= link_to "##{page.perma_id}", :data => {:link => page.id, :chapter_id => page.chapter_id} do %>
|
3
|
-
|
3
|
+
<%= image_tag('', data: {src: asset_path(page.thumbnail_url(:navigation_thumbnail_small))}, width: 85, height: 47) %>
|
4
|
+
<%= page.title %>
|
4
5
|
<% end %>
|
5
6
|
<div class="navigation_site_detail">
|
6
7
|
<%= page.title %>
|
@@ -10,6 +10,12 @@ Paperclip.interpolates(:class_basename) do |attachment, style|
|
|
10
10
|
Pageflow::PaperclipInterpolations::Support.class_basename(attachment, style)
|
11
11
|
end
|
12
12
|
|
13
|
+
Paperclip.interpolates(:attachments_path_name) do |attachment, style|
|
14
|
+
record = attachment.instance
|
15
|
+
return record.attachments_path_name if record.respond_to?(:attachments_path_name)
|
16
|
+
self.attachment(attachment, style)
|
17
|
+
end
|
18
|
+
|
13
19
|
Paperclip.interpolates(:pageflow_placeholder) do |attachment, style|
|
14
20
|
Pageflow::PaperclipInterpolations::Support.pageflow_placeholder(attachment, style)
|
15
21
|
end
|
data/config/routes.rb
CHANGED
@@ -55,9 +55,9 @@ Pageflow::Engine.routes.draw do
|
|
55
55
|
resources :files,
|
56
56
|
path: 'files/:collection_name',
|
57
57
|
only: [:index, :create, :update, :destroy] do
|
58
|
-
post :empty, on: :collection, to: 'files#create'
|
59
58
|
post :reuse, on: :collection
|
60
59
|
post :retry, on: :member
|
60
|
+
put :publish, on: :member
|
61
61
|
end
|
62
62
|
end
|
63
63
|
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class ChangeProcessedAttachmentToAttachmentOnS3ForImages < ActiveRecord::Migration[5.2]
|
2
|
+
def change
|
3
|
+
rename_column :pageflow_image_files,
|
4
|
+
:processed_attachment_file_name,
|
5
|
+
:attachment_on_s3_file_name
|
6
|
+
rename_column :pageflow_image_files,
|
7
|
+
:processed_attachment_content_type,
|
8
|
+
:attachment_on_s3_content_type
|
9
|
+
rename_column :pageflow_image_files,
|
10
|
+
:processed_attachment_file_size,
|
11
|
+
:attachment_on_s3_file_size
|
12
|
+
rename_column :pageflow_image_files,
|
13
|
+
:processed_attachment_updated_at,
|
14
|
+
:attachment_on_s3_updated_at
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
class CopyFileAttributesOfFailedUploads < ActiveRecord::Migration[5.2]
|
2
|
+
def up
|
3
|
+
%w(audio text_track video).each do |hosted_file_type|
|
4
|
+
execute("UPDATE pageflow_#{hosted_file_type}_files hf
|
5
|
+
SET hf.attachment_on_s3_file_name = hf.attachment_on_filesystem_file_name,
|
6
|
+
hf.attachment_on_s3_content_type = hf.attachment_on_filesystem_content_type,
|
7
|
+
hf.attachment_on_s3_file_size = hf.attachment_on_filesystem_file_size,
|
8
|
+
hf.attachment_on_s3_updated_at = hf.attachment_on_filesystem_updated_at,
|
9
|
+
hf.state = 'uploading_failed'
|
10
|
+
WHERE hf.state = 'uploading_to_s3_failed';")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def down
|
15
|
+
%w(audio text_track video).each do |hosted_file_type|
|
16
|
+
execute("UPDATE pageflow_#{hosted_file_type}_files hf
|
17
|
+
SET hf.attachment_on_s3_file_name = NULL,
|
18
|
+
hf.attachment_on_s3_content_type = NULL,
|
19
|
+
hf.attachment_on_s3_file_size = NULL,
|
20
|
+
hf.attachment_on_s3_updated_at = NULL,
|
21
|
+
hf.state = 'uploading_to_s3_failed'
|
22
|
+
WHERE hf.state = 'uploading_failed';")
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,10 +1,6 @@
|
|
1
1
|
module Pageflow
|
2
2
|
# Options to be defined in the pageflow initializer of the main app.
|
3
3
|
class Configuration
|
4
|
-
# Default options for paperclip attachments which are supposed to
|
5
|
-
# use filesystem storage.
|
6
|
-
attr_accessor :paperclip_filesystem_default_options
|
7
|
-
|
8
4
|
# Default options for paperclip attachments which are supposed to use
|
9
5
|
# s3 storage.
|
10
6
|
attr_accessor :paperclip_s3_default_options
|
@@ -26,6 +22,16 @@ module Pageflow
|
|
26
22
|
# @since 13.0
|
27
23
|
attr_accessor :paperclip_s3_root
|
28
24
|
|
25
|
+
# Upload options provided to direct upload form.
|
26
|
+
# Defaults to S3 storage options.
|
27
|
+
# returns a hash with keys:
|
28
|
+
# - url: The URL to use as the action of the form
|
29
|
+
# - fields: A hash of fields that will be included in the direct upload form.
|
30
|
+
# This hash should include the signed POST policy, the access key ID and
|
31
|
+
# security token (if present), etc.
|
32
|
+
# These fields will be included as input elements of type 'hidden' on the form
|
33
|
+
attr_accessor :paperclip_direct_upload_options
|
34
|
+
|
29
35
|
# Refer to the pageflow initializer template for a list of
|
30
36
|
# supported options.
|
31
37
|
attr_accessor :zencoder_options
|
@@ -314,9 +320,21 @@ module Pageflow
|
|
314
320
|
@paperclip_filesystem_root = Rails.public_path.join('system/uploads')
|
315
321
|
@paperclip_s3_root = 'main'
|
316
322
|
|
317
|
-
@paperclip_filesystem_default_options = Defaults::PAPERCLIP_FILESYSTEM_DEFAULT_OPTIONS.dup
|
318
323
|
@paperclip_s3_default_options = Defaults::PAPERCLIP_S3_DEFAULT_OPTIONS.dup
|
319
324
|
|
325
|
+
@paperclip_direct_upload_options = lambda { |attachment|
|
326
|
+
max_upload_size = 4_294_967_296 # max file size in bytes
|
327
|
+
presigned_post_config = attachment.s3_bucket
|
328
|
+
.presigned_post(key: attachment.path,
|
329
|
+
success_action_status: '201',
|
330
|
+
acl: 'public-read',
|
331
|
+
content_length_range: 0..max_upload_size)
|
332
|
+
{
|
333
|
+
url: presigned_post_config.url,
|
334
|
+
fields: presigned_post_config.fields
|
335
|
+
}
|
336
|
+
}
|
337
|
+
|
320
338
|
@zencoder_options = {}
|
321
339
|
|
322
340
|
@mailer_sender = 'pageflow@example.com'
|
@@ -1,20 +1,13 @@
|
|
1
1
|
module Pageflow
|
2
2
|
class Configuration
|
3
3
|
module Defaults
|
4
|
-
PAPERCLIP_FILESYSTEM_DEFAULT_OPTIONS = {
|
5
|
-
storage: :filesystem,
|
6
|
-
path: ':pageflow_filesystem_root/:class/:attachment/:id_partition/:style/:filename',
|
7
|
-
url: 'not_uploaded_yet',
|
8
|
-
validate_media_type: false
|
9
|
-
}.freeze
|
10
|
-
|
11
4
|
PAPERCLIP_S3_DEFAULT_OPTIONS = {
|
12
5
|
storage: :s3,
|
13
6
|
s3_headers: {'Cache-Control' => 'public, max-age=31536000'},
|
14
7
|
|
15
8
|
url: ':s3_alias_url',
|
16
|
-
path: ':pageflow_s3_root/:class_basename/:
|
17
|
-
|
9
|
+
path: ':pageflow_s3_root/:class_basename/:attachments_path_name/' \
|
10
|
+
':id_partition/:pageflow_attachments_version:style/:filename',
|
18
11
|
|
19
12
|
validate_media_type: false,
|
20
13
|
|
data/lib/pageflow/version.rb
CHANGED
@@ -4,7 +4,8 @@ module Pageflow
|
|
4
4
|
entry
|
5
5
|
uploader { create(:user) }
|
6
6
|
|
7
|
-
|
7
|
+
attachment { File.open(Engine.root.join('spec', 'fixtures', 'et.ogg')) }
|
8
|
+
state { 'encoded' }
|
8
9
|
|
9
10
|
transient do
|
10
11
|
used_in { nil }
|
@@ -18,16 +19,23 @@ module Pageflow
|
|
18
19
|
create(:file_usage, :file => file, :revision => evaluator.used_in) if evaluator.used_in
|
19
20
|
end
|
20
21
|
|
21
|
-
trait :
|
22
|
-
|
23
|
-
|
24
|
-
state { '
|
22
|
+
trait :uploading do
|
23
|
+
attachment { nil }
|
24
|
+
file_name { 'et.ogg' }
|
25
|
+
state { 'uploading' }
|
26
|
+
|
27
|
+
after :create do |audio_file|
|
28
|
+
simulate_direct_upload(audio_file)
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
trait :uploaded do
|
33
|
+
uploading
|
34
|
+
state { 'uploaded' }
|
25
35
|
end
|
26
36
|
|
27
|
-
trait :
|
28
|
-
|
29
|
-
attachment_on_s3 { nil }
|
30
|
-
state { 'uploading_to_s3_failed' }
|
37
|
+
trait :uploading_failed do
|
38
|
+
state { 'uploading_failed' }
|
31
39
|
end
|
32
40
|
|
33
41
|
trait :waiting_for_confirmation do
|
@@ -39,7 +47,6 @@ module Pageflow
|
|
39
47
|
end
|
40
48
|
|
41
49
|
trait :encoded do
|
42
|
-
state { 'encoded' }
|
43
50
|
end
|
44
51
|
end
|
45
52
|
end
|
@@ -1,8 +1,8 @@
|
|
1
1
|
module Pageflow
|
2
2
|
FactoryBot.define do
|
3
3
|
factory :hosted_file, class: 'Pageflow::TestHostedFile' do
|
4
|
-
|
5
|
-
state { '
|
4
|
+
attachment { File.open(Engine.root.join('spec', 'fixtures', 'image.png')) }
|
5
|
+
state { 'uploaded' }
|
6
6
|
|
7
7
|
transient do
|
8
8
|
used_in { nil }
|
@@ -12,19 +12,21 @@ module Pageflow
|
|
12
12
|
create(:file_usage, file: file, revision: evaluator.used_in) if evaluator.used_in
|
13
13
|
end
|
14
14
|
|
15
|
-
trait :
|
16
|
-
|
17
|
-
|
18
|
-
state { '
|
15
|
+
trait :uploading do
|
16
|
+
attachment { nil }
|
17
|
+
file_name { 'image.jpg' }
|
18
|
+
state { 'uploading' }
|
19
|
+
|
20
|
+
after :create do |hosted_file|
|
21
|
+
simulate_direct_upload(hosted_file)
|
22
|
+
end
|
19
23
|
end
|
20
24
|
|
21
|
-
trait :
|
22
|
-
attachment_on_filesystem { File.open(Engine.root.join('spec', 'fixtures', 'image.png')) }
|
23
|
-
attachment_on_s3 { nil }
|
24
|
-
state { 'uploading_to_s3_failed' }
|
25
|
+
trait :uploaded do
|
25
26
|
end
|
26
27
|
|
27
|
-
trait :
|
28
|
+
trait :uploading_failed do
|
29
|
+
state { 'uploading_failed' }
|
28
30
|
end
|
29
31
|
end
|
30
32
|
end
|