Migrations
-
First we need to create a migration to add the file upload to our
Simulation
table:rails generate paperclip <ModelName> <FileName> #rails generate paperclip container myfile
-
Then we need to apply this migration:
rake db:migrate
Model
-
In the model (
app/model/container.rb
) we first add the common block of code which will need to be added for each individual file upload you want to handle (replace every occurrence ofmyfile
with what you chose):class Container < ActiveRecord::Base attr_accessor :myfile_cache attr_accessor :myfile_cache_name has_attached_file :myfile do_not_validate_attachment_file_type :myfile validates_presence_of :myfile end
-
Then we add caching methods that will apply to all file uploads you add:
class Container < ActiveRecord::Base ... # Creates a cache file and sets the appropriate cache file attributes from # the file currently staged in `:myfile` def myfile_set_cache myfile_rm_cache self.myfile_cache = File.join Dir.tmpdir, "#{SecureRandom.urlsafe_base64}.cache" FileUtils.ln myfile.staged_path, myfile_cache self.myfile_cache_name = myfile_file_name end # Deletes the cached file and resets the appropriate cache file attributes def myfile_rm_cache FileUtils.rm myfile_cache if File.exist?(myfile_cache.to_s) self.myfile_cache = nil self.myfile_cache_name = nil end end
If you add another file upload in the future, you will copy the given methods and replace the
myfile
occurrence with the name of the new file. -
We then add the callbacks that handle the cached file during various user requests:
class Container < ActiveRecord::Base ... # Cache file if it is staged otherwise assign the file to the cached file before_validation do if myfile.staged? myfile_set_cache elsif File.exist?(myfile_cache.to_s) self.myfile = File.new myfile_cache self.myfile.instance_write(:file_name, myfile_cache_name) end end # Clean up cache file after we successfully save the file after_save do myfile_rm_cache end end
If you add a new file upload, don't copy the callbacks. Instead copy the code inside the callback and replace all occurrences of
myfile
with your file name. -
Finally we modify the
copy
method to properly copy files when we copy simulations:class Container < ActiveRecord::Base ... # Make copy of workflow def copy new_container = self.dup new_container.myfile = self.myfile # make copy of file new_container.myfile_set_cache # cache this copy of the file new_container end end
If you add another file upload, just copy the lines with
myfile
occurrence. -
Confirm you renamed all occurrences of
myfile
to the name of the file you chose when using the Paperclip generator
Views
Show View
-
Add the file link to the
show.html.erb
file for the appropriate Simulation:<p> <strong>Myfile:</strong> <%= link_to @container.myfile_file_name, @container.myfile.url %> </p>
Form View
-
Add the file to the form in
_form.html.erb
for easy file uploading:<%= bootstrap_form_for(container) do |f| %> ... <%= f.hidden_field :myfile_cache %> <%= f.hidden_field :myfile_cache_name %> <%= f.file_field :myfile, label: "Myfile (#{f.object.myfile_cache_name || f.object.myfile_file_name})" %> ... <% end %>