beet 0.4.2 → 0.4.3

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/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