radiant-page_attachments-extension 1.0.0 → 1.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/HELP.md +27 -0
- data/README.md +34 -11
- data/VERSION +1 -1
- data/app/controllers/admin/page_attachments_controller.rb +46 -0
- data/app/helpers/admin/page_attachments_helper.rb +11 -0
- data/app/models/page_attachment_tags.rb +13 -6
- data/app/models/page_attachments_interface.rb +1 -0
- data/app/views/admin/page_attachments/edit.html.haml +21 -0
- data/app/views/admin/page_attachments/grid.html.haml +20 -0
- data/app/views/admin/page_attachments/index.html.haml +24 -0
- data/app/views/admin/pages/_attachment.html.erb +19 -0
- data/app/views/admin/pages/_attachment.html.haml +1 -1
- data/lib/tasks/page_attachments_extension_tasks.rake +3 -0
- data/page_attachments_extension.rb +17 -3
- data/public/images/admin/page_attachments/move_higher.png +0 -0
- data/public/images/admin/page_attachments/move_lower.png +0 -0
- data/public/images/admin/page_attachments/pdf-icon.png +0 -0
- data/public/javascripts/admin/lowpro.js +338 -0
- data/public/javascripts/admin/page_attachments.js +1 -1
- data/public/stylesheets/page_attachments.css +98 -0
- data/radiant-page_attachments-extension.gemspec +16 -5
- data/vendor/plugins/attachment_fu/README +7 -14
- data/vendor/plugins/attachment_fu/amazon_s3.yml.tpl +0 -3
- data/vendor/plugins/attachment_fu/install.rb +0 -2
- data/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu.rb +9 -18
- data/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb +8 -33
- data/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/s3_backend.rb +15 -55
- data/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/processors/rmagick_processor.rb +9 -0
- data/vendor/plugins/attachment_fu/test/backends/file_system_test.rb +1 -64
- data/vendor/plugins/attachment_fu/test/basic_test.rb +3 -3
- data/vendor/plugins/attachment_fu/test/fixtures/attachment.rb +0 -43
- data/vendor/plugins/attachment_fu/test/schema.rb +1 -27
- metadata +25 -5
- data/app/models/observe_page_attachments.rb +0 -5
@@ -23,7 +23,7 @@ Event.addBehavior({
|
|
23
23
|
var attachment = event.findElement('.attachment');
|
24
24
|
attachment.addClassName('deleted');
|
25
25
|
attachment.insert("<em>Attachment will be deleted when page is saved.</em>");
|
26
|
-
attachment.down('input[name*="
|
26
|
+
attachment.down('input[name*="_destroy"]').setValue('true');
|
27
27
|
}
|
28
28
|
}
|
29
29
|
|
@@ -0,0 +1,98 @@
|
|
1
|
+
.gridded, .gridded li { margin: 0; padding: 0;}
|
2
|
+
.gridded { overflow: hidden;}
|
3
|
+
.gridded li { background: #000; display: block; float: left; height: 230px; width: 180px; margin: 0 1em 1em 0;}
|
4
|
+
.sample { background: #fff; display: block; width: 180px; height: 120px; margin: 0 10px 10px 0; overflow: hidden;}
|
5
|
+
.pageTitle { background: #000; color: #fff; padding: 2px; }
|
6
|
+
.pageTitle a { color: #fff;}
|
7
|
+
#attachments {
|
8
|
+
clear: both;
|
9
|
+
border: 1px solid #d4cba4;
|
10
|
+
background: white;
|
11
|
+
margin: 10px 0;
|
12
|
+
}
|
13
|
+
#attachments .toolbar {
|
14
|
+
float: right;
|
15
|
+
padding: 10px;
|
16
|
+
width: 50px;
|
17
|
+
text-align: right;
|
18
|
+
}
|
19
|
+
#attachments .toolbar img {
|
20
|
+
padding: 5px;
|
21
|
+
cursor: pointer;
|
22
|
+
}
|
23
|
+
#attachments h3, #attachments p.notice {
|
24
|
+
background: #eae3c5;
|
25
|
+
margin: 0;
|
26
|
+
padding: 0.5em;
|
27
|
+
}
|
28
|
+
#attachments .attachment-upload {
|
29
|
+
padding: 0 0.8em 0.8em 0.8em;
|
30
|
+
}
|
31
|
+
#attachments p.notice {
|
32
|
+
padding: .5em .8em;
|
33
|
+
font-style: italic;
|
34
|
+
font-size: 90%;
|
35
|
+
color: red;
|
36
|
+
}
|
37
|
+
#attachments .attachment-upload img,
|
38
|
+
#attachments .attachment img.delete {
|
39
|
+
cursor: pointer;
|
40
|
+
padding: 2px;
|
41
|
+
margin-left:7px;
|
42
|
+
}
|
43
|
+
#attachments .attachment img.higher,
|
44
|
+
#attachments .attachment img.lower {
|
45
|
+
cursor: pointer;
|
46
|
+
padding: 2px;
|
47
|
+
margin-left:6px;
|
48
|
+
}
|
49
|
+
#attachments ol {
|
50
|
+
list-style-position:outside;
|
51
|
+
padding: 10px 10px 0 10px;
|
52
|
+
margin: 0;
|
53
|
+
}
|
54
|
+
#attachments ol li
|
55
|
+
{
|
56
|
+
margin-left:20px;
|
57
|
+
}
|
58
|
+
#attachments ol li div
|
59
|
+
{
|
60
|
+
float:left;width:25px;
|
61
|
+
}
|
62
|
+
#attachments ol li a.thumbnail
|
63
|
+
{
|
64
|
+
float:left;margin:0 10px 0 10px;
|
65
|
+
}
|
66
|
+
#attachments ol li p
|
67
|
+
{
|
68
|
+
margin:0 0 5px 0;
|
69
|
+
}
|
70
|
+
#attachments ol li
|
71
|
+
{
|
72
|
+
margin-bottom:10px;border-bottom:1px dashed #cccccc;width:66%;padding-bottom:3px;
|
73
|
+
}
|
74
|
+
|
75
|
+
#attachments .attachment .thumbnail img {
|
76
|
+
border: 2px solid #d4cba4;
|
77
|
+
}
|
78
|
+
|
79
|
+
#attachments p.title
|
80
|
+
{
|
81
|
+
border-bottom:1px #EAE3C5 solid;width:66%;font-size:17px;font-weight:bold;
|
82
|
+
}
|
83
|
+
#attachments table th
|
84
|
+
{
|
85
|
+
font-weight:bold;text-align:right;padding-right:10px;width:120px;padding-bottom:5px;
|
86
|
+
}
|
87
|
+
#attachments table td
|
88
|
+
{
|
89
|
+
padding-bottom:5px;
|
90
|
+
}
|
91
|
+
#attachments p#reorder_notice
|
92
|
+
{
|
93
|
+
color:#FF0000;margin:0 0 10px 20px;
|
94
|
+
}
|
95
|
+
.clearfix:after {content:".";display:block;height:0;clear:both;visibility:hidden;}
|
96
|
+
.clearfix {display:inline-block;}
|
97
|
+
.clearfix {display:block;}
|
98
|
+
li.clearfix {display:list-item;}
|
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{radiant-page_attachments-extension}
|
8
|
-
s.version = "1.0.
|
8
|
+
s.version = "1.0.2"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Sean Cribbs"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-06-28}
|
13
13
|
s.description = %q{Page Attachments adds support for file uploads realized as attachments to individual pages. Attachments can have an order via acts_as_list, a title, a description and various metadata fields as provided by AttachmentFu.}
|
14
14
|
s.email = %q{radiant@radiantcms.org}
|
15
15
|
s.extra_rdoc_files = [
|
@@ -18,15 +18,21 @@ Gem::Specification.new do |s|
|
|
18
18
|
]
|
19
19
|
s.files = [
|
20
20
|
".gitignore",
|
21
|
+
"HELP.md",
|
21
22
|
"LICENSE",
|
22
23
|
"README.md",
|
23
24
|
"Rakefile",
|
24
25
|
"VERSION",
|
25
|
-
"app/
|
26
|
+
"app/controllers/admin/page_attachments_controller.rb",
|
27
|
+
"app/helpers/admin/page_attachments_helper.rb",
|
26
28
|
"app/models/page_attachment.rb",
|
27
29
|
"app/models/page_attachment_associations.rb",
|
28
30
|
"app/models/page_attachment_tags.rb",
|
29
31
|
"app/models/page_attachments_interface.rb",
|
32
|
+
"app/views/admin/page_attachments/edit.html.haml",
|
33
|
+
"app/views/admin/page_attachments/grid.html.haml",
|
34
|
+
"app/views/admin/page_attachments/index.html.haml",
|
35
|
+
"app/views/admin/pages/_attachment.html.erb",
|
30
36
|
"app/views/admin/pages/_attachment.html.haml",
|
31
37
|
"app/views/admin/pages/_attachments_box.html.haml",
|
32
38
|
"db/migrate/001_create_page_attachments_extension_schema.rb",
|
@@ -40,8 +46,13 @@ Gem::Specification.new do |s|
|
|
40
46
|
"lib/tasks/page_attachments_extension_tasks.rake",
|
41
47
|
"page_attachments_extension.rb",
|
42
48
|
"public/images/admin/drag_order.png",
|
49
|
+
"public/images/admin/page_attachments/move_higher.png",
|
50
|
+
"public/images/admin/page_attachments/move_lower.png",
|
51
|
+
"public/images/admin/page_attachments/pdf-icon.png",
|
52
|
+
"public/javascripts/admin/lowpro.js",
|
43
53
|
"public/javascripts/admin/page_attachments.js",
|
44
54
|
"public/stylesheets/admin/page_attachments.css",
|
55
|
+
"public/stylesheets/page_attachments.css",
|
45
56
|
"radiant-page_attachments-extension.gemspec",
|
46
57
|
"spec/controllers/pages_controller_spec.rb",
|
47
58
|
"spec/datasets/page_attachments_dataset.rb",
|
@@ -108,7 +119,7 @@ Gem::Specification.new do |s|
|
|
108
119
|
s.homepage = %q{http://github.com/radiant/radiant-page-attachments-extension}
|
109
120
|
s.rdoc_options = ["--charset=UTF-8"]
|
110
121
|
s.require_paths = ["lib"]
|
111
|
-
s.rubygems_version = %q{1.3.
|
122
|
+
s.rubygems_version = %q{1.3.7}
|
112
123
|
s.summary = %q{Adds page-attachment-style asset management.}
|
113
124
|
s.test_files = [
|
114
125
|
"spec/controllers/pages_controller_spec.rb",
|
@@ -124,7 +135,7 @@ Gem::Specification.new do |s|
|
|
124
135
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
125
136
|
s.specification_version = 3
|
126
137
|
|
127
|
-
if Gem::Version.new(Gem::
|
138
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
128
139
|
s.add_development_dependency(%q<rspec>, [">= 0"])
|
129
140
|
s.add_development_dependency(%q<cucumber>, [">= 0"])
|
130
141
|
else
|
@@ -9,13 +9,12 @@ attachment_fu functionality
|
|
9
9
|
|
10
10
|
attachment_fu facilitates file uploads in Ruby on Rails. There are a few storage options for the actual file data, but the plugin always at a minimum stores metadata for each file in the database.
|
11
11
|
|
12
|
-
There are
|
12
|
+
There are three storage options for files uploaded through attachment_fu:
|
13
13
|
File system
|
14
14
|
Database file
|
15
15
|
Amazon S3
|
16
|
-
Rackspace (Mosso) Cloud Files
|
17
16
|
|
18
|
-
Each method of storage many options associated with it that will be covered in the following section. Something to note, however, is that the Amazon S3 storage requires you to modify config/amazon_s3.yml
|
17
|
+
Each method of storage many options associated with it that will be covered in the following section. Something to note, however, is that the Amazon S3 storage requires you to modify config/amazon_s3.yml and the Database file storage requires an extra table.
|
19
18
|
|
20
19
|
|
21
20
|
attachment_fu models
|
@@ -42,18 +41,14 @@ has_attachment(options = {})
|
|
42
41
|
# This option need only be included if you want thumbnailing.
|
43
42
|
:thumbnail_class # Set which model class to use for thumbnails.
|
44
43
|
# This current attachment class is used by default.
|
45
|
-
:path_prefix #
|
46
|
-
# Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the S3
|
44
|
+
:path_prefix # path to store the uploaded files.
|
45
|
+
# Uses public/#{table_name} by default for the filesystem, and just #{table_name} for the S3 backend.
|
47
46
|
# Setting this sets the :storage to :file_system.
|
48
|
-
:partition #
|
47
|
+
:partition # Partiton files in directories like /0000/0001/image.jpg. Default is true.
|
49
48
|
:storage # Specifies the storage system to use..
|
50
|
-
# Defaults to :db_file. Options are :file_system, :db_file,
|
51
|
-
:cloudfront # If using S3 for storage, this option allows for serving the files via Amazon CloudFront.
|
52
|
-
# Defaults to false.
|
49
|
+
# Defaults to :db_file. Options are :file_system, :db_file, and :s3.
|
53
50
|
:processor # Sets the image processor to use for resizing of the attached image.
|
54
51
|
# Options include ImageScience, Rmagick, and MiniMagick. Default is whatever is installed.
|
55
|
-
:uuid_primary_key # If your model's primary key is a 128-bit UUID in hexadecimal format, then set this to true.
|
56
|
-
:association_options # attachment_fu automatically defines associations with thumbnails with has_many and belongs_to. If there are any additional options that you want to pass to these methods, then specify them here.
|
57
52
|
|
58
53
|
|
59
54
|
Examples:
|
@@ -70,8 +65,6 @@ has_attachment(options = {})
|
|
70
65
|
has_attachment :storage => :file_system, :path_prefix => 'public/files',
|
71
66
|
:thumbnails => { :thumb => [50, 50], :geometry => 'x50' }
|
72
67
|
has_attachment :storage => :s3
|
73
|
-
has_attachment :store => :s3, :cloudfront => true
|
74
|
-
has_attachment :storage => :cloud_files
|
75
68
|
|
76
69
|
validates_as_attachment
|
77
70
|
This method prevents files outside of the valid range (:min_size to :max_size, or the :size range) from being saved. It does not however, halt the upload of such files. They will be uploaded into memory regardless of size before validation.
|
@@ -127,7 +120,7 @@ There are two parts of the upload form that differ from typical usage.
|
|
127
120
|
Example:
|
128
121
|
<%= form.file_field :uploaded_data %>
|
129
122
|
|
130
|
-
Displaying uploaded images is made easy by the public_filename method of the ActiveRecord attachment objects using file system
|
123
|
+
Displaying uploaded images is made easy by the public_filename method of the ActiveRecord attachment objects using file system and s3 storage.
|
131
124
|
|
132
125
|
public_filename(thumbnail = nil)
|
133
126
|
Returns the public path to the file. If a thumbnail prefix is specified it will return the public file path to the corresponding thumbnail.
|
@@ -2,16 +2,13 @@ development:
|
|
2
2
|
bucket_name: appname_development
|
3
3
|
access_key_id:
|
4
4
|
secret_access_key:
|
5
|
-
distribution_domain: XXXX.cloudfront.net
|
6
5
|
|
7
6
|
test:
|
8
7
|
bucket_name: appname_test
|
9
8
|
access_key_id:
|
10
9
|
secret_access_key:
|
11
|
-
distribution_domain: XXXX.cloudfront.net
|
12
10
|
|
13
11
|
production:
|
14
12
|
bucket_name: appname
|
15
13
|
access_key_id:
|
16
14
|
secret_access_key:
|
17
|
-
distribution_domain: XXXX.cloudfront.net
|
@@ -2,6 +2,4 @@ require 'fileutils'
|
|
2
2
|
|
3
3
|
s3_config = File.dirname(__FILE__) + '/../../../config/amazon_s3.yml'
|
4
4
|
FileUtils.cp File.dirname(__FILE__) + '/amazon_s3.yml.tpl', s3_config unless File.exist?(s3_config)
|
5
|
-
cloudfiles_config = File.dirname(__FILE__) + '/../../../config/rackspace_cloudfiles.yml'
|
6
|
-
FileUtils.cp File.dirname(__FILE__) + '/rackspace_cloudfiles.yml.tpl', cloudfiles_config unless File.exist?(cloudfiles_config)
|
7
5
|
puts IO.read(File.join(File.dirname(__FILE__), 'README'))
|
@@ -52,8 +52,6 @@ module Technoweenie # :nodoc:
|
|
52
52
|
# for the S3 backend. Setting this sets the :storage to :file_system.
|
53
53
|
|
54
54
|
# * <tt>:storage</tt> - Use :file_system to specify the attachment data is stored with the file system. Defaults to :db_system.
|
55
|
-
# * <tt>:cloundfront</tt> - Set to true if you are using S3 storage and want to serve the files through CloudFront. You will need to
|
56
|
-
# set a distribution domain in the amazon_s3.yml config file. Defaults to false
|
57
55
|
# * <tt>:bucket_key</tt> - Use this to specify a different bucket key other than :bucket_name in the amazon_s3.yml file. This allows you to use
|
58
56
|
# different buckets for different models. An example setting would be :image_bucket and the you would need to define the name of the corresponding
|
59
57
|
# bucket in the amazon_s3.yml file.
|
@@ -82,13 +80,17 @@ module Technoweenie # :nodoc:
|
|
82
80
|
options[:thumbnails] ||= {}
|
83
81
|
options[:thumbnail_class] ||= self
|
84
82
|
options[:s3_access] ||= :public_read
|
85
|
-
options[:
|
83
|
+
options[:s3_options] ||= {}
|
86
84
|
options[:content_type] = [options[:content_type]].flatten.collect! { |t| t == :image ? Technoweenie::AttachmentFu.content_types : t }.flatten unless options[:content_type].nil?
|
87
85
|
|
88
86
|
unless options[:thumbnails].is_a?(Hash)
|
89
87
|
raise ArgumentError, ":thumbnails option should be a hash: e.g. :thumbnails => { :foo => '50x50' }"
|
90
88
|
end
|
91
89
|
|
90
|
+
unless options[:s3_options].is_a?(Hash)
|
91
|
+
raise ArgumentError, ":s3_options option should be a hash: e.g. :s3_options => { :cache_control => 'max-age=2592000' }"
|
92
|
+
end
|
93
|
+
|
92
94
|
extend ClassMethods unless (class << self; included_modules; end).include?(ClassMethods)
|
93
95
|
include InstanceMethods unless included_modules.include?(InstanceMethods)
|
94
96
|
|
@@ -102,19 +104,11 @@ module Technoweenie # :nodoc:
|
|
102
104
|
attachment_options[:storage] ||= parent_options[:storage]
|
103
105
|
attachment_options[:path_prefix] ||= attachment_options[:file_system_path]
|
104
106
|
if attachment_options[:path_prefix].nil?
|
105
|
-
attachment_options[:path_prefix] =
|
106
|
-
when :s3 then table_name
|
107
|
-
when :cloud_files then table_name
|
108
|
-
else File.join("public", table_name)
|
109
|
-
end
|
107
|
+
attachment_options[:path_prefix] = attachment_options[:storage] == :s3 ? table_name : File.join("public", table_name)
|
110
108
|
end
|
111
109
|
attachment_options[:path_prefix] = attachment_options[:path_prefix][1..-1] if options[:path_prefix].first == '/'
|
112
110
|
|
113
|
-
|
114
|
-
if attachment_options[:association_options]
|
115
|
-
association_options.merge!(attachment_options[:association_options])
|
116
|
-
end
|
117
|
-
with_options(association_options) do |m|
|
111
|
+
with_options :foreign_key => 'parent_id' do |m|
|
118
112
|
m.has_many :thumbnails, :class_name => "::#{attachment_options[:thumbnail_class]}"
|
119
113
|
m.belongs_to :parent, :class_name => "::#{base_class}" unless options[:thumbnails].empty?
|
120
114
|
end
|
@@ -183,6 +177,7 @@ module Technoweenie # :nodoc:
|
|
183
177
|
base.after_save :after_process_attachment
|
184
178
|
base.after_destroy :destroy_file
|
185
179
|
base.after_validation :process_attachment
|
180
|
+
base.attr_accessible :uploaded_data
|
186
181
|
if defined?(::ActiveSupport::Callbacks)
|
187
182
|
base.define_callbacks :after_resize, :after_attachment_saved, :before_thumbnail_saved
|
188
183
|
end
|
@@ -428,11 +423,7 @@ module Technoweenie # :nodoc:
|
|
428
423
|
def attachment_attributes_valid?
|
429
424
|
[:size, :content_type].each do |attr_name|
|
430
425
|
enum = attachment_options[attr_name]
|
431
|
-
|
432
|
-
errors.add attr_name, I18n.translate("activerecord.errors.messages.inclusion", attr_name => enum) unless enum.nil? || enum.include?(send(attr_name))
|
433
|
-
else
|
434
|
-
errors.add attr_name, ActiveRecord::Errors.default_error_messages[:inclusion] unless enum.nil? || enum.include?(send(attr_name))
|
435
|
-
end
|
426
|
+
errors.add attr_name, ActiveRecord::Errors.default_error_messages[:inclusion] unless enum.nil? || enum.include?(send(attr_name))
|
436
427
|
end
|
437
428
|
end
|
438
429
|
|
data/vendor/plugins/attachment_fu/lib/technoweenie/attachment_fu/backends/file_system_backend.rb
CHANGED
@@ -1,6 +1,4 @@
|
|
1
|
-
require '
|
2
|
-
require 'digest/sha2'
|
3
|
-
|
1
|
+
require 'ftools'
|
4
2
|
module Technoweenie # :nodoc:
|
5
3
|
module AttachmentFu # :nodoc:
|
6
4
|
module Backends
|
@@ -30,39 +28,16 @@ module Technoweenie # :nodoc:
|
|
30
28
|
|
31
29
|
# The attachment ID used in the full path of a file
|
32
30
|
def attachment_path_id
|
33
|
-
((respond_to?(:parent_id) && parent_id) || id)
|
31
|
+
((respond_to?(:parent_id) && parent_id) || id).to_i
|
34
32
|
end
|
35
33
|
|
36
|
-
#
|
37
|
-
#
|
38
|
-
# For example, given an <tt>*args</tt> of ["foo", "bar"], it will return
|
39
|
-
# <tt>["0000", "0001", "foo", "bar"]</tt> (assuming that that id returns 1).
|
40
|
-
#
|
41
|
-
# If the id is not an integer, then path partitioning will be performed by
|
42
|
-
# hashing the string value of the id with SHA-512, and splitting the result
|
43
|
-
# into 4 components. If the id a 128-bit UUID (as set by :uuid_primary_key => true)
|
44
|
-
# then it will be split into 2 components.
|
45
|
-
#
|
46
|
-
# To turn this off entirely, set :partition => false.
|
34
|
+
# by default paritions files into directories e.g. 0000/0001/image.jpg
|
35
|
+
# to turn this off set :partition => false
|
47
36
|
def partitioned_path(*args)
|
48
37
|
if respond_to?(:attachment_options) && attachment_options[:partition] == false
|
49
38
|
args
|
50
|
-
|
51
|
-
|
52
|
-
path_id = attachment_path_id.to_s
|
53
|
-
component1 = path_id[0..15] || "-"
|
54
|
-
component2 = path_id[16..-1] || "-"
|
55
|
-
[component1, component2] + args
|
56
|
-
else
|
57
|
-
path_id = attachment_path_id
|
58
|
-
if path_id.is_a?(Integer)
|
59
|
-
# Primary key is an integer. Split it after padding it with 0.
|
60
|
-
("%08d" % path_id).scan(/..../) + args
|
61
|
-
else
|
62
|
-
# Primary key is a String. Hash it, then split it into 4 components.
|
63
|
-
hash = Digest::SHA512.hexdigest(path_id.to_s)
|
64
|
-
[hash[0..31], hash[32..63], hash[64..95], hash[96..127]] + args
|
65
|
-
end
|
39
|
+
else
|
40
|
+
("%08d" % attachment_path_id).scan(/..../) + args
|
66
41
|
end
|
67
42
|
end
|
68
43
|
|
@@ -110,8 +85,8 @@ module Technoweenie # :nodoc:
|
|
110
85
|
if save_attachment?
|
111
86
|
# TODO: This overwrites the file if it exists, maybe have an allow_overwrite option?
|
112
87
|
FileUtils.mkdir_p(File.dirname(full_filename))
|
113
|
-
|
114
|
-
|
88
|
+
File.cp(temp_path, full_filename)
|
89
|
+
File.chmod(attachment_options[:chmod] || 0644, full_filename)
|
115
90
|
end
|
116
91
|
@old_filename = nil
|
117
92
|
true
|
@@ -17,28 +17,22 @@ module Technoweenie # :nodoc:
|
|
17
17
|
# If you don't already have your access keys, all you need to sign up for the S3 service is an account at Amazon.
|
18
18
|
# You can sign up for S3 and get access keys by visiting http://aws.amazon.com/s3.
|
19
19
|
#
|
20
|
-
# If you wish to use Amazon CloudFront to serve the files, you can also specify a distibution domain for the bucket.
|
21
|
-
# To read more about CloudFront, visit http://aws.amazon.com/cloudfront
|
22
|
-
#
|
23
20
|
# Example configuration (RAILS_ROOT/config/amazon_s3.yml)
|
24
21
|
#
|
25
22
|
# development:
|
26
23
|
# bucket_name: appname_development
|
27
24
|
# access_key_id: <your key>
|
28
25
|
# secret_access_key: <your key>
|
29
|
-
# distribution_domain: XXXX.cloudfront.net
|
30
26
|
#
|
31
27
|
# test:
|
32
28
|
# bucket_name: appname_test
|
33
29
|
# access_key_id: <your key>
|
34
30
|
# secret_access_key: <your key>
|
35
|
-
# distribution_domain: XXXX.cloudfront.net
|
36
31
|
#
|
37
32
|
# production:
|
38
33
|
# bucket_name: appname
|
39
34
|
# access_key_id: <your key>
|
40
35
|
# secret_access_key: <your key>
|
41
|
-
# distribution_domain: XXXX.cloudfront.net
|
42
36
|
#
|
43
37
|
# You can change the location of the config path by passing a full path to the :s3_config_path option.
|
44
38
|
#
|
@@ -65,8 +59,6 @@ module Technoweenie # :nodoc:
|
|
65
59
|
# * <tt>:server</tt> - The server to make requests to. Defaults to <tt>s3.amazonaws.com</tt>.
|
66
60
|
# * <tt>:port</tt> - The port to the requests should be made on. Defaults to 80 or 443 if <tt>:use_ssl</tt> is set.
|
67
61
|
# * <tt>:use_ssl</tt> - If set to true, <tt>:port</tt> will be implicitly set to 443, unless specified otherwise. Defaults to false.
|
68
|
-
# * <tt>:distribution_domain</tt> - The CloudFront distribution domain for the bucket. This can either be the assigned
|
69
|
-
# distribution domain (ie. XXX.cloudfront.net) or a chosen domain using a CNAME. See CloudFront for more details.
|
70
62
|
#
|
71
63
|
# == Usage
|
72
64
|
#
|
@@ -122,6 +114,14 @@ module Technoweenie # :nodoc:
|
|
122
114
|
# default to the <tt>bucket_name</tt> key. This way you only have to create special buckets
|
123
115
|
# this can be helpful if you only need special buckets in certain environments.
|
124
116
|
#
|
117
|
+
# === S3 Header Options
|
118
|
+
#
|
119
|
+
# You can pass options to pass along to S3 via :s3_options as follows
|
120
|
+
#
|
121
|
+
# class Photo < ActiveRecord::Base
|
122
|
+
# has_attachment :storage => :s3, :s3_options => { :cache_control => "max-age=2592000" }
|
123
|
+
# end
|
124
|
+
#
|
125
125
|
# === Permissions
|
126
126
|
#
|
127
127
|
# By default, files are stored on S3 with public access permissions. You can customize this using
|
@@ -158,16 +158,6 @@ module Technoweenie # :nodoc:
|
|
158
158
|
#
|
159
159
|
# Niether <tt>base_path</tt> or <tt>full_filename</tt> include the bucket name as part of the path.
|
160
160
|
# You can retrieve the bucket name using the <tt>bucket_name</tt> method.
|
161
|
-
#
|
162
|
-
# === Accessing CloudFront URLs
|
163
|
-
#
|
164
|
-
# You can get an object's CloudFront URL using the cloudfront_url accessor. Using the example from above:
|
165
|
-
# @postcard.cloudfront_url # => http://XXXX.cloudfront.net/photos/1/mexico.jpg
|
166
|
-
#
|
167
|
-
# The resulting url is in the form: http://:distribution_domain/:table_name/:id/:file
|
168
|
-
#
|
169
|
-
# If you set :cloudfront to true in your model, the public_filename will be the CloudFront
|
170
|
-
# URL, not the S3 URL.
|
171
161
|
module S3Backend
|
172
162
|
class RequiredLibraryNotFoundError < StandardError; end
|
173
163
|
class ConfigFileNotFoundError < StandardError; end
|
@@ -192,11 +182,10 @@ module Technoweenie # :nodoc:
|
|
192
182
|
bucket_key = base.attachment_options[:bucket_key]
|
193
183
|
|
194
184
|
if bucket_key and s3_config[bucket_key.to_sym]
|
195
|
-
|
185
|
+
@@bucket_name = s3_config[bucket_key.to_sym]
|
196
186
|
else
|
197
|
-
|
187
|
+
@@bucket_name = s3_config[:bucket_name]
|
198
188
|
end
|
199
|
-
base.class_eval(eval_string, __FILE__, __LINE__)
|
200
189
|
|
201
190
|
Base.establish_connection!(s3_config.slice(:access_key_id, :secret_access_key, :server, :port, :use_ssl, :persistent, :proxy))
|
202
191
|
|
@@ -216,10 +205,6 @@ module Technoweenie # :nodoc:
|
|
216
205
|
def self.port_string
|
217
206
|
@port_string ||= (s3_config[:port].nil? || s3_config[:port] == (s3_config[:use_ssl] ? 443 : 80)) ? '' : ":#{s3_config[:port]}"
|
218
207
|
end
|
219
|
-
|
220
|
-
def self.distribution_domain
|
221
|
-
@distribution_domain = s3_config[:distribution_domain]
|
222
|
-
end
|
223
208
|
|
224
209
|
module ClassMethods
|
225
210
|
def s3_protocol
|
@@ -233,10 +218,6 @@ module Technoweenie # :nodoc:
|
|
233
218
|
def s3_port_string
|
234
219
|
Technoweenie::AttachmentFu::Backends::S3Backend.port_string
|
235
220
|
end
|
236
|
-
|
237
|
-
def cloudfront_distribution_domain
|
238
|
-
Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
|
239
|
-
end
|
240
221
|
end
|
241
222
|
|
242
223
|
# Overwrites the base filename writer in order to store the old filename
|
@@ -275,27 +256,7 @@ module Technoweenie # :nodoc:
|
|
275
256
|
def s3_url(thumbnail = nil)
|
276
257
|
File.join(s3_protocol + s3_hostname + s3_port_string, bucket_name, full_filename(thumbnail))
|
277
258
|
end
|
278
|
-
|
279
|
-
# All public objects are accessible via a GET request to CloudFront. You can generate a
|
280
|
-
# url for an object using the cloudfront_url method.
|
281
|
-
#
|
282
|
-
# @photo.cloudfront_url
|
283
|
-
#
|
284
|
-
# The resulting url is in the form: <tt>http://:distribution_domain/:table_name/:id/:file</tt> using
|
285
|
-
# the <tt>:distribution_domain</tt> variable set in the configuration parameters in <tt>RAILS_ROOT/config/amazon_s3.yml</tt>.
|
286
|
-
#
|
287
|
-
# The optional thumbnail argument will output the thumbnail's filename (if any).
|
288
|
-
def cloudfront_url(thumbnail = nil)
|
289
|
-
"http://" + cloudfront_distribution_domain + "/" + full_filename(thumbnail)
|
290
|
-
end
|
291
|
-
|
292
|
-
def public_filename(*args)
|
293
|
-
if attachment_options[:cloudfront]
|
294
|
-
cloudfront_url(args)
|
295
|
-
else
|
296
|
-
s3_url(args)
|
297
|
-
end
|
298
|
-
end
|
259
|
+
alias :public_filename :s3_url
|
299
260
|
|
300
261
|
# All private objects are accessible via an authenticated GET request to the S3 servers. You can generate an
|
301
262
|
# authenticated url for an object like this:
|
@@ -323,7 +284,6 @@ module Technoweenie # :nodoc:
|
|
323
284
|
# @photo.authenticated_s3_url('thumbnail', :expires_in => 5.hours, :use_ssl => true)
|
324
285
|
def authenticated_s3_url(*args)
|
325
286
|
options = args.extract_options!
|
326
|
-
options[:expires_in] = options[:expires_in].to_i if options[:expires_in]
|
327
287
|
thumbnail = args.shift
|
328
288
|
S3Object.url_for(full_filename(thumbnail), bucket_name, options)
|
329
289
|
end
|
@@ -347,10 +307,6 @@ module Technoweenie # :nodoc:
|
|
347
307
|
def s3_port_string
|
348
308
|
Technoweenie::AttachmentFu::Backends::S3Backend.port_string
|
349
309
|
end
|
350
|
-
|
351
|
-
def cloudfront_distribution_domain
|
352
|
-
Technoweenie::AttachmentFu::Backends::S3Backend.distribution_domain
|
353
|
-
end
|
354
310
|
|
355
311
|
protected
|
356
312
|
# Called in the after_destroy callback
|
@@ -367,7 +323,9 @@ module Technoweenie # :nodoc:
|
|
367
323
|
old_full_filename,
|
368
324
|
full_filename,
|
369
325
|
bucket_name,
|
326
|
+
attachment_options[:s3_options].merge(
|
370
327
|
:access => attachment_options[:s3_access]
|
328
|
+
)
|
371
329
|
)
|
372
330
|
|
373
331
|
@old_filename = nil
|
@@ -380,8 +338,10 @@ module Technoweenie # :nodoc:
|
|
380
338
|
full_filename,
|
381
339
|
(temp_path ? File.open(temp_path) : temp_data),
|
382
340
|
bucket_name,
|
341
|
+
attachment_options[:s3_options].merge(
|
383
342
|
:content_type => content_type,
|
384
343
|
:access => attachment_options[:s3_access]
|
344
|
+
)
|
385
345
|
)
|
386
346
|
end
|
387
347
|
|