beet 0.4.2 → 0.4.3

Sign up to get free protection for your applications and to get access to all the features.
data/README.rdoc CHANGED
@@ -6,4 +6,4 @@ Please visit the homepage to learn more: http://jackdempsey.github.com/beet
6
6
 
7
7
  == Copyright
8
8
 
9
- Copyright (c) 2009 Jack Dempsey. See LICENSE for details.
9
+ Copyright (c) 2010 Jack Dempsey. See LICENSE for details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.4.2
1
+ 0.4.3
data/beet.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{beet}
8
- s.version = "0.4.2"
8
+ s.version = "0.4.3"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Jack Dempsey"]
12
- s.date = %q{2009-12-14}
12
+ s.date = %q{2010-01-09}
13
13
  s.default_executable = %q{beet}
14
14
  s.email = %q{jack.dempsey@gmail.com}
15
15
  s.executables = ["beet"]
@@ -37,6 +37,10 @@ Gem::Specification.new do |s|
37
37
  "lib/beet/execution.rb",
38
38
  "lib/beet/executor.rb",
39
39
  "lib/beet/file_system.rb",
40
+ "lib/beet/files/swfupload/images/cancelbutton.gif",
41
+ "lib/beet/files/swfupload/images/header-bg.jpg",
42
+ "lib/beet/files/swfupload/images/logo.gif",
43
+ "lib/beet/files/swfupload/js/handlers.js",
40
44
  "lib/beet/gem_location_map.rb",
41
45
  "lib/beet/interaction.rb",
42
46
  "lib/beet/logger.rb",
@@ -52,10 +56,12 @@ Gem::Specification.new do |s|
52
56
  "lib/beet/recipes/rails/css/blueprint.rb",
53
57
  "lib/beet/recipes/rails/css/nifty_layout.rb",
54
58
  "lib/beet/recipes/rails/css/reset.rb",
59
+ "lib/beet/recipes/rails/db/mongo.rb",
55
60
  "lib/beet/recipes/rails/db/mysql.rb",
56
61
  "lib/beet/recipes/rails/db/postgres.rb",
57
62
  "lib/beet/recipes/rails/git.rb",
58
63
  "lib/beet/recipes/rails/jquery.rb",
64
+ "lib/beet/recipes/rails/swfupload.rb",
59
65
  "lib/beet/recipes/rails/testing/rspec.rb",
60
66
  "lib/beet/recipes/rails/testing/shoulda.rb",
61
67
  "lib/beet/scm.rb",
@@ -0,0 +1,290 @@
1
+ function fileQueueError(file, errorCode, message) {
2
+ try {
3
+ var imageName = "error.gif";
4
+ var errorName = "";
5
+ if (errorCode === SWFUpload.errorCode_QUEUE_LIMIT_EXCEEDED) {
6
+ errorName = "You have attempted to queue too many files.";
7
+ }
8
+
9
+ if (errorName !== "") {
10
+ alert(errorName);
11
+ return;
12
+ }
13
+
14
+ switch (errorCode) {
15
+ case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
16
+ imageName = "zerobyte.gif";
17
+ break;
18
+ case SWFUpload.QUEUE_ERROR.FILE_EXCEEDS_SIZE_LIMIT:
19
+ imageName = "toobig.gif";
20
+ break;
21
+ case SWFUpload.QUEUE_ERROR.ZERO_BYTE_FILE:
22
+ case SWFUpload.QUEUE_ERROR.INVALID_FILETYPE:
23
+ default:
24
+ alert(message);
25
+ break;
26
+ }
27
+
28
+ addImage("images/swfupload/" + imageName);
29
+
30
+ } catch (ex) {
31
+ this.debug(ex);
32
+ }
33
+
34
+ }
35
+
36
+ function fileDialogComplete(numFilesSelected, numFilesQueued) {
37
+ try {
38
+ if (numFilesQueued > 0) {
39
+ this.startUpload();
40
+ }
41
+ } catch (ex) {
42
+ this.debug(ex);
43
+ }
44
+ }
45
+
46
+ function uploadProgress(file, bytesLoaded) {
47
+
48
+ try {
49
+ var percent = Math.ceil((bytesLoaded / file.size) * 100);
50
+
51
+ var progress = new FileProgress(file, this.customSettings.upload_target);
52
+ progress.setProgress(percent);
53
+ if (percent === 100) {
54
+ progress.setStatus("Processing file...");
55
+ progress.toggleCancel(false, this);
56
+ } else {
57
+ progress.setStatus("Uploading...");
58
+ progress.toggleCancel(true, this);
59
+ }
60
+ } catch (ex) {
61
+ this.debug(ex);
62
+ }
63
+ }
64
+
65
+ function uploadSuccess(file, serverData) {
66
+ try {
67
+ $('#mp3info').append("<p>"+serverData+"</p>");
68
+ var progress = new FileProgress(file, this.customSettings.upload_target);
69
+
70
+ if (serverData.substring(0, 2) === "OK") {
71
+ //addImage("thumbnail.php?id=" + serverData.substring(7));
72
+
73
+ progress.setStatus("Upload Successfull.");
74
+ progress.toggleCancel(false);
75
+ } else {
76
+ addImage("/images/swfupload/error.gif");
77
+ progress.setStatus("Error.");
78
+ progress.toggleCancel(false);
79
+ alert(serverData);
80
+
81
+ }
82
+
83
+
84
+ } catch (ex) {
85
+ this.debug(ex);
86
+ }
87
+ }
88
+
89
+ function uploadComplete(file) {
90
+ try {
91
+ /* I want the next upload to continue automatically so I'll call startUpload here */
92
+ if (this.getStats().files_queued > 0) {
93
+ this.startUpload();
94
+ } else {
95
+ var progress = new FileProgress(file, this.customSettings.upload_target);
96
+ progress.setComplete();
97
+ progress.setStatus("All files received.");
98
+ progress.toggleCancel(false);
99
+ }
100
+ } catch (ex) {
101
+ this.debug(ex);
102
+ }
103
+ }
104
+
105
+ function uploadError(file, errorCode, message) {
106
+ var imageName = "error.gif";
107
+ var progress;
108
+ try {
109
+ switch (errorCode) {
110
+ case SWFUpload.UPLOAD_ERROR.FILE_CANCELLED:
111
+ try {
112
+ progress = new FileProgress(file, this.customSettings.upload_target);
113
+ progress.setCancelled();
114
+ progress.setStatus("Cancelled");
115
+ progress.toggleCancel(false);
116
+ }
117
+ catch (ex1) {
118
+ this.debug(ex1);
119
+ }
120
+ break;
121
+ case SWFUpload.UPLOAD_ERROR.UPLOAD_STOPPED:
122
+ try {
123
+ progress = new FileProgress(file, this.customSettings.upload_target);
124
+ progress.setCancelled();
125
+ progress.setStatus("Stopped");
126
+ progress.toggleCancel(true);
127
+ }
128
+ catch (ex2) {
129
+ this.debug(ex2);
130
+ }
131
+ case SWFUpload.UPLOAD_ERROR.UPLOAD_LIMIT_EXCEEDED:
132
+ imageName = "uploadlimit.gif";
133
+ break;
134
+ default:
135
+ alert(message);
136
+ break;
137
+ }
138
+
139
+ addImage("/images/swfupload/" + imageName);
140
+
141
+ } catch (ex3) {
142
+ this.debug(ex3);
143
+ }
144
+
145
+ }
146
+
147
+
148
+ function addImage(src) {
149
+ var newImg = document.createElement("img");
150
+ newImg.style.margin = "5px";
151
+
152
+ document.getElementById("thumbnails").appendChild(newImg);
153
+ if (newImg.filters) {
154
+ try {
155
+ newImg.filters.item("DXImageTransform.Microsoft.Alpha").opacity = 0;
156
+ } catch (e) {
157
+ // If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
158
+ newImg.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + 0 + ')';
159
+ }
160
+ } else {
161
+ newImg.style.opacity = 0;
162
+ }
163
+
164
+ newImg.onload = function () {
165
+ fadeIn(newImg, 0);
166
+ };
167
+ newImg.src = src;
168
+ }
169
+
170
+ function fadeIn(element, opacity) {
171
+ var reduceOpacityBy = 5;
172
+ var rate = 30; // 15 fps
173
+
174
+
175
+ if (opacity < 100) {
176
+ opacity += reduceOpacityBy;
177
+ if (opacity > 100) {
178
+ opacity = 100;
179
+ }
180
+
181
+ if (element.filters) {
182
+ try {
183
+ element.filters.item("DXImageTransform.Microsoft.Alpha").opacity = opacity;
184
+ } catch (e) {
185
+ // If it is not set initially, the browser will throw an error. This will set it if it is not set yet.
186
+ element.style.filter = 'progid:DXImageTransform.Microsoft.Alpha(opacity=' + opacity + ')';
187
+ }
188
+ } else {
189
+ element.style.opacity = opacity / 100;
190
+ }
191
+ }
192
+
193
+ if (opacity < 100) {
194
+ setTimeout(function () {
195
+ fadeIn(element, opacity);
196
+ }, rate);
197
+ }
198
+ }
199
+
200
+
201
+
202
+ /* ******************************************
203
+ * FileProgress Object
204
+ * Control object for displaying file info
205
+ * ****************************************** */
206
+
207
+ function FileProgress(file, targetID) {
208
+ this.fileProgressID = "divFileProgress";
209
+
210
+ this.fileProgressWrapper = document.getElementById(this.fileProgressID);
211
+ if (!this.fileProgressWrapper) {
212
+ this.fileProgressWrapper = document.createElement("div");
213
+ this.fileProgressWrapper.className = "progressWrapper";
214
+ this.fileProgressWrapper.id = this.fileProgressID;
215
+
216
+ this.fileProgressElement = document.createElement("div");
217
+ this.fileProgressElement.className = "progressContainer";
218
+
219
+ var progressCancel = document.createElement("a");
220
+ progressCancel.className = "progressCancel";
221
+ progressCancel.href = "#";
222
+ progressCancel.style.visibility = "hidden";
223
+ progressCancel.appendChild(document.createTextNode(" "));
224
+
225
+ var progressText = document.createElement("div");
226
+ progressText.className = "progressName";
227
+ progressText.appendChild(document.createTextNode(file.name));
228
+
229
+ var progressBar = document.createElement("div");
230
+ progressBar.className = "progressBarInProgress";
231
+
232
+ var progressStatus = document.createElement("div");
233
+ progressStatus.className = "progressBarStatus";
234
+ progressStatus.innerHTML = "&nbsp;";
235
+
236
+ this.fileProgressElement.appendChild(progressCancel);
237
+ this.fileProgressElement.appendChild(progressText);
238
+ this.fileProgressElement.appendChild(progressStatus);
239
+ this.fileProgressElement.appendChild(progressBar);
240
+
241
+ this.fileProgressWrapper.appendChild(this.fileProgressElement);
242
+
243
+ document.getElementById(targetID).appendChild(this.fileProgressWrapper);
244
+ fadeIn(this.fileProgressWrapper, 0);
245
+
246
+ } else {
247
+ this.fileProgressElement = this.fileProgressWrapper.firstChild;
248
+ this.fileProgressElement.childNodes[1].firstChild.nodeValue = file.name;
249
+ }
250
+
251
+ this.height = this.fileProgressWrapper.offsetHeight;
252
+
253
+ }
254
+ FileProgress.prototype.setProgress = function (percentage) {
255
+ this.fileProgressElement.className = "progressContainer green";
256
+ this.fileProgressElement.childNodes[3].className = "progressBarInProgress";
257
+ this.fileProgressElement.childNodes[3].style.width = percentage + "%";
258
+ };
259
+ FileProgress.prototype.setComplete = function () {
260
+ this.fileProgressElement.className = "progressContainer blue";
261
+ this.fileProgressElement.childNodes[3].className = "progressBarComplete";
262
+ this.fileProgressElement.childNodes[3].style.width = "";
263
+
264
+ };
265
+ FileProgress.prototype.setError = function () {
266
+ this.fileProgressElement.className = "progressContainer red";
267
+ this.fileProgressElement.childNodes[3].className = "progressBarError";
268
+ this.fileProgressElement.childNodes[3].style.width = "";
269
+
270
+ };
271
+ FileProgress.prototype.setCancelled = function () {
272
+ this.fileProgressElement.className = "progressContainer";
273
+ this.fileProgressElement.childNodes[3].className = "progressBarError";
274
+ this.fileProgressElement.childNodes[3].style.width = "";
275
+
276
+ };
277
+ FileProgress.prototype.setStatus = function (status) {
278
+ this.fileProgressElement.childNodes[2].innerHTML = status;
279
+ };
280
+
281
+ FileProgress.prototype.toggleCancel = function (show, swfuploadInstance) {
282
+ this.fileProgressElement.childNodes[0].style.visibility = show ? "visible" : "hidden";
283
+ if (swfuploadInstance) {
284
+ var fileID = this.fileProgressID;
285
+ this.fileProgressElement.childNodes[0].onclick = function () {
286
+ swfuploadInstance.cancelUpload(fileID);
287
+ return false;
288
+ };
289
+ }
290
+ };
@@ -1,5 +1,5 @@
1
- gem 'warden', :version => '~> 0.5.1'
2
- gem 'devise', :version => '~> 0.4.1'
1
+ gem 'warden', :version => '~> 0.6.5'
2
+ gem 'devise', :version => '~> 0.7.1'
3
3
 
4
4
  rake 'gems:install'
5
5
  generate "devise_install"
@@ -13,8 +13,7 @@ add_after 'config/routes.rb', '# map.root :controller => "welcome"', "\n map.ro
13
13
  rake "db:migrate"
14
14
 
15
15
  file 'app/controllers/home_controller.rb' do
16
- %{
17
- class HomeController < ApplicationController
16
+ %{class HomeController < ApplicationController
18
17
  def index
19
18
  render :text => "Welcome!"
20
19
  end
@@ -0,0 +1,57 @@
1
+ # based on jnunemaker's gist at http://gist.github.com/232953
2
+ file 'config/database.yml' do
3
+ %{
4
+ development: &global_settings
5
+ database: #{project_name}_development
6
+ host: 127.0.0.1
7
+ port: 27017
8
+
9
+ test:
10
+ database: #{project_name}_test
11
+ <<: *global_settings
12
+
13
+ production:
14
+ host: hostname
15
+ database: databasename
16
+ username: username
17
+ password: password
18
+ <<: *global_settings
19
+ }
20
+ end
21
+
22
+ file 'config/initializers/mongo.rb' do
23
+ %{
24
+ config = YAML.load_file(Rails.root + 'config' + 'database.yml')[Rails.env]
25
+
26
+ MongoMapper.connection = Mongo::Connection.new(config['host'], config['port'], {
27
+ :logger => Rails.logger
28
+ })
29
+
30
+ MongoMapper.database = config['database']
31
+ if config['username'].present?
32
+ MongoMapper.database.authenticate(config['username'], config['password'])
33
+ end
34
+
35
+ Dir[Rails.root + 'app/models/**/*.rb'].each do |model_path|
36
+ File.basename(model_path, '.rb').classify.constantize
37
+ end
38
+ MongoMapper.ensure_indexes!
39
+
40
+ if defined?(PhusionPassenger)
41
+ PhusionPassenger.on_event(:starting_worker_process) do |forked|
42
+ # if using older than 0.6.5 of MM then you want database instead of connection
43
+ # MongoMapper.database.connect_to_master if forked
44
+ MongoMapper.connection.connect_to_master if forked
45
+ end
46
+ end
47
+ }
48
+ end
49
+
50
+ # for those who don't like keeping database.yml in version control
51
+ # we slot in an example file to serve as reference
52
+
53
+ FileUtils.copy "config/database.yml", "config/database.yml.example"
54
+
55
+ environment 'config.frameworks -= [:active_record]'
56
+
57
+ gem 'mongo_mapper'
@@ -0,0 +1,305 @@
1
+ # lots of code and ideas borrowed from http://jetpackweb.com/blog/2009/10/21/rails-2-3-4-and-swfupload-rack-middleware-for-flash-uploads-that-degrade-gracefully/
2
+ # setup directories to hold files
3
+ FileUtils.mkdir_p 'public/javascripts/swfupload'
4
+ FileUtils.mkdir_p 'public/flash/swfupload'
5
+ FileUtils.mkdir_p 'public/images/swfupload'
6
+ FileUtils.mkdir_p 'app/views/swfupload'
7
+ FileUtils.mkdir_p 'app/stylesheets'
8
+
9
+ # download plugin files
10
+ base_url = 'http://swfupload.googlecode.com/svn/swfupload/trunk/core/plugins'
11
+
12
+ js_files = %w(swfupload.cookies swfupload.queue swfupload.speed swfupload.swfobject handlers swfupload)
13
+
14
+ js_files.each do |js_file|
15
+ run "curl -L #{base_url}/#{js_file}.js > public/javascripts/swfupload/#{js_file}.js"
16
+ end
17
+
18
+ run "curl -L http://github.com/jackdempsey/beet/raw/master/lib/beet/files/swfupload/js/handlers.js > public/javascripts/swfupload/handlers.js"
19
+ run "curl -L http://swfupload.googlecode.com/svn/swfupload/trunk/core/swfupload.js > public/javascripts/swfupload/swfupload.js"
20
+ run "curl -L http://swfupload.googlecode.com/svn/swfupload/trunk/core/Flash/swfupload.swf > public/flash/swfupload/swfupload.swf"
21
+ run "chmod +x public/flash/swfupload/swfupload.swf"
22
+ run "curl -L http://github.com/jackdempsey/beet/raw/master/lib/beet/files/swfupload/images/cancelbutton.gif > public/images/swfupload/cancelbutton.gif"
23
+
24
+ file 'app/stylesheets/swfupload.sass', <<-FILE
25
+ divFileProgressContainer
26
+ height: 75px
27
+
28
+ #divFileProgress
29
+
30
+ .progressWrapper
31
+ width: 100%
32
+ overflow: hidden
33
+
34
+ .progressContainer
35
+ margin: 5px
36
+ padding: 4px
37
+ border: solid 1px #E8E8E8
38
+ background-color: #F7F7F7
39
+ overflow: hidden
40
+
41
+ .progressName
42
+ font-size: 8pt
43
+ font-weight: 700
44
+ color: #555
45
+ width: 100%
46
+ height: 14px
47
+ text-align: left
48
+ white-space: nowrap
49
+ overflow: hidden
50
+
51
+ .progressBarInProgress, .progressBarComplete, .progressBarError
52
+ font-size: 0
53
+ width: 0%
54
+ height: 2px
55
+ background-color: blue
56
+ margin-top: 2px
57
+
58
+ .progressBarComplete
59
+ width: 100%
60
+ background-color: green
61
+ visibility: hidden
62
+
63
+ .progressBarError
64
+ width: 100%
65
+ background-color: red
66
+ visibility: hidden
67
+
68
+ .progressBarStatus
69
+ margin-top: 2px
70
+ width: 337px
71
+ font-size: 7pt
72
+ font-family: Arial
73
+ text-align: left
74
+ white-space: nowrap
75
+
76
+ a.progressCancel
77
+ font-size: 0
78
+ display: block
79
+ height: 14px
80
+ width: 14px
81
+ background-image: url(/images/swfupload/cancelbutton.gif)
82
+ background-repeat: no-repeat
83
+ background-position: -14px 0px
84
+ float: right
85
+
86
+ a.progressCancel:hover
87
+ background-position: 0px 0px
88
+ FILE
89
+
90
+ # create upload partial
91
+ file 'app/views/swfupload/_upload.html.haml', %q{
92
+ - content_for :head do
93
+ = javascript_include_tag 'swfupload/swfupload', 'swfupload/swfupload.swfobject', 'swfupload/handlers'
94
+ = stylesheet_link_tag %w(compiled/swfupload)
95
+ - session_key_name = ActionController::Base.session_options[:key]
96
+
97
+ - upload_url = songs_path
98
+ - form_tag upload_url, :multipart => true do
99
+ #swfupload_degraded_container
100
+ %noscript= "You should have Javascript enabled for a nicer upload experience"
101
+ = file_field_tag :Filedata
102
+ = submit_tag "Add a File"
103
+ #swfupload_container{ :style => "display: none" }
104
+ %span#spanButtonPlaceholder
105
+ #divFileProgressContainer
106
+
107
+
108
+ :javascript
109
+ SWFUpload.onload = function() {
110
+ var swf_settings = {
111
+
112
+ // SWFObject settings
113
+ minimum_flash_version: "9.0.28",
114
+ swfupload_pre_load_handler: function() {
115
+ $('#swfupload_degraded_container').hide();
116
+ $('#swfupload_container').show();
117
+ },
118
+ swfupload_load_failed_handler: function() {
119
+ },
120
+
121
+ post_params: {
122
+ "#{session_key_name}": "#{cookies[session_key_name]}",
123
+ "authenticity_token": "#{form_authenticity_token}",
124
+ },
125
+
126
+ //upload_url: "#{upload_url}?#{session_key_name}="+encodeURIComponent("#{cookies[session_key_name]}")+"&authenticity_token="+encodeURIComponent("#{form_authenticity_token}"),
127
+ upload_url: "#{upload_url}",
128
+ flash_url: '/flash/swfupload/swfupload.swf',
129
+
130
+ //example below lets you scope to only allowing image uploads
131
+ //file_types: "*.jpg;*.jpeg;*.gif;*.png;",
132
+ file_types: "*",
133
+ file_types_description: "pictures",
134
+ file_size_limit: "20 MB",
135
+
136
+ button_placeholder_id: "spanButtonPlaceholder",
137
+ button_width: 380,
138
+ button_height: 32,
139
+ button_text : '<span class="button">Select Files <span class="buttonSmall">(10 MB Max)</span></span>',
140
+ button_text_style : '.button { font-family: Helvetica, Arial, sans-serif; font-size: 24pt; } .buttonSmall { font-size: 18pt; }',
141
+ button_text_top_padding: 0,
142
+ button_text_left_padding: 18,
143
+ button_window_mode: SWFUpload.WINDOW_MODE.TRANSPARENT,
144
+ button_cursor: SWFUpload.CURSOR.HAND,
145
+ file_queue_error_handler : fileQueueError,
146
+ file_dialog_complete_handler : fileDialogComplete,
147
+ upload_progress_handler : uploadProgress,
148
+ upload_error_handler : uploadError,
149
+ upload_success_handler : uploadSuccess,
150
+ upload_complete_handler : uploadComplete,
151
+
152
+ custom_settings : {
153
+ upload_target: "divFileProgressContainer"
154
+ }
155
+ }
156
+ var swf_upload = new SWFUpload(swf_settings);
157
+ };
158
+ }
159
+
160
+ append_file 'config/initializers/session_store.rb', <<-FILE
161
+ require 'rack/utils'
162
+
163
+ class FlashSessionCookieMiddleware
164
+ def initialize(app, session_key = '_session_id')
165
+ @app = app
166
+ @session_key = session_key
167
+ end
168
+
169
+ def call(env)
170
+ if env['HTTP_USER_AGENT'] =~ /^(Adobe|Shockwave) Flash/
171
+ params = ::Rack::Request.new(env).params
172
+ env['HTTP_COOKIE'] = [ @session_key, params[@session_key] ].join('=').freeze unless params[@session_key].nil?
173
+ end
174
+ @app.call(env)
175
+ end
176
+ end
177
+
178
+ ActionController::Dispatcher.middleware.insert_before(ActionController::Base.session_store, FlashSessionCookieMiddleware, ActionController::Base.session_options[:key])
179
+ FILE
180
+
181
+ # example Song resource for those who want it
182
+ controller_file = <<-FILE
183
+ class SongsController < ApplicationController
184
+ layout 'swfupload'
185
+
186
+ def index
187
+ @songs = Song.all
188
+ end
189
+
190
+ def create
191
+ require 'mime/types'
192
+ mp3_info = Mp3Info.new(params[:Filedata].path)
193
+
194
+ song = Song.new
195
+ song.artist = mp3_info.tag.artist
196
+ song.title = mp3_info.tag.title
197
+ song.length_in_seconds = mp3_info.length.to_i
198
+
199
+ params[:Filedata].content_type = MIME::Types.type_for(params[:Filedata].original_filename).to_s
200
+ song.track = params[:Filedata]
201
+ song.save
202
+
203
+ render :text => [song.artist, song.title, song.convert_seconds_to_time].join(" - ")
204
+ rescue Mp3InfoError => e
205
+ render :text => "File error"
206
+ rescue Exception => e
207
+ render :text => e.message
208
+ end
209
+ end
210
+ FILE
211
+
212
+
213
+ model_file = <<-FILE
214
+ class Song < ActiveRecord::Base
215
+
216
+ has_attached_file :track
217
+
218
+ # validates_presence_of :title, :artist, :length_in_seconds
219
+ validates_attachment_presence :track
220
+ validates_attachment_content_type :track, :content_type => [ 'application/mp3', 'application/x-mp3', 'audio/mpeg', 'audio/mp3' ]
221
+ validates_attachment_size :track, :less_than => 20.megabytes
222
+
223
+ attr_accessible :title, :artist, :length_in_seconds
224
+
225
+ def convert_seconds_to_time
226
+ total_minutes = length_in_seconds / 1.minutes
227
+ seconds_in_last_minute = length_in_seconds - total_minutes.minutes.seconds
228
+ "\#{total_minutes}m \#{seconds_in_last_minute}s"
229
+ end
230
+
231
+
232
+ end
233
+ FILE
234
+
235
+ view_file = <<-FILE
236
+ %h1 Songs
237
+
238
+ - @songs.each do |song|
239
+ %p= song.title
240
+
241
+ = render 'swfupload/upload'
242
+ FILE
243
+
244
+ migration_file = <<-FILE
245
+ class CreateSongs < ActiveRecord::Migration
246
+ def self.up
247
+ create_table :songs do |t|
248
+ t.string :artist
249
+ t.string :title
250
+ t.integer :length_in_seconds
251
+ t.string :track_file_name
252
+ t.string :track_content_type
253
+ t.integer :track_file_size
254
+ t.timestamps
255
+ end
256
+ end
257
+
258
+ def self.down
259
+ drop_table :songs
260
+ end
261
+ end
262
+ FILE
263
+
264
+ layout_file = <<-FILE
265
+ !!! Strict
266
+ %html
267
+ %head
268
+ %title
269
+ = h(yield(:title) || "Untitled")
270
+ = '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery.min.js"></script>'
271
+ = '<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.3.1/jquery-ui.min.js"></script>'
272
+ = yield(:head)
273
+ %body
274
+ #container
275
+ = yield
276
+ FILE
277
+
278
+ puts '=' * 80
279
+ if yes? "Create an example resource using Paperclip? (y/n)"
280
+ FileUtils.mkdir_p 'app/views/songs'
281
+ FileUtils.mkdir_p 'public/stylesheets/compiled'
282
+
283
+ file 'app/views/layouts/swfupload.html.haml', layout_file
284
+ file 'app/controllers/songs_controller.rb', controller_file
285
+ file 'app/models/song.rb', model_file
286
+ file 'app/views/songs/index.html.haml', view_file
287
+
288
+ generate "migration", "create_songs"
289
+ filename = Dir['db/migrate/*create_songs.rb'].first
290
+ file filename, migration_file
291
+ rake "db:migrate"
292
+
293
+ gem 'paperclip'
294
+ gem 'haml'
295
+ gem 'ruby-mp3info', :lib => 'mp3info'
296
+
297
+ run "sass app/stylesheets/swfupload.sass > public/stylesheets/compiled/swfupload.css"
298
+
299
+ route 'map.resources :songs'
300
+
301
+ puts "Now fire up the app and go to /songs to test it out!"
302
+ else
303
+ puts "\nYour controller should have a create action that looks something like this:\n#{controller_file}"
304
+ puts "\nYou can create a model that looks like this:\n#{model_file}"
305
+ end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: beet
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.4.2
4
+ version: 0.4.3
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jack Dempsey
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-12-14 00:00:00 -05:00
12
+ date: 2010-01-09 00:00:00 -05:00
13
13
  default_executable: beet
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -51,6 +51,10 @@ files:
51
51
  - lib/beet/execution.rb
52
52
  - lib/beet/executor.rb
53
53
  - lib/beet/file_system.rb
54
+ - lib/beet/files/swfupload/images/cancelbutton.gif
55
+ - lib/beet/files/swfupload/images/header-bg.jpg
56
+ - lib/beet/files/swfupload/images/logo.gif
57
+ - lib/beet/files/swfupload/js/handlers.js
54
58
  - lib/beet/gem_location_map.rb
55
59
  - lib/beet/interaction.rb
56
60
  - lib/beet/logger.rb
@@ -66,10 +70,12 @@ files:
66
70
  - lib/beet/recipes/rails/css/blueprint.rb
67
71
  - lib/beet/recipes/rails/css/nifty_layout.rb
68
72
  - lib/beet/recipes/rails/css/reset.rb
73
+ - lib/beet/recipes/rails/db/mongo.rb
69
74
  - lib/beet/recipes/rails/db/mysql.rb
70
75
  - lib/beet/recipes/rails/db/postgres.rb
71
76
  - lib/beet/recipes/rails/git.rb
72
77
  - lib/beet/recipes/rails/jquery.rb
78
+ - lib/beet/recipes/rails/swfupload.rb
73
79
  - lib/beet/recipes/rails/testing/rspec.rb
74
80
  - lib/beet/recipes/rails/testing/shoulda.rb
75
81
  - lib/beet/scm.rb