-
Notifications
You must be signed in to change notification settings - Fork 0
Upload files
programrails edited this page Nov 27, 2018
·
1 revision
<%#
# ====================================================
# CarrierWave multi-upload partial
# Just put this partial into your 'views/layouts' folder - and use CarrierWave multiple uploads in both edit-show pages:
#
# class FileUpload < ApplicationRecord
# has_many :images, dependent: :destroy
# accepts_nested_attributes_for :images, allow_destroy: true
# end
# class Image < ApplicationRecord
# mount_uploader :file, FileUploader
# belongs_to :file_upload
# end
<!-- db/migrate/20181126180719_create_images.rb -->
PostgreSQL option: (otherwise use t.json :string)
class CreateImages < ActiveRecord::Migration[5.2]
def change
create_table :images do |t|
t.json :file
t.references :file_upload, foreign_key: true
t.timestamps
end
end
end
# USAGE:
# Show action:
# <%= render 'layouts/uploaded_files', param: @file_upload %>
<%#
# Edit action:
# <%= render 'layouts/uploaded_files', param: form %>
<%
# These functions definitions are included into this view to make this partial "all-inclusive".
# The idea is that you simply add this partial into your Rails project - and that's it. No more mess.
# Meaning that you get the ability to handle CarrierWave multiple uploads in both edit-show pages for that.
# Including functions definitions into Rails view violates the architectural rules.
# But since image uploading usually happens only in the Admin area, I think that the architecture may be neglected here.
# Anyway if you are such a fan of architecture, you may move these functions definitions into a Rails module/service.
# Beware that CarrierWave multi-upload does NOT allow you to add/delete attachments by ONE (only all of them at once).
# That's why here a helper model is used (containing a single attachement). But you are free to choose whathever name
# for this helper model (not necessarily 'Image' - choose 'Attachment' if you wish), as it's name is auto-detected in this partial.
### ==================== CONFIG ===========================
# Change to 'false' if the uploaded files are not images
file_is_image = true
f = param
### ==================== END OF CONFIG ====================
def klass_name(f)
object = (f.respond_to? :object) ? f.object : f
object.class.to_s.underscore
end
def assoc_names(f)
klass = klass_name(f).camelize.constantize
# https://stackoverflow.com/a/12784574/6594668
klass.reflections.collect do |_, b|
b.class_name.underscore.pluralize if b.macro==:has_many && b.class_name.constantize.uploaders.present?
end.compact.first
end
def assoc_klass(f)
assoc_names(f).singularize.camelize.constantize
end
def helper_by_name(f, image)
klass = klass_name(f)
accepts_nested_attributes_for_params =
{
"#{assoc_names(f)}_attributes": { id: image.id, _destroy: true }
}
url_for(action: 'update', controller: controller_name, id: f.object.id, klass.to_sym => accepts_nested_attributes_for_params)
end
def file_url(request, file)
request.base_url.to_s + file.file.to_s
end
def file_names(f)
klass = klass_name(f)
"#{klass}[#{assoc_names(f)}_attributes][][file]"
end
%>
<% if f.class.to_s == "ActionView::Helpers::FormBuilder" %>
<div class="field">
<%= f.label "Uploaded file" %><br />
<% f.object.try(assoc_names(f.object)).each_with_index do |file, index| %>
<% if file.id %>
<% if file_is_image %>
<% url = file_url(request, file) %>
<div class="field">
<%= image_tag url %>
</div>
<% end %>
<div class="field">
<%= link_to "Delete", helper_by_name(f, file), method: :patch, data: { confirm: 'Are you sure?' } %>
</div>
<% end %>
<% end %>
</div>
<%= f.fields_for assoc_names(f).to_sym, assoc_klass(f).new do |ff| %>
<div class="field">
<%= ff.label "File" %><br>
<%= ff.file_field :file, :multiple => true, name: file_names(f) %>
</div>
<% end %>
<% else %>
<strong>Uploaded files:</strong>
<p>
<% f.try(assoc_names(f)).each_with_index do |file, index| %>
<% if file_is_image %>
<% url = file_url(request, file) %>
<div class="field">
<%= image_tag url %>
</div>
<% end %>
<div class="field">
id: <%= file.id %> <a href="<%= url %>" target="blank"><%= url %></a>
</div>
<% end %>
</p>
<% end %>
<%# console %>