Multiple image upload Rails - ruby-on-rails

I have been stuck on a problem for three weeks now, and although I have tried everyday to find an answer to my problem, I haven't found anything that I have been able to make work. If anyone could help me, I would be very, very grateful.
I have built a basic blog in Rails that allows an admin user to publish articles using a form, containing a title text_field, body text_area, and file_field for an image, which uses Paperclip. All very simple and easy and no problems there. However, I have been trying to alter the form to allow an admin user to upload multiple images as part of a new article, but have been unable to find a way to do this.
I need a solution that will allow me to achieve multiple image upload functionality in a form. I have tried many gems and many tutorials, but have been unable to integrate anything into my app without completely breaking it. Can any one help me get out of this dead end I've found myself in for the last three weeks? Do you have any clear tutorials or solutions that will help me overcome this problem?
Thank you very much to anyone that can help me.

Your question is quite broad, without any schema or anything so I'll try to help you as much as possible given that.
If it's a blog, you might have a post model.
You could have a photo model, with a reference to the post model. If you add paperclip to your photo model, then you can save multiple photos.
There are multiple ways to do this. The first one I think of is using nested forms with a gem like cocoon.
The second I think of is using a dropzone, which would upload the photos using Ajax.

By default PaperClip allows you to upload one attachment. However, a clean way I've found to work around this is to create another model which would wrap around the images.
class Article < AR::Base
has_many :images
accepts_nested_attributes_for :images
end
class Image < AR::Base
belongs_to :article
has_attached_file :filename, styles: { medium: "300x300>", thumb: "100x100>" }, default_url: "/images/:style/missing.png"
validates_attachment_content_type :filename, content_type: /\Aimage\/.*\Z/
end
Don't forget to run a migration to create the images table:
rails generate model image article:references
and
rails generate paperclip image filename
Then in your articles/form, where you initially had the field to upload the image, you would have
<%= f.fields_for :images do |p| %>
<%= p.label :filename %><br>
<%= p.file_field :filename%>
<% end %>
In your articles_controller#article_params, along with the current params, you would have, params.require(:article).permit(..., images_attributes: [:filename])
Afterwards, allowing the uploads of multiple images would therefore only require the basic knowledge of nested forms.
To set a default number of file_fields, in your ArticlesController#new after initializing your #article you would have
def new
#article = Article.new
2.times{ #article.images.build}
end
With this setup, when you navigate to your new_articles route, you should see your article ready to upload 2 images.
To learn more about how to use NestedForms to do even more, you should see Ryan Bates tutorial.
This approach provides a cleaner interface, as the other approaches, I guess, would require some sort of hack.
Let me know if I'm able to help or further clarifications required.

Related

How to add a picture to a model (User) in Rails using ActiveStorage and the Cloudinary Upload Widget?

world!
After implementing Cloudinary's Active Storage Integration, it's easy to make it work in a form.
We just need to add to our simple_form_for a
<%= f.input :photo, as: :file %>
BUT, if we want to use the Cloudinary Upload Widget, there's no straightforward way of adding this file to the form.
What I have tried is:
1- let the widget upload the picture;
2- update the value of a hidden input with the url of the uploaded picture;
3- in the controller, when creating the model, download the picture and attach it to the model:
require 'open-uri'
file = URI.open(photo_url)
#user.photo.attach(io: file, filename: 'profile_photo.jpg')
# [...]
private
def photo_url
params.require(:user).permit(:photo_url)[:photo_url]
end
It works, BUT it uploads twice the same picture and - IMHO - is extremely inefficient.
Any ideas?
Thank you!
Good Luck, Have Fun!

Paperclip image medium size broken to missing link

I am doing the One Month Rails Course. I am using Rails 4. My Github folder is: https://github.com/phanatuan/pinteresting
I use the Paperclip gem. In the App/views/pins/show.html.erb, I want to show the pins picture at medium size. I passed the code <%= image_tag #pin.image.url %>. The browser shows the pin with the un-resized pictures. When i pass ":medium" into the code as such <%= image_tag #pin.image.url(:medium) %>, the browser shows the missing image.
I check all the documentations and follow closely the instructions but I could not find the mistake.
Really Appreciate your help
Tuan
Its hard to diagnose this without seeing the code, but my best guess is that you did not declare the style :medium for the attached file in your model.
Try this:
has_attached_file :image,
:styles => { :medium => "120x120>" }
Also, make sure that you specify a :style in your path declaration for the file.

Rails - HowTo - Handle Users w/o Images

I just installed paper_clip to allow user's to upload a profile pic which can be displayed easily with:
<%= image_tag #user.profile_pic.url %>
What I'm curious about now is how to handle user's that don't have a profile_pic uploaded.. How to show a standard site user image (generic)
Should I make a helper?
something like showProfilePic(#user, size)
And then use that helper to show the right size image, either the user's uploaded photo or a generic site profile pic?
thanks. Any existing helpers out there?
You can use the default_url and default_style options to set this. The default default_url is /:attachment/:style/missing.png, so you could drop in missing.png for each style and have that be your generic profile pic. If you want to customize, though...
class User < ActiveRecord::Base
has_attached_file :profile_pic,
:default_style => :thumbnail,
:default_url => '/path/to/:style_default.jpg'
end

Paperclip with albums

I'm struggling with paperclip and adding the attached images to albums. Should I be writing an album_id to the images row in the database? Right now, I'm trying to use an album model, which belongs_to :user and has_many :photos. The photo model belongs_to :album and has_attached_file. Is that the way to go about it?
I'm really new to Rails so i'm still getting hung up on things like...
<%= form_for #album, :html => { :mulitpart => true } do |f| %>
because I have no idea how #album is suppose to point to the right controller/action. Another thing is how the h*ll is photo suppose to know which album its apart of? Normally I would have said save the album_id in the photo row but I feel like I'm passing up paperclips functionality.
Rails still hasn't "clicked" for me =/
I think PHP ruined me...or the auto-magickness is too powerful for my mind.
There is no Magic in Rails . It all about how you understand the concepts . In order to understand the rails following things are essential
Basic Knowledge on Ruby
Agile web development will be kick start (Understand MVC Architecture)
Debugging Rails application and script/console
Coming back to your above Paperclip application .
Here #album is an instance variable which holds the value of the form fields like the title ,image etc.
<% form_for(#album,:url => {:controller => "albums" , :action => "create" }) do |f| %> correct syntax is this , which points to the albums controller create action , if you are familiar with the routes you can use new_album_path will also routes as same as above.
h*ll is photo suppose to know which album its apart of? Answer is through specifying Associations in the Model between album and Photo and User. Based on your requirement. set the associations. Associations are the relationship between to two tables , Like in PHP you do foreign key and relate two tables . Best book to learn this is Pro Active Record
Here is a nice tutorial by Jimneath
Hope it helps !

Adding a photo to a model's has_many model from a view

I have a model, Thing, that has a has_many with ThingPhoto, using Paperclip to manage everything. On the "show" view for Thing, I want to have a file upload, and have it relate to the Thing model.
For some reason, I'm totally glitching on how this should be done. I've tried doing this (Haml):
- form_for #thing.thing_photos, :html => {:multipart => true} do |f|
= f.file_field :photo
= f.submit
... and I get this error:
undefined method `array_path' for #<ActionView::Base:0x24d42b4>
Google is failing me. I'm sure this is super easy, but I just can't get my brain around it.
Edit: I should have mentioned that if I change the #thing.thing_photos to just #thing, it works fine, in that it displays the form, but of course it's not associated with the correct model.
try #thing.thing_photos.new
this should instance a new model of thing_photos. If you're not using nested routes you'll have to add the thing_id as a hidden field.
If you're not tied to Paperclip (and if you're just doing images), I've had a lot of luck with fleximage. It's got really good documentation for image upload, manipulation, and display (with all sorts of neat effects like watermarking and stuff).
It doesn't quite answer your question, but it might be a cool thing to look into.
But I bet your problem related to the fact you're creating a form for an array of objects (through an association). I bet something is finding the type of the object (should be "thing_photo" but is "array" in your example), and appending "path" to it to write the form post URL. Perhaps you should add a .first or create a partial?
The form should be for #thing_photo and should either pass in the thing_id or if it's a nested route you can get it from that
then in your thing_photos controller
#thing_photo = Photo.new(params[:thing_photo])
#if using nested route
#thing = Thing.find(params[:thing_id])
#if using hidden field
#thing = Thing.find(params[:thing_photo][:thing_id])
if #thing_photo.save
#this is what ties the thing photo to the thing
#thing.thing_photos << #thing_photo
end
If I understand the question correctly, this might help.

Resources