effective_assets 0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/MIT-LICENSE +20 -0
- data/README.md +228 -0
- data/Rakefile +23 -0
- data/app/assets/images/effective_assets/icon_close.png +0 -0
- data/app/assets/images/effective_assets/s3_down_button.gif +0 -0
- data/app/assets/images/effective_assets/s3_over_button.gif +0 -0
- data/app/assets/images/effective_assets/s3_up_button.gif +0 -0
- data/app/assets/images/effective_assets/s3_upload.swf +0 -0
- data/app/assets/images/effective_assets/spinner.gif +0 -0
- data/app/assets/images/mime-types/excel.jpg +0 -0
- data/app/assets/images/mime-types/file.png +0 -0
- data/app/assets/images/mime-types/mp3.png +0 -0
- data/app/assets/images/mime-types/pdf.png +0 -0
- data/app/assets/images/mime-types/video.png +0 -0
- data/app/assets/images/mime-types/word.jpg +0 -0
- data/app/assets/images/mime-types/zip.png +0 -0
- data/app/assets/javascripts/effective_assets.js +1 -0
- data/app/assets/javascripts/effective_assets/asset_box_input.js.coffee +71 -0
- data/app/assets/javascripts/effective_assets/asset_box_uploader.js +122 -0
- data/app/assets/javascripts/effective_assets/asset_box_uploader_customization.js +166 -0
- data/app/assets/javascripts/effective_assets/jquery_ui_sortable.js +2106 -0
- data/app/assets/stylesheets/effective_assets.css.scss +1 -0
- data/app/assets/stylesheets/effective_assets/_asset_box_input.scss +206 -0
- data/app/controllers/effective/attachments_controller.rb +14 -0
- data/app/controllers/effective/s3_uploads_controller.rb +98 -0
- data/app/helpers/effective_assets_helper.rb +55 -0
- data/app/models/concerns/acts_as_asset_box.rb +97 -0
- data/app/models/effective/asset.rb +224 -0
- data/app/models/effective/attachment.rb +25 -0
- data/app/models/effective/delayed_job.rb +99 -0
- data/app/models/inputs/asset_box_input.rb +87 -0
- data/app/models/validators/asset_box_length_validator.rb +11 -0
- data/app/models/validators/asset_box_presence_validator.rb +6 -0
- data/app/uploaders/asset_uploader.rb +26 -0
- data/app/uploaders/effective_assets_uploader.rb +63 -0
- data/app/views/active_admin/effective_assets/_edit.html.haml +35 -0
- data/app/views/active_admin/effective_assets/_form.html.haml +4 -0
- data/app/views/active_admin/effective_assets/_new.html.haml +3 -0
- data/app/views/asset_box_input/_attachment_fields.html.haml +14 -0
- data/app/views/asset_box_input/_uploader.html.haml +119 -0
- data/app/views/assets/_video.html.erb +4 -0
- data/config/routes.rb +6 -0
- data/db/migrate/01_create_effective_assets.rb.erb +42 -0
- data/lib/effective_assets.rb +31 -0
- data/lib/effective_assets/engine.rb +38 -0
- data/lib/effective_assets/version.rb +3 -0
- data/lib/generators/effective_assets/install_generator.rb +41 -0
- data/lib/generators/templates/README +1 -0
- data/lib/generators/templates/asset_uploader.rb +25 -0
- data/lib/generators/templates/effective_assets.rb +19 -0
- data/lib/tasks/effective_assets_tasks.rake +4 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +65 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/db/development.sqlite3 +0 -0
- data/spec/dummy/db/schema.rb +16 -0
- data/spec/dummy/db/test.sqlite3 +0 -0
- data/spec/dummy/log/development.log +71 -0
- data/spec/dummy/log/test.log +33 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/dummy/spec_link +3 -0
- data/spec/models/asset_spec.rb +46 -0
- data/spec/spec_helper.rb +34 -0
- data/spec/support/factories.rb +28 -0
- metadata +431 -0
@@ -0,0 +1 @@
|
|
1
|
+
@import "effective_assets/asset_box_input";
|
@@ -0,0 +1,206 @@
|
|
1
|
+
@mixin clearfix {
|
2
|
+
display: block;
|
3
|
+
&:after { content:"\0020";display:block;height:0;clear:both;visibility:hidden;overflow:hidden; }
|
4
|
+
}
|
5
|
+
|
6
|
+
@mixin border-radius ($radius) {
|
7
|
+
position: relative;
|
8
|
+
-webkit-border-radius: $radius;
|
9
|
+
-moz-border-radius: $radius;
|
10
|
+
-ms-border-radius: $radius;
|
11
|
+
-o-border-radius: $radius;
|
12
|
+
border-radius: $radius;
|
13
|
+
}
|
14
|
+
|
15
|
+
.asset_box_uploader {
|
16
|
+
width: 800px;
|
17
|
+
margin: 0px auto;
|
18
|
+
text-align: left;
|
19
|
+
|
20
|
+
.file_lists {
|
21
|
+
border: 1px solid #B7B9BB;
|
22
|
+
height: 300px;
|
23
|
+
margin-bottom: 10px;
|
24
|
+
overflow-y: scroll;
|
25
|
+
}
|
26
|
+
|
27
|
+
.file_list {
|
28
|
+
border-width: 0 0 1px 0;
|
29
|
+
list-style-type: none;
|
30
|
+
padding: 0;
|
31
|
+
margin: 0;
|
32
|
+
|
33
|
+
li {
|
34
|
+
border: 1px solid #B7B9BB;
|
35
|
+
height: 60px;
|
36
|
+
line-height: 45px;
|
37
|
+
position: relative;
|
38
|
+
padding: 0 0 25px 0;
|
39
|
+
}
|
40
|
+
|
41
|
+
.progress {
|
42
|
+
display: block;
|
43
|
+
height: 85px;
|
44
|
+
text-align: right;
|
45
|
+
background: #EFEFEF;
|
46
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#EFEFEF), to(#DFE1E2));
|
47
|
+
background: -moz-linear-gradient(-90deg, #EFEFEF, #DFE1E2);
|
48
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#efefef, endColorstr=#dfe1e2);
|
49
|
+
-ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#efefef, endColorstr=#dfe1e2);
|
50
|
+
|
51
|
+
.amount {
|
52
|
+
position: absolute;
|
53
|
+
right: 10px;
|
54
|
+
top: 15px;
|
55
|
+
color: #666;
|
56
|
+
text-shadow: 1px 1px #fff;
|
57
|
+
}
|
58
|
+
}
|
59
|
+
|
60
|
+
.file_name {
|
61
|
+
display: block;
|
62
|
+
position: absolute;
|
63
|
+
font-weight: bold;
|
64
|
+
margin: 0 0 15px 10px;
|
65
|
+
}
|
66
|
+
|
67
|
+
.file_size {
|
68
|
+
display: block;
|
69
|
+
position: absolute;
|
70
|
+
right: 10px;
|
71
|
+
bottom: 0;
|
72
|
+
line-height: 2;
|
73
|
+
color: #AEAEAE;
|
74
|
+
}
|
75
|
+
|
76
|
+
.properties {
|
77
|
+
position: absolute;
|
78
|
+
left: 10px;
|
79
|
+
bottom: 10px;
|
80
|
+
display: block;
|
81
|
+
|
82
|
+
label {
|
83
|
+
float: left !important;
|
84
|
+
line-height: 2 !important;
|
85
|
+
margin-right: 4px !important;
|
86
|
+
}
|
87
|
+
|
88
|
+
input[type="text"] {
|
89
|
+
float: left !important;
|
90
|
+
margin-right: 30px !important;
|
91
|
+
width: 130px !important;
|
92
|
+
}
|
93
|
+
}
|
94
|
+
}
|
95
|
+
|
96
|
+
.file_todo_list {
|
97
|
+
.progress { display: none; }
|
98
|
+
}
|
99
|
+
|
100
|
+
.file_done_list {
|
101
|
+
.progress { width: 100%; }
|
102
|
+
}
|
103
|
+
|
104
|
+
.overall {
|
105
|
+
border: 1px solid #B7B9BB;
|
106
|
+
height: 35px;
|
107
|
+
line-height: 35px;
|
108
|
+
position: relative;
|
109
|
+
font-size: 130%;
|
110
|
+
margin-bottom: 10px;
|
111
|
+
|
112
|
+
.progress {
|
113
|
+
display: block;
|
114
|
+
height: 35px;
|
115
|
+
background: #6A7176;
|
116
|
+
background: -webkit-gradient(linear, left top, left bottom, from(#6A7176), to(#4D5256));
|
117
|
+
background: -moz-linear-gradient(-90deg, #6A7176, #4D5256);
|
118
|
+
filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6a7176, endColorstr=#4d5256);
|
119
|
+
-ms-filter: progid:DXImageTransform.Microsoft.gradient(startColorstr=#6a7176, endColorstr=#4d5256);
|
120
|
+
|
121
|
+
.amount {
|
122
|
+
padding-right: 0px;
|
123
|
+
color: #eaeaea;
|
124
|
+
text-shadow: 1px 1px #333;
|
125
|
+
position: absolute;
|
126
|
+
right: 10px;
|
127
|
+
}
|
128
|
+
}
|
129
|
+
|
130
|
+
.status {
|
131
|
+
text-align: center;
|
132
|
+
display: block;
|
133
|
+
width: 100%;
|
134
|
+
font-weight: bold;
|
135
|
+
color: #aaa;
|
136
|
+
position: absolute;
|
137
|
+
}
|
138
|
+
|
139
|
+
}
|
140
|
+
|
141
|
+
.progress {
|
142
|
+
display: block;
|
143
|
+
position: absolute;
|
144
|
+
text-align: right;
|
145
|
+
}
|
146
|
+
|
147
|
+
input[type="submit"] {
|
148
|
+
margin-left: 0 !important;
|
149
|
+
|
150
|
+
&.StopButton, &.ResetButton {
|
151
|
+
float: right;
|
152
|
+
margin-left: 10px !important;
|
153
|
+
}
|
154
|
+
}
|
155
|
+
|
156
|
+
label {
|
157
|
+
float: none;
|
158
|
+
width: auto !important;
|
159
|
+
text-align: left;
|
160
|
+
margin: 0 !important;
|
161
|
+
}
|
162
|
+
}
|
163
|
+
|
164
|
+
.asset-box-attachment {
|
165
|
+
position: relative;
|
166
|
+
width: 128px;
|
167
|
+
float: left;
|
168
|
+
margin-right: 20px;
|
169
|
+
height: 190px;
|
170
|
+
|
171
|
+
p.title {
|
172
|
+
font-size: 14px;
|
173
|
+
color: #818181;
|
174
|
+
padding: 10px;
|
175
|
+
margin: 0;
|
176
|
+
}
|
177
|
+
}
|
178
|
+
|
179
|
+
.asset-box-spinner {
|
180
|
+
height: 128px;
|
181
|
+
width: 128px;
|
182
|
+
background: rgba(255,255,255,0.8) image-url('effective_assets/spinner.gif') no-repeat center center;
|
183
|
+
display: block;
|
184
|
+
margin-bottom: 6px;
|
185
|
+
}
|
186
|
+
|
187
|
+
.attachments {
|
188
|
+
@include clearfix;
|
189
|
+
}
|
190
|
+
|
191
|
+
.file_to_upload .delete, .asset-box-remove {
|
192
|
+
@include border-radius(3px);
|
193
|
+
display: block;
|
194
|
+
position: absolute;
|
195
|
+
background: rgba(255,255,255,0.8) image-url('effective_assets/icon_close.png') no-repeat center center;
|
196
|
+
text-indent: -99999px !important;
|
197
|
+
height: 20px;
|
198
|
+
width: 20px;
|
199
|
+
right: 10px;
|
200
|
+
top: 10px;
|
201
|
+
cursor: pointer;
|
202
|
+
}
|
203
|
+
|
204
|
+
.assets {
|
205
|
+
clear: both;
|
206
|
+
}
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Effective
|
2
|
+
class AttachmentsController < ApplicationController
|
3
|
+
skip_authorize_resource if defined?(CanCan)
|
4
|
+
respond_to :json
|
5
|
+
|
6
|
+
def show
|
7
|
+
@asset = Asset.find(params[:id]) # This should actually search Assets
|
8
|
+
|
9
|
+
EffectiveAssets.authorized?(self, :read, @asset)
|
10
|
+
|
11
|
+
respond_with @asset
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 's3_swf_upload'
|
2
|
+
require 'base64'
|
3
|
+
|
4
|
+
module Effective
|
5
|
+
class S3UploadsController < ApplicationController
|
6
|
+
skip_authorize_resource if defined?(CanCan)
|
7
|
+
|
8
|
+
respond_to :js, :xml
|
9
|
+
|
10
|
+
include S3SwfUpload::Signature
|
11
|
+
|
12
|
+
def index
|
13
|
+
# This is actually a 'new' action. Not an index. The s3 flash uploader is hardcoded to check this url as an xml request
|
14
|
+
|
15
|
+
EffectiveAssets.authorized?(self, :create, Effective::Asset)
|
16
|
+
|
17
|
+
bucket = EffectiveAssets.aws_bucket
|
18
|
+
access_key_id = EffectiveAssets.aws_access_key_id
|
19
|
+
acl = EffectiveAssets.aws_acl
|
20
|
+
secret_key = EffectiveAssets.aws_secret_access_key
|
21
|
+
key = params[:key]
|
22
|
+
content_type = params[:content_type]
|
23
|
+
https = 'false'
|
24
|
+
error_message = ''
|
25
|
+
expiration_date = 1.hours.from_now.utc.strftime('%Y-%m-%dT%H:%M:%S.000Z')
|
26
|
+
|
27
|
+
policy = Base64.encode64(
|
28
|
+
"{
|
29
|
+
'expiration': '#{expiration_date}',
|
30
|
+
'conditions': [
|
31
|
+
{'bucket': '#{bucket}'},
|
32
|
+
{'key': '#{key}'},
|
33
|
+
{'acl': '#{acl}'},
|
34
|
+
{'Content-Type': '#{content_type}'},
|
35
|
+
{'Content-Disposition': 'attachment'},
|
36
|
+
['starts-with', '$Filename', ''],
|
37
|
+
['eq', '$success_action_status', '201']
|
38
|
+
]
|
39
|
+
}").gsub(/\n|\r/, '')
|
40
|
+
|
41
|
+
signature = b64_hmac_sha1(secret_key, policy)
|
42
|
+
|
43
|
+
respond_to do |format|
|
44
|
+
format.xml {
|
45
|
+
render :xml => {
|
46
|
+
:policy => policy,
|
47
|
+
:signature => signature,
|
48
|
+
:bucket => bucket,
|
49
|
+
:accesskeyid => access_key_id,
|
50
|
+
:acl => acl,
|
51
|
+
:expirationdate => expiration_date,
|
52
|
+
:https => https,
|
53
|
+
:errorMessage => error_message.to_s,
|
54
|
+
}.to_xml
|
55
|
+
}
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def create
|
60
|
+
EffectiveAssets.authorized?(self, :create, Effective::Asset)
|
61
|
+
|
62
|
+
# If we're passed Asset information, then create an Asset
|
63
|
+
if params[:file_path].present?
|
64
|
+
asset = Asset.create_from_s3_uploader(params[:file_path],
|
65
|
+
{
|
66
|
+
:title => params[:title],
|
67
|
+
:description => params[:description],
|
68
|
+
:tags => params[:tags],
|
69
|
+
:content_type => params[:content_type],
|
70
|
+
:data_size => params[:file_size],
|
71
|
+
:user_id => current_user.try(:id)
|
72
|
+
}
|
73
|
+
)
|
74
|
+
else
|
75
|
+
asset = (Asset.find(params[:asset_id].to_i) rescue false)
|
76
|
+
end
|
77
|
+
|
78
|
+
unless asset
|
79
|
+
render :text => '', :status => :unprocessable_entity
|
80
|
+
return
|
81
|
+
end
|
82
|
+
|
83
|
+
# If the attachment information is present, then our input needs some attachment HTML
|
84
|
+
if params.key?(:attachable_type)
|
85
|
+
attachment = Attachment.new
|
86
|
+
attachment.attachable_type = params[:attachable_type].try(:classify)
|
87
|
+
attachment.attachable_id = params[:attachable_id].try(:to_i) if params[:attachable_id].present? # attachable_id can be nil if we're on a New action
|
88
|
+
attachment.asset_id = asset.try(:id)
|
89
|
+
attachment.box = params[:box]
|
90
|
+
attachment.position = 0
|
91
|
+
|
92
|
+
render :partial => 'asset_box_input/attachment_fields', :locals => {:attachment => attachment}, :status => 200, :content_type => 'text/html'
|
93
|
+
else
|
94
|
+
render :text => '', :status => 200
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
module EffectiveAssetsHelper
|
2
|
+
# Generates an image tag based on the particular asset
|
3
|
+
def effective_asset_image_tag(asset, version = nil, options = {})
|
4
|
+
if asset.image? == false
|
5
|
+
opts = {}
|
6
|
+
elsif version.present? and asset.versions_info[version].present?
|
7
|
+
opts = { :height => asset.versions_info[version][:height], :width => asset.versions_info[version][:width] }
|
8
|
+
elsif version.present? and asset.data.respond_to?(:versions_info) and asset.data.versions_info[version].present?
|
9
|
+
opts = { :height => asset.data.versions_info[version][:height], :width => asset.data.versions_info[version][:width] }
|
10
|
+
elsif asset.height.present? and asset.width.present?
|
11
|
+
opts = { :height => asset.height, :width => asset.width }
|
12
|
+
else
|
13
|
+
opts = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
opts = opts.merge({:alt => asset.description || asset.title || asset.file_name}).merge(options)
|
17
|
+
image_tag(_effective_asset_image_url(asset, version), opts).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
|
18
|
+
end
|
19
|
+
|
20
|
+
def effective_asset_link_to(asset, version = nil, options = {})
|
21
|
+
link_title = asset.title || asset.file_name || asset.description || "Asset ##{asset.id}"
|
22
|
+
|
23
|
+
link_to(link_title, asset.url).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
|
24
|
+
end
|
25
|
+
|
26
|
+
def effective_asset_video_tag(asset)
|
27
|
+
render(:partial => 'assets/video', :locals => { :asset => asset }).gsub('"', "'").html_safe # we need all ' quotes or it breaks Insert as functionality
|
28
|
+
end
|
29
|
+
|
30
|
+
def _effective_asset_image_url(asset, version = nil)
|
31
|
+
return '/assets/mime-types/file.png' if !asset.content_type.present? or asset.content_type == 'unknown'
|
32
|
+
|
33
|
+
if asset.icon?
|
34
|
+
asset.url
|
35
|
+
elsif asset.image?
|
36
|
+
(version == nil or asset.still_processing?) ? asset.url : asset.url.insert(asset.url.rindex('/')+1, "#{version.to_s}_")
|
37
|
+
elsif asset.audio?
|
38
|
+
'/assets/mime-types/mp3.png'
|
39
|
+
elsif asset.video?
|
40
|
+
'/assets/mime-types/video.png'
|
41
|
+
elsif asset.content_type.include? 'msword'
|
42
|
+
'/assets/mime-types/word.jpg'
|
43
|
+
elsif asset.content_type.include? 'excel'
|
44
|
+
'/assets/mime-types/excel.jpg'
|
45
|
+
elsif asset.content_type.include? 'application/pdf'
|
46
|
+
'/assets/mime-types/pdf.png'
|
47
|
+
elsif asset.content_type.include? 'application/zip'
|
48
|
+
'/assets/mime-types/zip.png'
|
49
|
+
else
|
50
|
+
'/assets/mime-types/file.png'
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,97 @@
|
|
1
|
+
# ActsAsAssetBox
|
2
|
+
#
|
3
|
+
# Returns a set of assets or one asset as defined by the provided 'boxes' (a box is just a category) array
|
4
|
+
# Works with Formtastic::Inputs::asset_box_input
|
5
|
+
#
|
6
|
+
# Define your model with 'acts_as_asset_box' if you just need one box of assets
|
7
|
+
# You will then be able to call @my_resource.assets and @my_resource.asset
|
8
|
+
#
|
9
|
+
# or
|
10
|
+
#
|
11
|
+
# acts_as_asset_box :fav_icon, :pictures, :logos
|
12
|
+
#
|
13
|
+
# or (if you want validations)
|
14
|
+
#
|
15
|
+
# acts_as_asset_box :fav_icon => true, :pictures => false, :videos => 2, :images => 5..10
|
16
|
+
#
|
17
|
+
# Define your model with 'acts_as_asset_box :fav_icon, :pictures, :logos' for 3 different boxes of assets.
|
18
|
+
# This creates three methods, @my_resource.fav_icon, @my_resource.pictures, @my_resource.logos
|
19
|
+
#
|
20
|
+
# If you define a singular name, like :fav_icon, then calling @my_resource.fav_icon will return the 1 asset from the fav_icon box
|
21
|
+
# If you define a plural name, like :pictures, then calling @my_resource.pictures will return all assets in the pictures box
|
22
|
+
#
|
23
|
+
# This works with the lib/acts_as_asset_box_input.rb for editting boxes of assets
|
24
|
+
#
|
25
|
+
|
26
|
+
module ActsAsAssetBox
|
27
|
+
extend ActiveSupport::Concern
|
28
|
+
|
29
|
+
module ActiveRecord
|
30
|
+
def acts_as_asset_box(*options)
|
31
|
+
@acts_as_asset_box_opts = options || []
|
32
|
+
include ::ActsAsAssetBox
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
included do
|
37
|
+
has_many :attachments, :as => :attachable, :class_name => "Effective::Attachment", :dependent => :delete_all
|
38
|
+
has_many :assets, :through => :attachments, :class_name => "Effective::Asset"
|
39
|
+
|
40
|
+
#attr_accessible :attachments_attributes
|
41
|
+
accepts_nested_attributes_for :attachments, :reject_if => :all_blank, :allow_destroy => true
|
42
|
+
|
43
|
+
# Setup validations
|
44
|
+
boxes = @acts_as_asset_box_opts.try(:flatten) || []
|
45
|
+
if boxes.first.kind_of?(Hash) # We were passed some validation requirements
|
46
|
+
boxes = boxes.first
|
47
|
+
|
48
|
+
@@acts_as_asset_box_boxes = boxes.keys
|
49
|
+
|
50
|
+
boxes.each do |box, validation|
|
51
|
+
if validation == true
|
52
|
+
validates box, :asset_box_presence => true
|
53
|
+
elsif validation.kind_of?(Integer) or validation.kind_of?(Range)
|
54
|
+
validates box, :asset_box_length => validation
|
55
|
+
end
|
56
|
+
end
|
57
|
+
else
|
58
|
+
@@acts_as_asset_box_boxes = boxes
|
59
|
+
end
|
60
|
+
|
61
|
+
class_eval do
|
62
|
+
def attachments_attributes=(atts)
|
63
|
+
current_box = ''; position = 0
|
64
|
+
|
65
|
+
atts.each do |k, v|
|
66
|
+
(current_box = v['box'] and position = 0) if v['box'] != current_box
|
67
|
+
atts[k]['position'] = (position += 1) if atts[k]['_destroy'] != '1'
|
68
|
+
end
|
69
|
+
|
70
|
+
assign_nested_attributes_for_collection_association(:attachments, atts, {})
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
module ClassMethods
|
76
|
+
end
|
77
|
+
|
78
|
+
def assets(box = nil)
|
79
|
+
box = (box.present? ? box.to_s : 'assets')
|
80
|
+
|
81
|
+
if box == box.pluralize
|
82
|
+
attachments.select { |attachment| attachment.box == box }.map { |attachment| attachment.asset }
|
83
|
+
else
|
84
|
+
attachments.to_a.find { |attachment| attachment.box == box.pluralize }.try(:asset)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
def asset
|
89
|
+
assets(:asset)
|
90
|
+
end
|
91
|
+
|
92
|
+
# This handles all the boxes type function calls
|
93
|
+
def method_missing(method_name, *args, &block)
|
94
|
+
(@@acts_as_asset_box_boxes || []).include?(method_name.to_sym) ? assets(method_name) : super
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|