uploader 2.0.2 → 3.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/README.rdoc +55 -57
- data/Rakefile +1 -1
- data/VERSION +1 -1
- data/app/helpers/uploader_helper.rb +3 -3
- data/app/views/uploads/_swf_javascript.html.erb +9 -6
- data/app/views/uploads/_swf_upload.html.erb +2 -2
- data/app/views/uploads/_uploadify.html.erb +3 -3
- data/{locales → config/locales}/ar.yml +0 -0
- data/{locales → config/locales}/bg.yml +0 -0
- data/{locales → config/locales}/ca.yml +0 -0
- data/{locales → config/locales}/cs.yml +0 -0
- data/{locales → config/locales}/da.yml +0 -0
- data/{locales → config/locales}/de.yml +0 -0
- data/{locales → config/locales}/el.yml +0 -0
- data/{locales → config/locales}/en.yml +0 -0
- data/{locales → config/locales}/es.yml +0 -0
- data/{locales → config/locales}/et.yml +0 -0
- data/{locales → config/locales}/fa.yml +2 -2
- data/{locales → config/locales}/fi.yml +0 -0
- data/{locales → config/locales}/fr.yml +0 -0
- data/{locales → config/locales}/gl.yml +0 -0
- data/{locales → config/locales}/hi.yml +1 -1
- data/{locales → config/locales}/hr.yml +0 -0
- data/{locales → config/locales}/hu.yml +0 -0
- data/{locales → config/locales}/id.yml +1 -1
- data/{locales → config/locales}/it.yml +0 -0
- data/{locales → config/locales}/iw.yml +0 -0
- data/{locales → config/locales}/ja.yml +0 -0
- data/{locales → config/locales}/ko.yml +2 -2
- data/{locales → config/locales}/lt.yml +0 -0
- data/{locales → config/locales}/lv.yml +0 -0
- data/{locales → config/locales}/mt.yml +0 -0
- data/{locales → config/locales}/nl.yml +0 -0
- data/{locales → config/locales}/no.yml +0 -0
- data/{locales → config/locales}/pl.yml +0 -0
- data/{locales → config/locales}/pt-PT.yml +0 -0
- data/{locales → config/locales}/ro.yml +0 -0
- data/{locales → config/locales}/ru.yml +0 -0
- data/{locales → config/locales}/sk.yml +0 -0
- data/{locales → config/locales}/sl.yml +0 -0
- data/{locales → config/locales}/sq.yml +0 -0
- data/{locales → config/locales}/sr.yml +0 -0
- data/{locales → config/locales}/sv.yml +0 -0
- data/{locales → config/locales}/th.yml +1 -1
- data/{locales → config/locales}/tl.yml +0 -0
- data/{locales → config/locales}/tr.yml +0 -0
- data/{locales → config/locales}/uk.yml +0 -0
- data/{locales → config/locales}/vi.yml +2 -2
- data/{locales → config/locales}/zh-CN.yml +0 -0
- data/{locales → config/locales}/zh-TW.yml +0 -0
- data/{locales → config/locales}/zh.yml +0 -0
- data/config/routes.rb +8 -0
- data/lib/tasks/uploader.rake +22 -0
- data/lib/uploader/config.rb +65 -0
- data/lib/uploader/engine.rb +19 -0
- data/lib/uploader/models/upload.rb +229 -0
- data/lib/uploader.rb +4 -2
- data/test/{rails_root → rails_test}/.gitignore +0 -0
- data/test/{rails_root → rails_test}/.rake_tasks +0 -0
- data/test/rails_test/Gemfile +21 -0
- data/{Gemfile.lock → test/rails_test/Gemfile.lock} +21 -1
- data/test/rails_test/README +256 -0
- data/test/{rails_root → rails_test}/Rakefile +2 -7
- data/test/{rails_root → rails_test}/app/controllers/application_controller.rb +0 -0
- data/test/rails_test/app/controllers/default_controller.rb +18 -0
- data/test/{rails_root → rails_test}/app/controllers/uploads_controller.rb +5 -2
- data/test/{rails_root → rails_test}/app/models/.keep +0 -0
- data/test/rails_test/app/models/upload.rb +38 -0
- data/test/{rails_root → rails_test}/app/models/user.rb +0 -0
- data/test/{rails_root → rails_test}/app/views/default/index.html.erb +11 -1
- data/test/rails_test/app/views/default/uploadify.html.erb +27 -0
- data/test/{rails_root → rails_test}/app/views/layouts/application.html.erb +2 -2
- data/test/{rails_root → rails_test}/config/amazon_s3.yml +0 -0
- data/test/{rails_root → rails_test}/config/application.rb +6 -12
- data/test/rails_test/config/boot.rb +13 -0
- data/test/{rails_root → rails_test}/config/database.yml +3 -11
- data/test/rails_test/config/environment.rb +5 -0
- data/test/rails_test/config/environments/development.rb +26 -0
- data/test/rails_test/config/environments/production.rb +49 -0
- data/test/rails_test/config/environments/test.rb +35 -0
- data/test/{rails_root → rails_test}/config/global_config.yml +0 -0
- data/test/{rails_root → rails_test}/config/initializers/backtrace_silencers.rb +0 -0
- data/test/{rails_root → rails_test}/config/initializers/inflections.rb +2 -2
- data/test/{rails_root → rails_test}/config/initializers/mime_types.rb +0 -0
- data/test/{rails_root → rails_test}/config/initializers/s3_credentials.rb +1 -1
- data/test/{rails_root → rails_test}/config/initializers/secret_token.rb +1 -1
- data/test/rails_test/config/initializers/session_store.rb +8 -0
- data/test/rails_test/config/locales/en.yml +5 -0
- data/test/rails_test/config/routes.rb +13 -0
- data/test/rails_test/config.ru +4 -0
- data/test/{rails_root → rails_test}/db/.keep +0 -0
- data/test/{rails_root → rails_test}/db/migrate/20090517040220_create_uploads.rb +0 -0
- data/test/{rails_root → rails_test}/db/migrate/20090602041838_create_users.rb +0 -0
- data/test/rails_test/db/seeds.rb +7 -0
- data/test/rails_test/doc/README_FOR_APP +2 -0
- data/test/{rails_root → rails_test}/features/step_definitions/webrat_steps.rb +0 -0
- data/test/{rails_root → rails_test}/features/support/env.rb +0 -0
- data/test/{rails_root → rails_test}/lib/daemons/amazonaws.rb +0 -0
- data/test/{rails_root/public/favicon.ico → rails_test/lib/tasks/.gitkeep} +0 -0
- data/test/rails_test/public/404.html +26 -0
- data/test/rails_test/public/422.html +26 -0
- data/test/rails_test/public/500.html +26 -0
- data/test/{rails_root/public/stylesheets/.keep → rails_test/public/favicon.ico} +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/excel.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file.png +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_aac.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_ai.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_avi.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_bin.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_bmp.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_cue.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_divx.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_doc.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_eps.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_flac.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_flv.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_gif.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_html.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_ical.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_indd.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_inx.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_iso.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_jpg.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_mov.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_mp3.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_mpg.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_pdf.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_php.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_png.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_pps.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_ppt.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_psd.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_qxd.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_qxp.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_raw.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_rtf.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_svg.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_tif.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_txt.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_vcf.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_wav.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_wma.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_xls.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/file_xml.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/mp3.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/pdf.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/pdf.png +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/text.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/text.png +0 -0
- data/test/{rails_root → rails_test}/public/images/file_icons/word.gif +0 -0
- data/test/rails_test/public/images/rails.png +0 -0
- data/test/{rails_root/public/images → rails_test/public/images/swfupload}/SWFUploadButton.png +0 -0
- data/test/{rails_root/public/images → rails_test/public/images/swfupload}/cancelbutton.gif +0 -0
- data/test/{rails_root → rails_test}/public/images/uploadify/cancel.png +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/application.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/controls.js +75 -73
- data/test/{rails_root → rails_test}/public/javascripts/dragdrop.js +171 -169
- data/test/{rails_root → rails_test}/public/javascripts/effects.js +180 -177
- data/test/{rails_root/public/javascripts/jquery/jquery.js → rails_test/public/javascripts/jquery/jquery-1.4.2.min.js} +0 -0
- data/test/{rails_root/public/javascripts/jquery/jquery-ui.js → rails_test/public/javascripts/jquery/jquery-ui-1.8.4.custom.min.js} +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/jquery/jquery.uploadify.min.js +0 -0
- data/test/rails_test/public/javascripts/prototype.js +6001 -0
- data/test/rails_test/public/javascripts/rails.js +175 -0
- data/test/{rails_root → rails_test}/public/javascripts/swf/swfobject.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/fileprogress.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/handlers.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.cookies.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.proxy.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.queue.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.speed.js +0 -0
- data/test/{rails_root → rails_test}/public/javascripts/swfupload/swfupload.swfobject.js +0 -0
- data/test/rails_test/public/robots.txt +5 -0
- data/test/{rails_root/test/functional/.keep → rails_test/public/stylesheets/.gitkeep} +0 -0
- data/test/{rails_root → rails_test}/public/stylesheets/swfupload.css +0 -0
- data/test/{rails_root → rails_test}/public/stylesheets/uploadify.css +0 -0
- data/test/{rails_root → rails_test}/public/swf/expressInstall.swf +0 -0
- data/test/{rails_root → rails_test}/public/swf/swfupload.swf +0 -0
- data/test/{rails_root → rails_test}/public/swf/swfupload_fp9.swf +0 -0
- data/test/{rails_root → rails_test}/public/swf/uploadify.swf +0 -0
- data/test/rails_test/script/rails +6 -0
- data/test/{rails_root → rails_test}/test/factories.rb +1 -1
- data/test/{rails_root → rails_test}/test/fixtures/files/5k.png +0 -0
- data/test/{rails_root → rails_test}/test/fixtures/files/IT'sUPPERCASE!AND WeIRD.JPG +0 -0
- data/test/rails_test/test/fixtures/rails.png +0 -0
- data/test/{rails_root/test → rails_test/test/fixtures}/test.doc +0 -0
- data/test/{rails_root/test → rails_test/test/fixtures}/test.pdf +0 -0
- data/test/rails_test/test/fixtures/test.txt +1 -0
- data/test/{rails_root/test → rails_test/test/fixtures}/test.xls +0 -0
- data/test/{rails_root/test/integration → rails_test/test/functional}/.keep +0 -0
- data/test/{rails_root → rails_test}/test/functional/default_controller_test.rb +0 -0
- data/test/{rails_root → rails_test}/test/functional/uploads_controller_test.rb +0 -0
- data/test/{rails_root/test/mocks/development → rails_test/test/integration}/.keep +0 -0
- data/test/rails_test/test/performance/browsing_test.rb +9 -0
- data/test/{rails_root → rails_test}/test/shoulda_macros/paperclip.rb +0 -0
- data/test/rails_test/test/test_helper.rb +25 -0
- data/test/{rails_root/test/mocks/test → rails_test/test/unit}/.keep +0 -0
- data/test/{rails_root → rails_test}/test/unit/upload_test.rb +9 -18
- data/test/{rails_root/test/unit/.keep → rails_test/vendor/plugins/.gitkeep} +0 -0
- data/uploader.gemspec +225 -255
- metadata +228 -258
- data/Gemfile +0 -13
- data/config/uploader_routes.rb +0 -3
- data/lib/active_record/acts/uploader_upload.rb +0 -279
- data/lib/uploader/initialize_routes.rb +0 -8
- data/lib/uploader/tasks.rb +0 -42
- data/rails/init.rb +0 -38
- data/tasks/rails.rake +0 -2
- data/test/rails_root/Capfile +0 -3
- data/test/rails_root/app/controllers/default_controller.rb +0 -12
- data/test/rails_root/app/models/upload.rb +0 -55
- data/test/rails_root/app/views/default/uploadify.html.erb +0 -17
- data/test/rails_root/config/boot.rb +0 -109
- data/test/rails_root/config/environment.rb +0 -29
- data/test/rails_root/config/environments/development.rb +0 -19
- data/test/rails_root/config/environments/production.rb +0 -1
- data/test/rails_root/config/environments/test.rb +0 -27
- data/test/rails_root/config/initializers/requires.rb +0 -13
- data/test/rails_root/config/initializers/session_store.rb +0 -8
- data/test/rails_root/config/initializers/uploader.rb +0 -11
- data/test/rails_root/config/routes.rb +0 -13
- data/test/rails_root/db/development.sqlite3 +0 -0
- data/test/rails_root/db/schema.rb +0 -47
- data/test/rails_root/db/test.sqlite3 +0 -0
- data/test/rails_root/public/.htaccess +0 -40
- data/test/rails_root/public/404.html +0 -30
- data/test/rails_root/public/422.html +0 -30
- data/test/rails_root/public/500.html +0 -30
- data/test/rails_root/public/dispatch.rb +0 -10
- data/test/rails_root/public/images/rails.png +0 -0
- data/test/rails_root/public/images/swfupload/SWFUploadButton.png +0 -0
- data/test/rails_root/public/images/swfupload/cancelbutton.gif +0 -0
- data/test/rails_root/public/javascripts/builder.js +0 -136
- data/test/rails_root/public/javascripts/jquery/jquery.easing.js +0 -1
- data/test/rails_root/public/javascripts/jquery/jquery.fancybox.js +0 -9
- data/test/rails_root/public/javascripts/jquery/jquery.form.js +0 -637
- data/test/rails_root/public/javascripts/jquery/jquery.jgrowl.js +0 -2
- data/test/rails_root/public/javascripts/jquery/jquery.tips.js +0 -69
- data/test/rails_root/public/javascripts/jquery/jrails.js +0 -1
- data/test/rails_root/public/javascripts/prototype.js +0 -4225
- data/test/rails_root/public/javascripts/scriptaculous.js +0 -58
- data/test/rails_root/public/javascripts/slider.js +0 -277
- data/test/rails_root/public/javascripts/sound.js +0 -60
- data/test/rails_root/public/robots.txt +0 -1
- data/test/rails_root/script/about +0 -3
- data/test/rails_root/script/breakpointer +0 -3
- data/test/rails_root/script/console +0 -3
- data/test/rails_root/script/create_project.rb +0 -52
- data/test/rails_root/script/cucumber +0 -7
- data/test/rails_root/script/dbconsole +0 -3
- data/test/rails_root/script/destroy +0 -3
- data/test/rails_root/script/generate +0 -3
- data/test/rails_root/script/performance/benchmarker +0 -3
- data/test/rails_root/script/performance/profiler +0 -3
- data/test/rails_root/script/performance/request +0 -3
- data/test/rails_root/script/plugin +0 -3
- data/test/rails_root/script/process/inspector +0 -3
- data/test/rails_root/script/process/reaper +0 -3
- data/test/rails_root/script/process/spawner +0 -3
- data/test/rails_root/script/runner +0 -3
- data/test/rails_root/script/server +0 -3
- data/test/rails_root/test/test_helper.rb +0 -26
@@ -0,0 +1,229 @@
|
|
1
|
+
require 'mime/types'
|
2
|
+
|
3
|
+
module Uploader
|
4
|
+
module Models
|
5
|
+
module Upload
|
6
|
+
extend ActiveSupport::Concern
|
7
|
+
|
8
|
+
included do
|
9
|
+
|
10
|
+
scope :newest, order("created_at DESC")
|
11
|
+
scope :by_filename, order("local_file_name DESC")
|
12
|
+
scope :newest, order("created_at DESC")
|
13
|
+
scope :is_public, where('is_public = true')
|
14
|
+
scope :images, where("local_content_type IN (#{Uploader::MimeTypeGroups::IMAGE_TYPES.collect{|type| "'#{type}'"}.join(',')})")
|
15
|
+
scope :documents, where("local_content_type IN (#{(Uploader::MimeTypeGroups::WORD_TYPES + Uploader::MimeTypeGroups::EXCEL_TYPES + Uploader::MimeTypeGroups::PDF_TYPES).collect{|type| "'#{type}'"}.join(',')})")
|
16
|
+
scope :files, where("local_content_type NOT IN (#{Uploader::MimeTypeGroups::IMAGE_TYPES.collect{|type| "'#{type}'"}.join(',')})")
|
17
|
+
scope :recent, lambda { |*args| where("created_at > ?", args.first || 7.days.ago.to_s(:db)) }
|
18
|
+
scope :created_by, lambda { |creator_id| where("creator_id = ?", creator_id) }
|
19
|
+
scope :pending_s3_migrations, where("remote_file_name IS NULL").order('created_at DESC')
|
20
|
+
|
21
|
+
# Paperclip
|
22
|
+
has_attached_file :local, Uploader.configuration.has_attached_file_options.merge(:storage => :filesystem) # Override any storage settings. This one has to be local.
|
23
|
+
has_attached_file :remote, Uploader.configuration.has_attached_file_options
|
24
|
+
|
25
|
+
belongs_to :uploadable, :polymorphic => true
|
26
|
+
belongs_to :creator, :class_name => 'User', :foreign_key => 'creator_id'
|
27
|
+
|
28
|
+
before_save :determine_immediate_send_to_remote
|
29
|
+
|
30
|
+
before_post_process :transliterate_file_name
|
31
|
+
before_post_process :halt_nonimage_processing unless Uploader.configuration.disable_halt_nonimage_processing
|
32
|
+
before_create :add_width_and_height
|
33
|
+
|
34
|
+
# Protect data in the model
|
35
|
+
attr_protected :creator_id, :uploadable_id, :uploadable_type
|
36
|
+
end
|
37
|
+
|
38
|
+
module ClassMethods
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
def file
|
43
|
+
local_file_name ? local : remote
|
44
|
+
end
|
45
|
+
|
46
|
+
def file_name
|
47
|
+
remote_file_name || local_file_name
|
48
|
+
end
|
49
|
+
|
50
|
+
def determine_immediate_send_to_remote
|
51
|
+
if Uploader.configuration.s3_no_wait
|
52
|
+
self.remote = local.to_file # This will result in the file being sent to S3
|
53
|
+
end
|
54
|
+
end
|
55
|
+
|
56
|
+
def send_to_remote
|
57
|
+
if local_file_name
|
58
|
+
self.remote = local.to_file
|
59
|
+
if self.save and remote.original_filename and remote.exists?
|
60
|
+
self.local = nil unless Uploader.configuration.keep_local_file
|
61
|
+
self.save
|
62
|
+
else
|
63
|
+
false
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
def multiupload_local=(filedata)
|
69
|
+
filedata.content_type = MIME::Types.type_for(filedata.original_filename)[0].to_s
|
70
|
+
self.local = filedata
|
71
|
+
end
|
72
|
+
|
73
|
+
def is_image?
|
74
|
+
Uploader::MimeTypeGroups::IMAGE_TYPES.include?(self.local_content_type)
|
75
|
+
end
|
76
|
+
|
77
|
+
def is_mp3?
|
78
|
+
Uploader::MimeTypeGroups::MP3_TYPES.include?(self.local_content_type)
|
79
|
+
end
|
80
|
+
|
81
|
+
def is_excel?
|
82
|
+
Uploader::MimeTypeGroups::EXCEL_TYPES.include?(self.local_content_type)
|
83
|
+
end
|
84
|
+
|
85
|
+
def is_pdf?
|
86
|
+
Uploader::MimeTypeGroups::PDF_TYPES.include?(self.local_content_type)
|
87
|
+
end
|
88
|
+
|
89
|
+
def is_word?
|
90
|
+
Uploader::MimeTypeGroups::WORD_TYPES.include?(self.local_content_type)
|
91
|
+
end
|
92
|
+
|
93
|
+
def is_text?
|
94
|
+
Uploader::MimeTypeGroups::TEXT_TYPES.include?(self.local_content_type)
|
95
|
+
end
|
96
|
+
|
97
|
+
def upload_type
|
98
|
+
if self.is_pdf?
|
99
|
+
'Adobe pdf file'
|
100
|
+
elsif self.is_word?
|
101
|
+
'Word document'
|
102
|
+
elsif self.is_image?
|
103
|
+
'photo'
|
104
|
+
elsif self.is_mp3?
|
105
|
+
'mp3'
|
106
|
+
elsif self.is_excel?
|
107
|
+
'Excel document'
|
108
|
+
elsif self.is_text?
|
109
|
+
'text file'
|
110
|
+
else
|
111
|
+
'file'
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def icon
|
116
|
+
if self.is_pdf?
|
117
|
+
'/images/file_icons/file_pdf.gif'
|
118
|
+
elsif self.is_word?
|
119
|
+
'/images/file_icons/file_doc.gif'
|
120
|
+
elsif self.is_image?
|
121
|
+
self.file.url(:icon)
|
122
|
+
elsif self.is_mp3?
|
123
|
+
'/images/file_icons/file_mp3.gif'
|
124
|
+
elsif self.is_excel?
|
125
|
+
'/images/file_icons/file_xls.gif'
|
126
|
+
elsif self.is_text?
|
127
|
+
'/images/file_icons/file_txt.gif'
|
128
|
+
else
|
129
|
+
'/images/file_icons/file_raw.gif'
|
130
|
+
end
|
131
|
+
end
|
132
|
+
|
133
|
+
# Only works for images
|
134
|
+
def thumb
|
135
|
+
if self.is_image?
|
136
|
+
self.file.url(:thumb)
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
def display_name
|
141
|
+
CGI::escapeHTML(self.local_file_name)
|
142
|
+
end
|
143
|
+
|
144
|
+
def can_edit?(check_user)
|
145
|
+
return false if check_user.blank?
|
146
|
+
check_user == self.creator
|
147
|
+
end
|
148
|
+
|
149
|
+
# Image dimension calculations
|
150
|
+
|
151
|
+
def width(style = :default)
|
152
|
+
return nil unless self[:width]
|
153
|
+
return self[:width] if style == :default
|
154
|
+
calculate_sizes(style.to_sym)
|
155
|
+
return @image_width.to_i
|
156
|
+
end
|
157
|
+
|
158
|
+
def height(style = :default)
|
159
|
+
return nil unless self[:height]
|
160
|
+
return self[:height] if style == :default
|
161
|
+
calculate_sizes(style.to_sym)
|
162
|
+
return @image_height.to_i
|
163
|
+
end
|
164
|
+
|
165
|
+
def size(style = :default)
|
166
|
+
return nil unless width || height
|
167
|
+
return "#{width}x#{height}" if style == :default
|
168
|
+
calculate_sizes(style.to_sym)
|
169
|
+
return @image_size
|
170
|
+
end
|
171
|
+
|
172
|
+
def max_dimension(style)
|
173
|
+
@max_dimension ||= Paperclip::Geometry.parse(self.local.styles[style][:geometry]).width.to_f
|
174
|
+
end
|
175
|
+
|
176
|
+
def image_ratio
|
177
|
+
@image_ratio ||= width.to_f / height.to_f
|
178
|
+
end
|
179
|
+
|
180
|
+
def calculate_sizes(style)
|
181
|
+
if image_ratio > 1
|
182
|
+
@image_width ||= width > max_dimension(style) ? max_dimension(style) : width
|
183
|
+
@image_height ||= (@image_width / image_ratio).round
|
184
|
+
else
|
185
|
+
@image_height ||= height > max_dimension(style) ? max_dimension(style) : height
|
186
|
+
@image_width ||= (@image_height * image_ratio).round
|
187
|
+
end
|
188
|
+
@image_size ||= "#{@image_width.to_i}x#{@image_height.to_i}"
|
189
|
+
end
|
190
|
+
|
191
|
+
protected
|
192
|
+
|
193
|
+
def transliterate_file_name
|
194
|
+
extension = File.extname(local_file_name).gsub(/^\.+/, '')
|
195
|
+
filename = local_file_name.gsub(/\.#{extension}$/, '')
|
196
|
+
self.local.instance_write(:file_name, "#{transliterate(filename)}.#{transliterate(extension)}")
|
197
|
+
end
|
198
|
+
|
199
|
+
def transliterate(str)
|
200
|
+
# Lifted from permalink_fu by Rick Olsen
|
201
|
+
# Escape str by transliterating to UTF-8 with Iconv,
|
202
|
+
# downcasing, then removing illegal characters and replacing them with ’-’
|
203
|
+
s = Iconv.iconv('ascii//ignore//translit', 'utf-8', str).to_s
|
204
|
+
s.downcase!
|
205
|
+
s.gsub!(/\'/, '')
|
206
|
+
s.gsub!(/[^A-Za-z0-9]+/, ' ')
|
207
|
+
s.strip!
|
208
|
+
s.gsub!(/\ +/, '-') # set single or multiple spaces to a single dash
|
209
|
+
return s
|
210
|
+
end
|
211
|
+
|
212
|
+
def add_width_and_height
|
213
|
+
return unless self.is_image?
|
214
|
+
if self.local.to_file
|
215
|
+
geometry = Paperclip::Geometry.from_file self.local.to_file
|
216
|
+
self[:width] = geometry.width.to_i
|
217
|
+
self[:height] = geometry.height.to_i
|
218
|
+
end
|
219
|
+
end
|
220
|
+
|
221
|
+
def halt_nonimage_processing
|
222
|
+
if !self.is_image? && self.local.options[:styles]
|
223
|
+
return false
|
224
|
+
end
|
225
|
+
end
|
226
|
+
|
227
|
+
end
|
228
|
+
end
|
229
|
+
end
|
data/lib/uploader.rb
CHANGED
@@ -1,4 +1,6 @@
|
|
1
|
-
require '
|
1
|
+
require 'uploader/config'
|
2
2
|
require 'uploader/exceptions'
|
3
3
|
require 'uploader/mime_type_groups'
|
4
|
-
require 'uploader/middleware/flash_session_cookie_middleware'
|
4
|
+
require 'uploader/middleware/flash_session_cookie_middleware'
|
5
|
+
require 'uploader/models/upload'
|
6
|
+
require 'uploader/engine'
|
File without changes
|
File without changes
|
@@ -0,0 +1,21 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
gem "rails", "3.0.0"
|
4
|
+
gem "capybara", ">= 0.3.9"
|
5
|
+
gem 'mysql'
|
6
|
+
|
7
|
+
gem "mime-types"
|
8
|
+
gem "rack"
|
9
|
+
gem "paperclip"
|
10
|
+
gem "uploader", :path => '../../'
|
11
|
+
|
12
|
+
if RUBY_VERSION < '1.9'
|
13
|
+
gem "ruby-debug"
|
14
|
+
end
|
15
|
+
|
16
|
+
group :test do
|
17
|
+
gem 'shoulda'
|
18
|
+
gem 'factory_girl'
|
19
|
+
gem 'mocha'
|
20
|
+
gem 'redgreen'
|
21
|
+
end
|
@@ -1,3 +1,12 @@
|
|
1
|
+
PATH
|
2
|
+
remote: /Users/jbasdf/projects/uploader
|
3
|
+
specs:
|
4
|
+
uploader (2.0.2)
|
5
|
+
aws-s3
|
6
|
+
mime-types
|
7
|
+
paperclip
|
8
|
+
rack
|
9
|
+
|
1
10
|
GEM
|
2
11
|
remote: http://rubygems.org/
|
3
12
|
specs:
|
@@ -30,6 +39,10 @@ GEM
|
|
30
39
|
activesupport (3.0.0)
|
31
40
|
arel (1.0.1)
|
32
41
|
activesupport (~> 3.0.0)
|
42
|
+
aws-s3 (0.6.2)
|
43
|
+
builder
|
44
|
+
mime-types
|
45
|
+
xml-simple
|
33
46
|
builder (2.1.2)
|
34
47
|
capybara (0.3.9)
|
35
48
|
culerity (>= 0.2.4)
|
@@ -53,6 +66,8 @@ GEM
|
|
53
66
|
mime-types
|
54
67
|
treetop (>= 1.4.5)
|
55
68
|
mime-types (1.16)
|
69
|
+
mocha (0.9.8)
|
70
|
+
rake
|
56
71
|
mysql (2.8.1)
|
57
72
|
nokogiri (1.4.3.1)
|
58
73
|
paperclip (2.3.3)
|
@@ -78,6 +93,7 @@ GEM
|
|
78
93
|
rake (>= 0.8.4)
|
79
94
|
thor (~> 0.14.0)
|
80
95
|
rake (0.8.7)
|
96
|
+
redgreen (1.2.2)
|
81
97
|
ruby-debug (0.10.3)
|
82
98
|
columnize (>= 0.1)
|
83
99
|
ruby-debug-base (~> 0.10.3.0)
|
@@ -93,6 +109,7 @@ GEM
|
|
93
109
|
treetop (1.4.8)
|
94
110
|
polyglot (>= 0.3.1)
|
95
111
|
tzinfo (0.3.23)
|
112
|
+
xml-simple (1.0.12)
|
96
113
|
|
97
114
|
PLATFORMS
|
98
115
|
ruby
|
@@ -101,9 +118,12 @@ DEPENDENCIES
|
|
101
118
|
capybara (>= 0.3.9)
|
102
119
|
factory_girl
|
103
120
|
mime-types
|
121
|
+
mocha
|
104
122
|
mysql
|
105
123
|
paperclip
|
106
124
|
rack
|
107
125
|
rails (= 3.0.0)
|
108
|
-
|
126
|
+
redgreen
|
127
|
+
ruby-debug
|
109
128
|
shoulda
|
129
|
+
uploader!
|
@@ -0,0 +1,256 @@
|
|
1
|
+
== Welcome to Rails
|
2
|
+
|
3
|
+
Rails is a web-application framework that includes everything needed to create
|
4
|
+
database-backed web applications according to the Model-View-Control pattern.
|
5
|
+
|
6
|
+
This pattern splits the view (also called the presentation) into "dumb"
|
7
|
+
templates that are primarily responsible for inserting pre-built data in between
|
8
|
+
HTML tags. The model contains the "smart" domain objects (such as Account,
|
9
|
+
Product, Person, Post) that holds all the business logic and knows how to
|
10
|
+
persist themselves to a database. The controller handles the incoming requests
|
11
|
+
(such as Save New Account, Update Product, Show Post) by manipulating the model
|
12
|
+
and directing data to the view.
|
13
|
+
|
14
|
+
In Rails, the model is handled by what's called an object-relational mapping
|
15
|
+
layer entitled Active Record. This layer allows you to present the data from
|
16
|
+
database rows as objects and embellish these data objects with business logic
|
17
|
+
methods. You can read more about Active Record in
|
18
|
+
link:files/vendor/rails/activerecord/README.html.
|
19
|
+
|
20
|
+
The controller and view are handled by the Action Pack, which handles both
|
21
|
+
layers by its two parts: Action View and Action Controller. These two layers
|
22
|
+
are bundled in a single package due to their heavy interdependence. This is
|
23
|
+
unlike the relationship between the Active Record and Action Pack that is much
|
24
|
+
more separate. Each of these packages can be used independently outside of
|
25
|
+
Rails. You can read more about Action Pack in
|
26
|
+
link:files/vendor/rails/actionpack/README.html.
|
27
|
+
|
28
|
+
|
29
|
+
== Getting Started
|
30
|
+
|
31
|
+
1. At the command prompt, create a new Rails application:
|
32
|
+
<tt>rails new myapp</tt> (where <tt>myapp</tt> is the application name)
|
33
|
+
|
34
|
+
2. Change directory to <tt>myapp</tt> and start the web server:
|
35
|
+
<tt>cd myapp; rails server</tt> (run with --help for options)
|
36
|
+
|
37
|
+
3. Go to http://localhost:3000/ and you'll see:
|
38
|
+
"Welcome aboard: You're riding Ruby on Rails!"
|
39
|
+
|
40
|
+
4. Follow the guidelines to start developing your application. You can find
|
41
|
+
the following resources handy:
|
42
|
+
|
43
|
+
* The Getting Started Guide: http://guides.rubyonrails.org/getting_started.html
|
44
|
+
* Ruby on Rails Tutorial Book: http://www.railstutorial.org/
|
45
|
+
|
46
|
+
|
47
|
+
== Debugging Rails
|
48
|
+
|
49
|
+
Sometimes your application goes wrong. Fortunately there are a lot of tools that
|
50
|
+
will help you debug it and get it back on the rails.
|
51
|
+
|
52
|
+
First area to check is the application log files. Have "tail -f" commands
|
53
|
+
running on the server.log and development.log. Rails will automatically display
|
54
|
+
debugging and runtime information to these files. Debugging info will also be
|
55
|
+
shown in the browser on requests from 127.0.0.1.
|
56
|
+
|
57
|
+
You can also log your own messages directly into the log file from your code
|
58
|
+
using the Ruby logger class from inside your controllers. Example:
|
59
|
+
|
60
|
+
class WeblogController < ActionController::Base
|
61
|
+
def destroy
|
62
|
+
@weblog = Weblog.find(params[:id])
|
63
|
+
@weblog.destroy
|
64
|
+
logger.info("#{Time.now} Destroyed Weblog ID ##{@weblog.id}!")
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
The result will be a message in your log file along the lines of:
|
69
|
+
|
70
|
+
Mon Oct 08 14:22:29 +1000 2007 Destroyed Weblog ID #1!
|
71
|
+
|
72
|
+
More information on how to use the logger is at http://www.ruby-doc.org/core/
|
73
|
+
|
74
|
+
Also, Ruby documentation can be found at http://www.ruby-lang.org/. There are
|
75
|
+
several books available online as well:
|
76
|
+
|
77
|
+
* Programming Ruby: http://www.ruby-doc.org/docs/ProgrammingRuby/ (Pickaxe)
|
78
|
+
* Learn to Program: http://pine.fm/LearnToProgram/ (a beginners guide)
|
79
|
+
|
80
|
+
These two books will bring you up to speed on the Ruby language and also on
|
81
|
+
programming in general.
|
82
|
+
|
83
|
+
|
84
|
+
== Debugger
|
85
|
+
|
86
|
+
Debugger support is available through the debugger command when you start your
|
87
|
+
Mongrel or WEBrick server with --debugger. This means that you can break out of
|
88
|
+
execution at any point in the code, investigate and change the model, and then,
|
89
|
+
resume execution! You need to install ruby-debug to run the server in debugging
|
90
|
+
mode. With gems, use <tt>sudo gem install ruby-debug</tt>. Example:
|
91
|
+
|
92
|
+
class WeblogController < ActionController::Base
|
93
|
+
def index
|
94
|
+
@posts = Post.find(:all)
|
95
|
+
debugger
|
96
|
+
end
|
97
|
+
end
|
98
|
+
|
99
|
+
So the controller will accept the action, run the first line, then present you
|
100
|
+
with a IRB prompt in the server window. Here you can do things like:
|
101
|
+
|
102
|
+
>> @posts.inspect
|
103
|
+
=> "[#<Post:0x14a6be8
|
104
|
+
@attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>,
|
105
|
+
#<Post:0x14a6620
|
106
|
+
@attributes={"title"=>"Rails", "body"=>"Only ten..", "id"=>"2"}>]"
|
107
|
+
>> @posts.first.title = "hello from a debugger"
|
108
|
+
=> "hello from a debugger"
|
109
|
+
|
110
|
+
...and even better, you can examine how your runtime objects actually work:
|
111
|
+
|
112
|
+
>> f = @posts.first
|
113
|
+
=> #<Post:0x13630c4 @attributes={"title"=>nil, "body"=>nil, "id"=>"1"}>
|
114
|
+
>> f.
|
115
|
+
Display all 152 possibilities? (y or n)
|
116
|
+
|
117
|
+
Finally, when you're ready to resume execution, you can enter "cont".
|
118
|
+
|
119
|
+
|
120
|
+
== Console
|
121
|
+
|
122
|
+
The console is a Ruby shell, which allows you to interact with your
|
123
|
+
application's domain model. Here you'll have all parts of the application
|
124
|
+
configured, just like it is when the application is running. You can inspect
|
125
|
+
domain models, change values, and save to the database. Starting the script
|
126
|
+
without arguments will launch it in the development environment.
|
127
|
+
|
128
|
+
To start the console, run <tt>rails console</tt> from the application
|
129
|
+
directory.
|
130
|
+
|
131
|
+
Options:
|
132
|
+
|
133
|
+
* Passing the <tt>-s, --sandbox</tt> argument will rollback any modifications
|
134
|
+
made to the database.
|
135
|
+
* Passing an environment name as an argument will load the corresponding
|
136
|
+
environment. Example: <tt>rails console production</tt>.
|
137
|
+
|
138
|
+
To reload your controllers and models after launching the console run
|
139
|
+
<tt>reload!</tt>
|
140
|
+
|
141
|
+
More information about irb can be found at:
|
142
|
+
link:http://www.rubycentral.com/pickaxe/irb.html
|
143
|
+
|
144
|
+
|
145
|
+
== dbconsole
|
146
|
+
|
147
|
+
You can go to the command line of your database directly through <tt>rails
|
148
|
+
dbconsole</tt>. You would be connected to the database with the credentials
|
149
|
+
defined in database.yml. Starting the script without arguments will connect you
|
150
|
+
to the development database. Passing an argument will connect you to a different
|
151
|
+
database, like <tt>rails dbconsole production</tt>. Currently works for MySQL,
|
152
|
+
PostgreSQL and SQLite 3.
|
153
|
+
|
154
|
+
== Description of Contents
|
155
|
+
|
156
|
+
The default directory structure of a generated Ruby on Rails application:
|
157
|
+
|
158
|
+
|-- app
|
159
|
+
| |-- controllers
|
160
|
+
| |-- helpers
|
161
|
+
| |-- models
|
162
|
+
| `-- views
|
163
|
+
| `-- layouts
|
164
|
+
|-- config
|
165
|
+
| |-- environments
|
166
|
+
| |-- initializers
|
167
|
+
| `-- locales
|
168
|
+
|-- db
|
169
|
+
|-- doc
|
170
|
+
|-- lib
|
171
|
+
| `-- tasks
|
172
|
+
|-- log
|
173
|
+
|-- public
|
174
|
+
| |-- images
|
175
|
+
| |-- javascripts
|
176
|
+
| `-- stylesheets
|
177
|
+
|-- script
|
178
|
+
| `-- performance
|
179
|
+
|-- test
|
180
|
+
| |-- fixtures
|
181
|
+
| |-- functional
|
182
|
+
| |-- integration
|
183
|
+
| |-- performance
|
184
|
+
| `-- unit
|
185
|
+
|-- tmp
|
186
|
+
| |-- cache
|
187
|
+
| |-- pids
|
188
|
+
| |-- sessions
|
189
|
+
| `-- sockets
|
190
|
+
`-- vendor
|
191
|
+
`-- plugins
|
192
|
+
|
193
|
+
app
|
194
|
+
Holds all the code that's specific to this particular application.
|
195
|
+
|
196
|
+
app/controllers
|
197
|
+
Holds controllers that should be named like weblogs_controller.rb for
|
198
|
+
automated URL mapping. All controllers should descend from
|
199
|
+
ApplicationController which itself descends from ActionController::Base.
|
200
|
+
|
201
|
+
app/models
|
202
|
+
Holds models that should be named like post.rb. Models descend from
|
203
|
+
ActiveRecord::Base by default.
|
204
|
+
|
205
|
+
app/views
|
206
|
+
Holds the template files for the view that should be named like
|
207
|
+
weblogs/index.html.erb for the WeblogsController#index action. All views use
|
208
|
+
eRuby syntax by default.
|
209
|
+
|
210
|
+
app/views/layouts
|
211
|
+
Holds the template files for layouts to be used with views. This models the
|
212
|
+
common header/footer method of wrapping views. In your views, define a layout
|
213
|
+
using the <tt>layout :default</tt> and create a file named default.html.erb.
|
214
|
+
Inside default.html.erb, call <% yield %> to render the view using this
|
215
|
+
layout.
|
216
|
+
|
217
|
+
app/helpers
|
218
|
+
Holds view helpers that should be named like weblogs_helper.rb. These are
|
219
|
+
generated for you automatically when using generators for controllers.
|
220
|
+
Helpers can be used to wrap functionality for your views into methods.
|
221
|
+
|
222
|
+
config
|
223
|
+
Configuration files for the Rails environment, the routing map, the database,
|
224
|
+
and other dependencies.
|
225
|
+
|
226
|
+
db
|
227
|
+
Contains the database schema in schema.rb. db/migrate contains all the
|
228
|
+
sequence of Migrations for your schema.
|
229
|
+
|
230
|
+
doc
|
231
|
+
This directory is where your application documentation will be stored when
|
232
|
+
generated using <tt>rake doc:app</tt>
|
233
|
+
|
234
|
+
lib
|
235
|
+
Application specific libraries. Basically, any kind of custom code that
|
236
|
+
doesn't belong under controllers, models, or helpers. This directory is in
|
237
|
+
the load path.
|
238
|
+
|
239
|
+
public
|
240
|
+
The directory available for the web server. Contains subdirectories for
|
241
|
+
images, stylesheets, and javascripts. Also contains the dispatchers and the
|
242
|
+
default HTML files. This should be set as the DOCUMENT_ROOT of your web
|
243
|
+
server.
|
244
|
+
|
245
|
+
script
|
246
|
+
Helper scripts for automation and generation.
|
247
|
+
|
248
|
+
test
|
249
|
+
Unit and functional tests along with fixtures. When using the rails generate
|
250
|
+
command, template test files will be generated for you and placed in this
|
251
|
+
directory.
|
252
|
+
|
253
|
+
vendor
|
254
|
+
External libraries that the application depends on. Also includes the plugins
|
255
|
+
subdirectory. If the app has frozen rails, those gems also go here, under
|
256
|
+
vendor/rails/. This directory is in the load path.
|
@@ -1,12 +1,7 @@
|
|
1
1
|
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
2
2
|
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
3
3
|
|
4
|
-
require
|
5
|
-
|
4
|
+
require File.expand_path('../config/application', __FILE__)
|
6
5
|
require 'rake'
|
7
|
-
require 'rake/testtask'
|
8
|
-
require 'rake/rdoctask'
|
9
|
-
|
10
|
-
require 'tasks/rails'
|
11
6
|
|
12
|
-
|
7
|
+
RailsTest::Application.load_tasks
|
File without changes
|
@@ -1,5 +1,5 @@
|
|
1
1
|
class UploadsController < Uploader::UploadsController
|
2
|
-
|
2
|
+
|
3
3
|
def get_redirect(source)
|
4
4
|
case source
|
5
5
|
when :destroy_success
|
@@ -16,7 +16,10 @@ class UploadsController < Uploader::UploadsController
|
|
16
16
|
end
|
17
17
|
|
18
18
|
def get_upload_text(upload)
|
19
|
-
|
19
|
+
%Q{<div>
|
20
|
+
<img src="#{upload.icon}" />
|
21
|
+
<a href="#{upload.file.url}">#{upload.file_name}</a>
|
22
|
+
</div>}
|
20
23
|
end
|
21
24
|
|
22
25
|
end
|
File without changes
|
@@ -0,0 +1,38 @@
|
|
1
|
+
# == Schema Information
|
2
|
+
#
|
3
|
+
# Table name: uploads
|
4
|
+
#
|
5
|
+
# id :integer not null, primary key
|
6
|
+
# creator_id :integer
|
7
|
+
# name :string(255)
|
8
|
+
# caption :string(1000)
|
9
|
+
# description :text
|
10
|
+
# is_public :boolean default(TRUE)
|
11
|
+
# uploadable_id :integer
|
12
|
+
# uploadable_type :string(255)
|
13
|
+
# width :string(255)
|
14
|
+
# height :string(255)
|
15
|
+
# local_file_name :string(255)
|
16
|
+
# local_content_type :string(255)
|
17
|
+
# local_file_size :integer
|
18
|
+
# local_updated_at :datetime
|
19
|
+
# remote_file_name :string(255)
|
20
|
+
# remote_content_type :string(255)
|
21
|
+
# remote_file_size :integer
|
22
|
+
# remote_updated_at :datetime
|
23
|
+
# created_at :datetime
|
24
|
+
# updated_at :datetime
|
25
|
+
#
|
26
|
+
|
27
|
+
class Upload < ActiveRecord::Base
|
28
|
+
|
29
|
+
include Uploader::Models::Upload
|
30
|
+
|
31
|
+
validates_attachment_presence :local
|
32
|
+
validates_attachment_size :local, :less_than => 10.megabytes
|
33
|
+
|
34
|
+
def can_edit?(user)
|
35
|
+
return true
|
36
|
+
end
|
37
|
+
|
38
|
+
end
|
File without changes
|