anaconda 1.0.11 → 2.0.2
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.
- checksums.yaml +4 -4
- data/README.markdown +23 -6
- data/lib/anaconda.rb +12 -5
- data/lib/anaconda/anaconda_for.rb +43 -20
- data/lib/anaconda/version.rb +1 -1
- metadata +1 -1
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 57868170a368b59a870fd5cd967b553e13b65583
|
4
|
+
data.tar.gz: 2c2cc0aae3cb3b388fae8a251d43dcb28e06524d
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 852057515f6e9b772a4b39dd6bc73f812f058e4234884945744f0a8016db7c88751f429336aac94df4cc4a922c15a1fc04118dbfa55f827601c3585e970b9c46
|
7
|
+
data.tar.gz: 2cdfad1b498549f0fe7f268e3a0ec44fdcd967361dfd582b7712e77640aac0cc73856f7e0532b3631195099a07e381319bc036b2c4e73cfc9be639f28931afd6
|
data/README.markdown
CHANGED
@@ -126,17 +126,20 @@ We highly recommend the `figaro` gem [https://github.com/laserlemon/figaro](http
|
|
126
126
|
|
127
127
|
At this time the available options on anaconda_for are:
|
128
128
|
* `base_key` default: _%{plural model}/%{plural column}/%{random string}_
|
129
|
-
* `
|
130
|
-
* `
|
131
|
-
* `
|
129
|
+
* `aws_access_key` default: _aws_access_key_ specified in Anaconda config
|
130
|
+
* `aws_secret_key` default: _aws_secret_key_ specified in Anaconda config
|
131
|
+
* `aws_bucket` default: _aws_bucket_ specified in Anaconda config
|
132
|
+
* `aws_endpoint` default: _aws_endpoint_ specified in Anaconda config
|
132
133
|
* `acl` default _public-read_
|
133
134
|
* `max_file_size` default: `500.megabytes`
|
134
135
|
* `allowed_file_types` default: _all_
|
135
136
|
* `host` String. If specified, this will be used to access publically stored objects instead of the S3 bucket. Useful for CloudFront integration. Note: At this time privately stored objects will still be requested via S3. Default: _false_
|
136
137
|
* `protocol` `https`, `http`, or `:auto`. If `:auto`, `//` will be used as the protocol. Note: At this time, all privately stored objects are requested over https. Default: `http`
|
137
|
-
|
138
|
-
|
139
|
-
|
138
|
+
* `remove_previous_s3_files_on_change` Boolean. If true, files will be removed from S3 when a new file is uploaded. Default: `true`
|
139
|
+
* `remove_previous_s3_files_on_destroy` Boolean. If true, files will be removed from S3 when a record is destroyed. Default: `true`
|
140
|
+
* `expiry_length` - If supplied, this is the length in seconds that a signed URL is valid for. Default: `1.hour`
|
141
|
+
|
142
|
+
Any `anaconda_for` option may also be a proc that will be evaluated in the context of the current instance.
|
140
143
|
|
141
144
|
* Form setup
|
142
145
|
|
@@ -219,6 +222,20 @@ If you return false to the following events it will prevent the default behavior
|
|
219
222
|
From version 1.0.0 on we have used [Semantic Versioning](http://semver.org/).
|
220
223
|
|
221
224
|
## Changelog
|
225
|
+
* 2.0.2
|
226
|
+
* Fix `asset_url` method. There's tests coming. I swear.
|
227
|
+
|
228
|
+
* 2.0.1
|
229
|
+
YANKED
|
230
|
+
* Fix `asset_download_url` method
|
231
|
+
|
232
|
+
* 2.0.0
|
233
|
+
YANKED
|
234
|
+
*Breaking Changes!*
|
235
|
+
* The options you can pass to `anaconda_for` have changed.
|
236
|
+
* Add ability for `anaconda_for` options to be procs so we can have instance specific data there.
|
237
|
+
* Clean the `filename` that is passed to the `asset_download_url` method
|
238
|
+
|
222
239
|
* 1.0.11
|
223
240
|
* Add ability to pass `filename` to the `asset_download_url` method.
|
224
241
|
|
data/lib/anaconda.rb
CHANGED
@@ -32,8 +32,15 @@ module Anaconda
|
|
32
32
|
def self.config
|
33
33
|
yield self
|
34
34
|
|
35
|
-
|
36
|
-
|
35
|
+
if @@aws[:aws_bucket].present?
|
36
|
+
@@aws[:aws_endpoint] = "s3.amazonaws.com/#{@@aws[:aws_bucket]}" unless @@aws[:aws_endpoint].present?
|
37
|
+
end
|
38
|
+
|
39
|
+
if @@aws[:aws_endpoint].present? && @@aws[:aws_bucket].present?
|
40
|
+
@@aws[:path_style] = !@@aws[:aws_endpoint].starts_with?(@@aws[:aws_bucket])
|
41
|
+
else
|
42
|
+
@@aws[:path_style] = false
|
43
|
+
end
|
37
44
|
end
|
38
45
|
|
39
46
|
def self.js_file_types
|
@@ -55,8 +62,8 @@ module Anaconda
|
|
55
62
|
return js_file_types
|
56
63
|
end
|
57
64
|
|
58
|
-
def self.
|
59
|
-
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id =>
|
60
|
-
aws.delete_object(
|
65
|
+
def self.remove_s3_object(file_path, options)
|
66
|
+
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id => options[:aws_access_key], :aws_secret_access_key => options[:aws_secret_key], :path_style => options[:aws_use_path_style]})
|
67
|
+
aws.delete_object(options[:aws_bucket], file_path)
|
61
68
|
end
|
62
69
|
end
|
@@ -30,9 +30,11 @@ module Anaconda
|
|
30
30
|
end
|
31
31
|
self.anaconda_options = Hash.new unless self.anaconda_options.kind_of? Hash
|
32
32
|
self.anaconda_options[anaconda_column.to_sym] = options.reverse_merge(
|
33
|
-
|
34
|
-
|
35
|
-
|
33
|
+
aws_access_key: Anaconda.aws[:aws_access_key],
|
34
|
+
aws_secret_key: Anaconda.aws[:aws_secret_key],
|
35
|
+
aws_bucket: Anaconda.aws[:aws_bucket],
|
36
|
+
aws_endpoint: Anaconda.aws[:aws_endpoint],
|
37
|
+
aws_use_path_style: Anaconda.aws[:path_style],
|
36
38
|
acl: "public-read",
|
37
39
|
max_file_size: 500.megabytes,
|
38
40
|
allowed_file_types: [],
|
@@ -112,52 +114,73 @@ module Anaconda
|
|
112
114
|
end
|
113
115
|
end
|
114
116
|
|
117
|
+
def anaconda_options_for( anaconda_column )
|
118
|
+
if self.class.anaconda_columns.include? anaconda_column.to_sym
|
119
|
+
self.anaconda_options[anaconda_column].inject({}) do |hash, (k, v)|
|
120
|
+
if v.kind_of? Proc
|
121
|
+
hash[k] = self.instance_exec(&v)
|
122
|
+
else
|
123
|
+
hash[k] = v
|
124
|
+
end
|
125
|
+
hash
|
126
|
+
end
|
127
|
+
else
|
128
|
+
raise "#{anaconda_column} not configured for anaconda. Misspelling or did you forget to add the anaconda_for call for this field?"
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
115
132
|
private
|
116
133
|
def anaconda_url(column_name, *args)
|
117
134
|
return nil unless send("#{column_name}_file_path").present?
|
118
135
|
options = args.extract_options!
|
119
|
-
|
136
|
+
options = options.reverse_merge(self.anaconda_options_for( column_name ))
|
137
|
+
logger.debug "Options:"
|
120
138
|
logger.debug(options)
|
121
139
|
|
122
140
|
if send("#{column_name}_stored_privately")
|
123
|
-
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id =>
|
124
|
-
aws.get_object_https_url(
|
125
|
-
elsif
|
141
|
+
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id => options[:aws_access_key], :aws_secret_access_key => options[:aws_secret_key], :path_style => options[:aws_use_path_style]})
|
142
|
+
aws.get_object_https_url(options[:aws_bucket], send("#{column_name}_file_path"), anaconda_expiry_length(column_name, options[:expires]))
|
143
|
+
elsif options[:host]
|
126
144
|
"#{anaconda_protocol(column_name, options[:protocol])}#{self.anaconda_options[column_name.to_sym][:host]}/#{send("#{column_name}_file_path")}"
|
127
145
|
else
|
128
|
-
"#{anaconda_protocol(column_name, options[:protocol])}#{
|
146
|
+
"#{anaconda_protocol(column_name, options[:protocol])}#{options[:aws_endpoint]}/#{send("#{column_name}_file_path")}"
|
129
147
|
end
|
130
148
|
end
|
131
149
|
|
132
150
|
def anaconda_download_url(column_name, *args)
|
133
151
|
return nil unless send("#{column_name}_file_path").present?
|
134
152
|
options = args.extract_options!
|
135
|
-
|
153
|
+
options = options.reverse_merge(self.anaconda_options_for( column_name ))
|
154
|
+
logger.debug "Options:"
|
136
155
|
logger.debug(options)
|
156
|
+
|
137
157
|
filename = nil
|
138
158
|
if options[:filename].present?
|
139
|
-
|
159
|
+
clean_filename = options[:filename].gsub(/[^0-9A-Za-z.\-\ \(\)]/, '-')
|
160
|
+
logger.debug "Cleaned Filename: #{clean_filename}"
|
161
|
+
filename = "filename=#{clean_filename}"
|
140
162
|
end
|
141
163
|
|
142
164
|
aws_options = {query: {"response-content-disposition" => "attachment;#{filename}"}}
|
143
|
-
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id =>
|
144
|
-
aws.get_object_https_url(
|
165
|
+
aws = Fog::Storage.new({:provider => 'AWS', :aws_access_key_id => options[:aws_access_key], :aws_secret_access_key => options[:aws_secret_key], :path_style => options[:aws_use_path_style]})
|
166
|
+
aws.get_object_https_url(options[:aws_bucket], send("#{column_name}_file_path"), anaconda_expiry_length(column_name, options[:expires]), aws_options)
|
145
167
|
|
146
168
|
end
|
147
169
|
|
148
170
|
def anaconda_protocol(column_name, override = nil)
|
149
|
-
return override if override
|
150
|
-
|
171
|
+
return "#{override}://" if override
|
172
|
+
|
173
|
+
case self.anaconda_options_for( column_name )[:protocol]
|
151
174
|
when :auto
|
152
175
|
"//"
|
153
176
|
else
|
154
|
-
"#{self.
|
177
|
+
"#{self.anaconda_options_for( column_name )[:protocol]}://"
|
155
178
|
end
|
156
179
|
end
|
157
180
|
|
158
181
|
def anaconda_expiry_length(column_name, override = nil)
|
159
182
|
return override if override
|
160
|
-
self.
|
183
|
+
self.anaconda_options_for( column_name )[:expiry_length].seconds.from_now
|
161
184
|
end
|
162
185
|
|
163
186
|
def anaconda_default_base_key_for(column_name)
|
@@ -168,21 +191,21 @@ module Anaconda
|
|
168
191
|
|
169
192
|
if self.destroyed?
|
170
193
|
self.class.anaconda_columns.each do |column_name|
|
171
|
-
next unless self.
|
194
|
+
next unless self.anaconda_options_for( column_name )[:remove_previous_s3_files_on_destroy]
|
172
195
|
if self.send("#{column_name}_file_path").present?
|
173
|
-
Anaconda.
|
196
|
+
Anaconda.remove_s3_object(self.send("#{column_name}_file_path"), self.anaconda_options_for( column_name ))
|
174
197
|
end
|
175
198
|
end
|
176
199
|
else
|
177
200
|
self.class.anaconda_columns.each do |column_name|
|
178
|
-
next unless self.
|
201
|
+
next unless self.anaconda_options_for( column_name )[:remove_previous_s3_files_on_change]
|
179
202
|
if self.previous_changes["#{column_name}_file_path"].present?
|
180
203
|
# Looks like this field was edited.
|
181
204
|
if self.previous_changes["#{column_name}_file_path"][0].present? &&
|
182
205
|
self.previous_changes["#{column_name}_file_path"][0] != self.previous_changes["#{column_name}_file_path"][1]
|
183
206
|
# It's not a new entry ([0] would be nil), and it really did change, wasn't just committed for no reason
|
184
207
|
# So let's delete the previous file from S3
|
185
|
-
Anaconda.
|
208
|
+
Anaconda.remove_s3_object(self.previous_changes["#{column_name}_file_path"][0], self.anaconda_options_for( column_name ))
|
186
209
|
end
|
187
210
|
end
|
188
211
|
end
|
data/lib/anaconda/version.rb
CHANGED