cloud_crooner 0.0.2 → 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 96c6f6bcbfc3bc6923aa74ee75f875a9c8be8f37
4
- data.tar.gz: df7ffd57e4962c7ad2343b2960c6a553d603301c
3
+ metadata.gz: 533f793c3642efdcd932c69ea38c14b294292435
4
+ data.tar.gz: a5e7391023ab13648bb09b18456d4005ddd6b902
5
5
  SHA512:
6
- metadata.gz: b522ae4cb68eeb23cb34421928954824fdecc6fd7ce894332916403f1492a696110401795d0adae3a4c63a09930e840748f66c98b4568dd91f1d6745db649383
7
- data.tar.gz: f7878e04dea4a3349fc84daddb4069dfd3a6c090e7d77de60728d446d49de18add7b9b5ea770d646da28d854532940f42e8933cd2fd0b0d53250317462c6d48b
6
+ metadata.gz: 3ce43f58924705bf3479a4d7b77746b082b7fc49044e50bf8b455d08648a23b84baf11a78627b59d0fef733c0c5a71225d9374dab49cfd6f9a2e0aabf9876399
7
+ data.tar.gz: 32c3c5c46cac86393ceccf6c9a3198b7aae8a9ae0ebe5f42ecb7ccb0380dd996475e4b0804c0256993e271729e1a27925b7b0c2cd49fa333581e7a0a6080bc27
data/CHANGELOG.md CHANGED
@@ -1,4 +1,11 @@
1
+ # v0.0.3
2
+ Features:
3
+ * Removed `remote_assets` option, replaced with `serve_assets` which allows for
4
+ serving local_static, remote, or local_dynamic assets in any environment (#1)
5
+ * comments converted into Rdoc compatible format instead of randomness
6
+
1
7
  # v0.0.2
8
+ Bugfix:
2
9
  * fixed bug where sync did not check for remote_enabled
3
10
 
4
11
  # v0.0.1
@@ -17,42 +17,66 @@ module CloudCrooner
17
17
 
18
18
  class << self
19
19
 
20
+ ##
21
+ # Convinience method for setting options and configuring helpers
22
+ #
20
23
  def configure(&proc)
21
24
  yield self
22
25
  configure_sprockets_helpers
23
26
  end
24
27
 
28
+ ##
29
+ # Set up the helpers to properly link to assets in current environment.
30
+ #
31
+ # If you're running fully on defaults, you must call this explicitly in
32
+ # config.ru if you want to use the helpers
33
+ #
25
34
  def configure_sprockets_helpers
26
- # if you're running fully on defaults, you must call this explicitly in config.ru if you want to use the helpers
27
35
  Sprockets::Helpers.configure do |config|
28
- if ENV['RACK_ENV'] == "production"
36
+ case serve_assets
37
+ when "remote"
29
38
  config.manifest = manifest
30
- config.digest = true
31
39
  config.debug = false
32
- if remote_enabled?
33
- config.asset_host = asset_host
34
- else
35
- config.public_path = public_folder
36
- end
40
+ config.asset_host = asset_host
41
+ when "local_static"
42
+ config.manifest = manifest
43
+ config.debug = false
44
+ config.public_path = public_folder
37
45
  end
38
46
  config.environment = sprockets
39
- config.prefix = "/" + prefix
47
+ config.prefix = '/' + prefix
48
+ config.digest = digest
40
49
  end
41
50
  end
42
51
 
43
52
  def storage
44
53
  @storage ||= Storage.new
45
54
  end
46
-
47
- def remote_enabled?
48
- # Disable this in prod if you want to serve compiled assets locally.
49
- @remote_enabled.nil? ? (@remote_enabled = true) : @remote_enabled
55
+
56
+ ##
57
+ # Where to serve assets from
58
+ # * "local_dynamic" : default in dev and test - serves assets from
59
+ # sprockets
60
+ # * "local_static" : serves compiled assets from public_folder
61
+ # * "remote" : default in prod - serves compiled assets from S3
62
+ #
63
+ def serve_assets
64
+ if @serve_assets.nil?
65
+ ENV['RACK_ENV'] == 'production' ? (@serve_assets = 'remote') : (@serve_assets = 'local_dynamic')
66
+ end
67
+ @serve_assets
50
68
  end
51
69
 
52
- def remote_enabled= (val)
53
- @remote_enabled = val if [ true, false ].include?(val)
70
+ def serve_assets= (val)
71
+ (@serve_assets = val) if [ 'local_dynamic',
72
+ 'local_static',
73
+ 'remote' ].include?(val)
54
74
  end
55
75
 
76
+ ##
77
+ # Returns or creates the Sprockets instance and adds asset_paths to the
78
+ # Sprockets load path.
79
+ #
56
80
  def sprockets
57
81
  if @sprockets.nil?
58
82
  @sprockets = Sprockets::Environment.new { |env| env.logger = Logger.new($stdout) }
@@ -62,11 +86,21 @@ module CloudCrooner
62
86
  end
63
87
  attr_writer :sprockets
64
88
 
89
+ ##
90
+ # Returns or creates the Sprockets manifest in public_folder/prefix.
91
+ #
65
92
  def manifest
66
93
  @manifest ||= Sprockets::Manifest.new(sprockets, File.join(public_folder, prefix))
67
94
  end
68
95
  attr_writer :manifest
69
96
 
97
+ ##
98
+ # Path from root to dynamic assets base folder. By default '/assets'.
99
+ #
100
+ # Also serves as the prefix under which S3 assets will be stored.
101
+ # Paths to assets from the helpers will look something like
102
+ # 'http://bucket-name.s3.amazonaws.com/prefix/filename'.
103
+ #
70
104
  def prefix
71
105
  @prefix ||= 'assets'
72
106
  end
@@ -76,6 +110,10 @@ module CloudCrooner
76
110
  @prefix = val.chomp('/').gsub(/^\//, "")
77
111
  end
78
112
 
113
+ ##
114
+ # The public folder of the application. By default '/public'. If a
115
+ # different folder is set, it must also be set on the Sinatra app.
116
+ #
79
117
  def public_folder
80
118
  @public_folder ||= 'public'
81
119
  end
@@ -85,17 +123,21 @@ module CloudCrooner
85
123
  @public_folder = val.chomp('/').gsub(/^\//, "")
86
124
  end
87
125
 
126
+ ##
127
+ # The list of assets to compile, given by their Sprocket's load path.
128
+ # Defaults to every file under the prefix directory.
129
+ #
88
130
  def assets_to_compile
89
- # list of assets to compile, given by their Sprocket's load path
90
- # defaults to every file under the prefix directory
91
131
  return @assets_to_compile if @assets_to_compile
92
132
  files = Dir.glob(prefix + "**/*").select {|f| File.file?(f)}
93
133
  files.collect! { |f| f.gsub(/^#{prefix}\//, "") }
94
134
  end
95
135
  attr_writer :assets_to_compile
96
136
 
97
- # AWS bucket name, can be stored in ENV but can be overwritten in config block
98
- # Defaults to ENV['AWS_BUCKET_NAME']
137
+ ##
138
+ # AWS bucket name. Defaults to ENV['AWS_BUCKET_NAME'] but can be
139
+ # overridden in config block. Required if using S3.
140
+ #
99
141
  def bucket_name
100
142
  if @bucket_name
101
143
  return @bucket_name
@@ -106,8 +148,11 @@ module CloudCrooner
106
148
  end
107
149
  attr_writer :bucket_name
108
150
 
109
- # Region of your AWS bucket
110
- # Defaults to looking in ENV but can be overwritten in config block
151
+ ##
152
+ # Region of AWS bucket. Defaults to ENV['AWS_REGION'] but can
153
+ # be overridden in config block. Must be a valid AWS region. Required
154
+ # if using S3.
155
+ #
111
156
  def region
112
157
  if @region
113
158
  return @region
@@ -123,9 +168,13 @@ module CloudCrooner
123
168
  VALID_AWS_REGIONS.include?(val) ? @region = val : (raise FogSettingError, "Invalid region")
124
169
  end
125
170
 
126
- # AWS access id key given by Amazon, should be stored in
127
- # env but can be set to be elsewhere.
128
- # Defaults to ENV["AWS_ACCESS_ID_KEY"]
171
+ ##
172
+ # AWS access id key given by Amazon. Defaults to ENV['AWS_ACCESS_KEY_ID']
173
+ # but can be overridden in config block. Required if using S3.
174
+ #
175
+ # Do not set value directly in app, store outside in a non-source
176
+ # controlled location.
177
+ #
129
178
  def aws_access_key_id
130
179
  if @aws_access_key_id
131
180
  return @aws_access_key_id
@@ -136,8 +185,14 @@ module CloudCrooner
136
185
  end
137
186
  attr_writer :aws_access_key_id
138
187
 
139
- # AWS secret access key given by Amazon, should be stored in env but can be set to be elsewhere
140
- # Defaults to ENV["AWS_SECRET_ACCESS_KEY"]
188
+ ##
189
+ # AWS secret access key given by Amazon. Defaults to
190
+ # ENV['AWS_SECRET_ACCESS_KEY'] but can be overridden in config block.
191
+ # Required if using S3.
192
+ #
193
+ # Do not set value directly in app, store outside in a non-source
194
+ # controlled location.
195
+ #
141
196
  def aws_secret_access_key
142
197
  if @aws_secret_access_key
143
198
  return @aws_secret_access_key
@@ -148,43 +203,71 @@ module CloudCrooner
148
203
  end
149
204
  attr_writer :aws_secret_access_key
150
205
 
206
+ ##
207
+ # Logical paths to assets for use with Sprockets. Defaults to "prefix"
208
+ # dir.
209
+ # If serve_assets is set to "remote" or "local_static", paths will be
210
+ # added, but the link helpers bypass Sprockets and grab the manifest
211
+ # links, and will only fall back to the paths if the asset is not found in
212
+ # the manifest.
213
+ #
151
214
  def asset_paths
152
- # logical paths to assets for use with Sprockets
153
- # default: everything under the prefix dir
154
- # note that if remote is enabled in prod, asset paths will be added, but the link helpers bypass sprockets and grab the manifest links, and will only fall back to the paths if the asset is not found in the manifest.
155
215
  @asset_paths ||= [prefix]
156
216
  end
157
217
  attr_writer :asset_paths
158
218
 
219
+ ##
220
+ # Number of compiled assets to keep as backups. Default is 2.
221
+ #
159
222
  def backups_to_keep
160
223
  @backups_to_keep ||= 2
161
224
  end
162
225
  attr_writer :backups_to_keep
163
226
 
227
+ ##
228
+ # Passed to Fog gem when creating a Storage instance
229
+ #
164
230
  def fog_options
165
- options = { :provider => provider, :aws_access_key_id => aws_access_key_id, :aws_secret_access_key => aws_secret_access_key, :region => region }
231
+ options = {
232
+ :provider => provider,
233
+ :aws_access_key_id => aws_access_key_id,
234
+ :aws_secret_access_key => aws_secret_access_key,
235
+ :region => region
236
+ }
166
237
  end
167
238
 
239
+ ##
240
+ # Compile the assets given in "assets_to_compile". Outputs to the directory
241
+ # of the manifest. Updates the manifest.
242
+ #
168
243
  def compile_sprockets_assets
169
- # compile the assets in the sprockets load path. Outputs to directory of manifest. Updates the manifest
170
244
  manifest.compile(*self.assets_to_compile)
171
245
  end
172
246
 
247
+ ##
248
+ # If there are more than the set number of compiled asset backups, the
249
+ # oldest asset will be deleted locally and removed from the manifest.
250
+ #
173
251
  def clean_sprockets_assets
174
- # if there are more backups than the requested number, delete the oldest from the file system and update the manifest
175
252
  manifest.clean(backups_to_keep)
176
253
  end
177
254
 
255
+ ##
256
+ # Delete the manifest's containing directory and everything in it.
257
+ #
178
258
  def clobber_sprockets_assets
179
- # delete the manifest directory and everything in it
180
259
  manifest.clobber
181
260
  end
182
261
 
262
+ ##
263
+ # Compile assets locally and remove old local backups. If serve_assets is
264
+ # "remote", it will upload changed files and delete old remote backups.
265
+ #
183
266
  def sync
184
267
  compile_sprockets_assets
185
268
  clean_sprockets_assets
186
269
 
187
- if remote_enabled?
270
+ if serve_assets == "remote"
188
271
  storage.upload_files
189
272
  storage.clean_remote
190
273
  end
@@ -197,18 +280,28 @@ module CloudCrooner
197
280
 
198
281
  private
199
282
 
283
+ ##
284
+ # Used with Fog to set the remote asset host. Allows for expansion into
285
+ # other cloud providers.
286
+ #
200
287
  def provider
201
288
  'AWS'
202
289
  end
203
290
 
291
+ ##
292
+ # Used with Sprockets Helpers to link to compiled (digest) or uncompiled
293
+ # assets (non digest). False if serving local uncompiled assets.
294
+ #
204
295
  def digest
205
- true
296
+ serve_assets == "local_dynamic" ? false : true
206
297
  end
207
298
 
299
+ ##
300
+ # Used with Sprockets Helpers to link to remote assets
301
+ #
208
302
  def asset_host
209
303
  @asset_host ||= "#{bucket_name}.s3.amazonaws.com"
210
304
  end
211
305
 
212
306
  end
213
307
  end
214
-
@@ -11,16 +11,24 @@ module CloudCrooner
11
11
  @manifest = CloudCrooner.manifest
12
12
  end
13
13
 
14
+ ##
15
+ # Creates a new Fog connection
16
+ #
14
17
  def connection
15
18
  @connection ||= Fog::Storage.new(@fog_options)
16
19
  end
17
20
 
21
+ ##
22
+ # Returns the remote assets
23
+ #
18
24
  def bucket
19
25
  @bucket ||= connection.directories.get(@bucket_name, :prefix => @prefix)
20
26
  end
21
27
 
28
+ ##
29
+ # Compiled assets prepended with prefix for comparison against remote
30
+ #
22
31
  def local_compiled_assets
23
- # compiled assets prepended with prefix for comparison against remote
24
32
  @manifest.files.keys.map {|f| File.join(@prefix, f)}
25
33
  end
26
34
 
@@ -28,6 +36,9 @@ module CloudCrooner
28
36
  bucket.files.head(file)
29
37
  end
30
38
 
39
+ ##
40
+ # Upload all new files to the bucket
41
+ #
31
42
  def upload_files
32
43
  files_to_upload = local_compiled_assets.reject { |f| exists_on_remote?(f) }
33
44
  files_to_upload.each do |asset|
@@ -39,6 +50,10 @@ module CloudCrooner
39
50
  CloudCrooner.log(msg)
40
51
  end
41
52
 
53
+ ##
54
+ # Uploads a file to the bucket. Sets expires header to one year. If a
55
+ # gzipped version of the file exists and is a smaller file size
56
+ #
42
57
  def upload_file(f)
43
58
  # grabs the compiled asset from public_path
44
59
  full_file_path = File.join(File.dirname(@manifest.dir), f)
@@ -54,7 +69,6 @@ module CloudCrooner
54
69
 
55
70
  gzipped = "#{full_file_path}.gz"
56
71
 
57
- # if a gzipped version of the file exists and is a smaller file size than the original, upload that in place of the uncompressed file
58
72
  if File.exists?(gzipped)
59
73
  original_size = File.size(full_file_path)
60
74
  gzipped_size = File.size(gzipped)
@@ -77,9 +91,9 @@ module CloudCrooner
77
91
  })
78
92
  log "Uploading #{f}"
79
93
  end
80
- # put in reduced redundancy option here later if desired
94
+ # put in reduced redundancy option here later if desired
81
95
 
82
- file = bucket.files.create( file )
96
+ file = bucket.files.create( file )
83
97
  end
84
98
 
85
99
  def remote_assets
@@ -93,6 +107,10 @@ module CloudCrooner
93
107
  f.destroy
94
108
  end
95
109
 
110
+ ##
111
+ # Analogue to CloudCrooner::cleansprockets_assets - deletes old backups
112
+ # of assets
113
+ #
96
114
  def clean_remote
97
115
  to_delete = remote_assets - local_compiled_assets
98
116
  to_delete.each do |f|
@@ -1,3 +1,3 @@
1
1
  module CloudCrooner
2
- VERSION = "0.0.2"
2
+ VERSION = "0.0.3"
3
3
  end
@@ -15,8 +15,16 @@ describe CloudCrooner do
15
15
  expect(CloudCrooner.public_folder).to eq("public")
16
16
  end
17
17
 
18
- it 'defaults to remote enabled' do
19
- expect(CloudCrooner.remote_enabled?).to be_true
18
+ it 'defaults to serving development assets dynamically' do
19
+ ENV.stub(:[]).with('RACK_ENV').and_return('development')
20
+
21
+ expect(CloudCrooner.serve_assets).to eq("local_dynamic")
22
+ end
23
+
24
+ it 'defaults to serving production assets remotely' do
25
+ ENV.stub(:[]).with("RACK_ENV").and_return("production")
26
+
27
+ expect(CloudCrooner.serve_assets).to eq("remote")
20
28
  end
21
29
 
22
30
  it "defaults to looking for assets in '/assets'" do
@@ -120,18 +128,18 @@ describe CloudCrooner do
120
128
  end # construct
121
129
  end # it
122
130
 
123
- it 'initializes sprockets-helpers in development' do
131
+ it 'initializes sprockets-helpers in development to serve dynamic assets' do
124
132
  within_construct do |c|
133
+ ENV.stub(:[]).with('RACK_ENV').and_return('development')
125
134
  c.file 'assets/a.css'
126
135
  CloudCrooner.configure_sprockets_helpers
127
136
 
128
- expect(Sprockets::Helpers.prefix).to eq('/assets')
137
+ expect(CloudCrooner.send(:digest)).to be_false
129
138
  expect(context.stylesheet_tag('a.css')).to eq(%Q(<link rel="stylesheet" href="/assets/a.css">))
130
-
131
139
  end # context
132
140
  end #it
133
141
 
134
- it 'initizalizes sprockets-helpers in production' do
142
+ it 'initizalizes sprockets-helpers in production to serve remote static assets' do
135
143
  within_construct do |c|
136
144
  c.file 'assets/a.css'
137
145
  stub_env_vars
@@ -139,7 +147,9 @@ describe CloudCrooner do
139
147
  CloudCrooner.configure_sprockets_helpers
140
148
  CloudCrooner.manifest.compile('a.css')
141
149
 
150
+ expect(CloudCrooner.send(:digest)).to be_true
142
151
  expect(context.asset_path('a.css')).to eq("http://my-bucket.s3.amazonaws.com/assets/#{CloudCrooner.sprockets['a.css'].digest_path}")
152
+
143
153
  end # construct
144
154
  end # it
145
155
 
@@ -169,33 +179,60 @@ describe CloudCrooner do
169
179
  end
170
180
  end
171
181
 
172
- it 'can disable remote asset host' do
173
- CloudCrooner.remote_enabled = false
174
- expect(CloudCrooner.remote_enabled?).to be_false
182
+ it 'initializes sprockets-helpers when serving local static assets in prod' do
183
+ within_construct do |c|
184
+ c.file 'assets/a.css'
185
+ CloudCrooner.manifest.compile('a.css')
186
+ ENV.stub(:[]).with('RACK_ENV').and_return('production')
187
+
188
+ CloudCrooner.serve_assets = "local_static"
189
+ CloudCrooner.configure_sprockets_helpers
190
+
191
+ expect(context.asset_path('a.css')).to eq("/assets/#{CloudCrooner.sprockets['a.css'].digest_path}")
192
+ end
175
193
  end
176
194
 
177
- it 'initializes sprockets-helpers when remote is disabled' do
195
+ it 'intializes sprockets-helpers when serving dynamic assets in prod' do
178
196
  within_construct do |c|
179
- # compile the manifest and asset in dev
180
197
  c.file 'assets/a.css'
181
- c.directory 'public/assets'
182
- manifest = Sprockets::Manifest.new(CloudCrooner.sprockets, 'public/assets')
183
- CloudCrooner.manifest = manifest
184
198
  CloudCrooner.manifest.compile('a.css')
199
+ ENV.stub(:[]).with('RACK_ENV').and_return('production')
200
+
201
+ CloudCrooner.serve_assets = "local_dynamic"
202
+ CloudCrooner.configure_sprockets_helpers
185
203
 
186
- # reload the app & helpers in production
187
- reload_crooner
204
+ expect(context.stylesheet_tag('a.css')).to eq(%Q(<link rel="stylesheet" href="/assets/a.css">))
205
+ end
206
+ end
188
207
 
189
- ENV.stub(:[]).with('RACK_ENV').and_return('production')
190
- CloudCrooner.configure do |config|
191
- config.manifest = manifest
192
- config.remote_enabled = false
193
- end
208
+ it 'initializes sprockets-helpers when serving local static assets in dev' do
209
+ within_construct do |c|
210
+ c.file 'assets/a.css'
211
+ CloudCrooner.manifest.compile('a.css')
212
+ ENV.stub(:[]).with('RACK_ENV').and_return('development')
213
+
214
+ CloudCrooner.serve_assets = "local_static"
215
+ CloudCrooner.configure_sprockets_helpers
194
216
 
195
- expect(context.asset_path('a.css')).to eq("/assets/#{CloudCrooner.manifest.assets['a.css']}")
217
+ expect(context.asset_path('a.css')).to eq("/assets/#{CloudCrooner.sprockets['a.css'].digest_path}")
196
218
  end
197
219
  end
198
220
 
221
+ it 'initializes sprockets-helpers when serving remote assets in dev' do
222
+ within_construct do |c|
223
+ c.file 'assets/a.css'
224
+ stub_env_vars
225
+ ENV.stub(:[]).with('RACK_ENV').and_return("development")
226
+
227
+ CloudCrooner.serve_assets = 'remote'
228
+ CloudCrooner.configure_sprockets_helpers
229
+ CloudCrooner.manifest.compile('a.css')
230
+
231
+ expect(CloudCrooner.send(:digest)).to be_true
232
+ expect(context.asset_path('a.css')).to eq("http://my-bucket.s3.amazonaws.com/assets/#{CloudCrooner.sprockets['a.css'].digest_path}")
233
+ end # construct
234
+ end # it
235
+
199
236
  it 'accepts a custom manifest' do
200
237
  within_construct do |c|
201
238
  manifest = Sprockets::Manifest.new(CloudCrooner.sprockets, 'foo/bar')
@@ -305,10 +342,13 @@ describe CloudCrooner do
305
342
  end # construct
306
343
  end # it
307
344
 
308
- it 'compiles and syncs assets to the cloud', :moo => true do
345
+ it 'compiles and syncs assets to the cloud' do
309
346
  within_construct do |c|
310
347
  mock_environment(c)
311
- CloudCrooner.assets_to_compile = ['a.css', 'b.css']
348
+ CloudCrooner.configure do |config|
349
+ config.assets_to_compile = ['a.css', 'b.css']
350
+ config.serve_assets = "remote"
351
+ end
312
352
  mock_fog(CloudCrooner.storage)
313
353
  CloudCrooner.sync
314
354
 
@@ -321,7 +361,7 @@ describe CloudCrooner do
321
361
  mock_environment(c)
322
362
  CloudCrooner.configure do |config|
323
363
  config.assets_to_compile = ['a.css', 'b.css']
324
- config.remote_enabled = false
364
+ config.serve_assets = 'local_static'
325
365
  end
326
366
  mock_fog(CloudCrooner.storage)
327
367
  CloudCrooner.sync
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cloud_crooner
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.2
4
+ version: 0.0.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - bambery
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2013-08-14 00:00:00.000000000 Z
11
+ date: 2013-08-25 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler