Cloudinary::CarrierWave how to select the upload folder in Cloudinary - ruby-on-rails

I try to use the module Cloudinary::CarrierWave, but all my images are stored in the root folder of the cloud.
I want all my files to go to a specific remote folder.
I try this in my class:
class PhotoUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
def storage_identifier
'specific_folder'
end
end
I know there is some options with Cloudinary::Upload.upload, but as I use simple form in ruby on rails, I don't have access to this method.
Does anybody has an idea to fix that ?

When using Carrierwave with server-side uploads, you can use a code like the following:
classPictureUploader < CarrierWave::Uploader::Base
include Cloudinary::CarrierWave
...
def public_id
return "my_folder/" + model.short_name
end
end
If you're using client-side upload, you can set the folder parameter when building the upload tag:
<%= f.cl_image_upload(:image, :folder => "my_folder") %>

thanks to your answer, I solve that with your help, and I can give some other tips.
I did something like this to separate folders, but sometimes model.id doesn't exist (I should add an if else)
def public_id
"artpieces/#{model.class}/#{model.id}"
end
This code doesn't work for me :
<%= f.cl_image_upload(:image, :folder => "my_folder") %>
I can write directly :
<%= f.input :photo, input_html: {accept: ('image') } %>
as my input is already a PhotoUploader declare like this in the model :
mount_uploader :photo, PhotoUploader

Related

ActiveStorage multiple upload with intermediate model

The goal
I want to upload multiple files. So one Intervention can have multiple Uploads and each Upload has one attached file to it. This way, each Upload can have one file attached with different status, name, visibility, etc. instead of having one Upload with has_many_attached
What I have done
I have one Intervention model that can have many uploads :
class Intervention < ApplicationRecord
has_many :uploads, dependent: :destroy
accepts_nested_attributes_for :uploads, :allow_destroy => true
end
Each uploads has one attached file using ActiveStorage :
class Upload < ApplicationRecord
belongs_to :intervention
has_one_attached :file
end
In my interventions_controller I do :
def new
#intervention = Intervention.new
#intervention.uploads.build
end
def create
#intervention = Intervention.new(intervention_params)
# + default scaffolded controller [...]
end
def intervention_params
params.require(:intervention).permit(:user_id, :comment, uploads_attributes: [:status, :file])
end
In my form I have :
<%= form.fields_for :uploads, Upload.new do |uploads_attributes|%>
<%= uploads_attributes.label :file, "File:" %>
<%= uploads_attributes.file_field :file %>
<%= uploads_attributes.hidden_field :status, value: "raw" %>
<% end %>
Problem
This solution works when I want to upload only one file. But if I want to upload two files I can't figure out. I can add multiple: true to the file_field but how to created multiple Upload with one file each ?
Should I save the uploaded files into a temp variable first, extract them from the intervention_params, then create the Intervention without any Upload, then for each uploaded files saved, build a new Upload for the newly created Intervention ?
I have done what I have proposed. I don't know if there is a more elegant way to do it but anyway, this is working.
In my form I just added a simple files field that can take multiple files
<div class="field">
<%= form.label :files %>
<%= form.file_field :files, multiple: true %>
</div>
I have added this to the permitted parameters :
params.require(:intervention).permit(:user_id, :comment, files:[]])
Then I create my Intervention by ignoring this files params and I use it later to create a new Upload record for each files submitted.
# First create the intervention without the files attached
#intervention = Intervention.new(intervention_params.except(:files))
if #intervention.save
# Then for each files attached, create a separate Upload
intervention_params[:files].each do |f|
upload = #intervention.uploads.new()
upload.file.attach(f)
upload.save
end
end

How to validate sizes of multiple image uploads in CarrierWave uploader

I have my uploader set up for multiple image uploads like so:
class User < ActiveRecord::Base
mount_uploaders :avatars, AvatarUploader
end
and in view file:
<%= form.file_field :files, multiple: true %>
The issue is that the result will be in a json string of image_urls.
How do I then validate the size of each individual image i have uploaded?
For example, each of the images should be less then 5.megabytes.
Thank you very much!
EDIT:
This is based on CarrierWave(0.11.0)'s new feature thanks to Gen.
How to: Validate attachment file size
And there is no such thing as mount_uploaders:
Undefined method `mount_uploaders'

Refile gem : multiple file uploads

I'm using Refile with Rails 4. I'm following their tutorial for multiple image upload. Each Post can have multiple Images. My models look like this:
Post.rb:
has_many :images, dependent: :destroy
accepts_attachments_for :images, attachment: :file
Image.rb:
belongs_to :post
attachment :file
I can upload files, fine by using:
<%= f.attachment_field :images_files, multiple: true, direct: true, presigned: true %>
but when I try to retrieve an image like:
<%= attachment_image_tag(#post.images, :file, :small) %>
I get the error:
undefined method file for #<Image::ActiveRecord_Associations_CollectionProxy:0x007fbaf51e8ea0>
How can I retrieve an image with refile using multiple image upload?
In order to retrieve images who belongs to a post, you need to iterate through the array of images.
<% #post.images.each do |image| %>
<%= attachment_image_tag(image, :file, :fill, 300, 300) %>
<% end %>
The helper attachment_image_tag take:
[Refile::Attachment] object : Instance of a class which has an attached file.
[Symbol] name : The name of the attachment column
So here, #posts.images holds an array of image object. It's that object who has an attached file.
class Image < ActiveRecord::Base
belongs_to :post
attachment :file
end
Then when you iterate images, you give to the helper the image object, and the name of the attachment column, here :file.
Are you on the master branch?
gem 'refile', require: "refile/rails", git: 'https://github.com/refile/refile.git', branch: 'master'

Rails: How to download a previously uploaded document?

I need my user to upload documents such ad pdf and txt on their profile. And I did that using Carrierwave, so I have a list of documents with titles and urls.
But how can I make other users download those files? Do I have to use a gem or is there something native I don't even know since I am very new to rails?
Thanks
EDIT:
society.rb
class Society < ActiveRecord::Base
...
has_many :documents, :dependent => :destroy
end
document.rb
class Document < ActiveRecord::Base
belongs_to :society
mount_uploader :url, DocumentUploader
end
And then this in the view I want to download files:
<% #society.documents.each do |doc| %>
<%= link_to "Download it", doc.url %> //url is the column name of the saved url
<% end %>
I don't use Carrierwave but I guess it's similar to Paperclip.
Therefore you should be able to use something like this
link_to 'Download file', user.file.url
This is assuming you have a user instantiated object from a Model with a 'file' carrierwave attribute. Replace this with your attribute name.
You can use the send_file method for this. Which could look like:
class MyController
def download_file
#model = MyModel.find(params[:id])
send_file(#model.file.path,
:filename => #model.file.name,
:type => #model.file.content_type,
:disposition => 'attachment',
:url_based_filename => true)
end
end
Check the apidock link for more examples.
Or you can put anchor tag:
in your controller:
#doc = "query to get the document name from your database"
#docpath = request.base_url+"/uploads/"+#doc
in your view:
<a href="#docpath" download>Download File</a>.

Use Carrierwave with Active Admin

Did any of you guys manage to get Active Admin with Carrierwave working?
When I installed AA everything worked fine but the image file upload
fields were plain text fields so added following:
ActiveAdmin.register Club do
form do |f|
f.inputs "Club" do
f.input :league
f.input :name
f.input :image, :as => :file
f.input :approved
end
f.buttons
end
end
Now it's displayed as a file upload field and I can select a file but
after I submitted the form nothing changed. There's still no image and
the image field is empty. Anyone knows what else to do to get it
working?
Finally found the problem.
form do |f|
needs to become:
form(:html => { :multipart => true }) do |f|
I still don't know why console is not working but well, at least I can upload new images now :) Thanks a lot for the help, bruno077!
Yes, it works without an issue, remember to set the attr_accessible if you haven't. According to your configuration, you should have the following code in your model:
#app/models/club.rb
class Club < ActiveRecord::Base
attr_accessible (previous list), :image #If exists
mount_uploader :image, ImageUploader
end
And of course you should have generated the Image uploader with
rails generate uploader image
Edit: you can follow Ryan's railscast if you have any issue. That's what I did for my ActiveAdmin app with Carrierwave

Resources