Hi I'm currently making an app for users to upload pics. I'm trying to add Amazon S3 in preparation to deploy my app. I'm not getting any error, but after trying to set up Amazon S3 my pics aren't uploading properly. The pics are uploading properly onto Amazon, not in my database so that when I upload the pics and try to loop through them in the views to show them, nothing shows. Can anyone assist me?
Just as a sidenote, I'm using Paperclip + jQuery file upload (for multiple pic uploads) + Amazon S3 + a s3_direct_upload gem (https://github.com/WayneHoover/s3_direct_upload)
config routes (notice that pics is nested in albums and users) no issue here
Pholder::Application.routes.draw do
resources :users do
resources :friends
resources :albums do
resources :photos
end
end
end
users/show.html.erb (the page that is supposed to show my uploaded pics, no new pics are showing up even after my uploads)
<% #user.albums.each do |album| %>
<div class="albumthumb">
<%= link_to image_tag(!album.photos.empty? ? album.photos.first.avatar.url(:medium) : ("questionmark.png"), :size => "150x150"), user_album_path(#user, album) %>
<br>
<%= album.name %>
</div>
<% end %>
photos/new.html.erb (issue here as well)
#my new uploader that works with amazon s3, but doesn't seem to be storing the pics in my database
<%= s3_uploader_form post: user_album_photos_path, as: "photo[avatar]", id: "myS3Uploader" do %>
<%= file_field_tag :file, multiple: true %>
<% end %>
#this is my old upload form that worked fine when uploading pics to my local public directory.
#
#<% provide(:title, "Upload pictures") %>
#
#<%= form_for([#user, #album, #photo], :html => { :multipart => true }) do |f| %>
#
#<%= f.file_field :avatar, multiple: true, name: "photo[avatar]" %>
<div id="pics">
<%= render :partial => "photo", :collection => #photos %>
</div>
<script id="template-upload" type="text/x-tmpl">
<div class="upload">
{%=o.name%}
<div class="progress"><div class="bar" style="width: 0%"></div></div>
</div>
</script>
Here's my code on github: https://github.com/EdmundMai/railstest/blob/master/app/views/photos/new.html.erb
Let me know if you need me to upload any more code. Please help!
JQuery file upload just uploads the files to Amazon S3: it doesn't add the required Paperclip records to the database. To do that, you need to do a few more steps. See the jquery-fileupload-rails-paperclip-example or jQuery File Upload v4 for Rails 3.
Related
I can store the external image URL from the API response, and display it in view. But I am having trouble understanding how to store the the actual image so I can display it without calling the full external URL each time.
These are some of the resources I've looked at: Rails: upload a file OR store a url and http://code.runnable.com/UnsMH7fYN2V6AAAT/how-to-save-images-by-url-with-paperclip-for-ruby-on-rails-and-upload.
This is what I have so far:
# this is used for file upload from create form
has_attached_file :ephoto, :styles => { :medium => "480x270#", :small => "240x135#" }, :default_url => "/images/:style/missing.png"
if group_response.nil?
else
group_response.each do |group|
# stores external image URL into "ephoto_file_name"
event.update_attribute :ephoto_file_name, group["group_photo"]["photo_link"]
event.ephoto = open(group["group_photo"]["photo_link"])
end
end
The event.ephoto = open(group["group_photo"]["photo_link"]) does not seem to work properly. Using <%= image_tag event.ephoto.url %> just returns broken images.
Display image in view:
<% #events.each do |event| %>
<% if event.ephoto.path.present? && File.exist?(event.ephoto.path) %>
<%= image_tag event.ephoto.url(:medium) %>
<% else %>
<%= image_tag 'event-placeholder.png' %>
<%= image_tag event.ephoto_file_name %>
<% end %>
<% end %>
The <%= image_tag event.ephoto_file_name %> just uses the external URL each time to display the image instead of a stored image.
Is there a better way to display images from API responses? Any suggestions or insights would help. Thanks!
This is the code in _image_fields.html.erb
<div class="nested-fields">
<div class="image-fields"> <%= image_tag f.object.image_url(:thumb) if f.object.image_url.present? %>
<%= f.file_field :image %>
<%= f.hidden_field :image_cache %> </div> <div class="add-language-spacing"> <%= link_to_remove_association 'Remove Image', f, id: 'remove_photo' %> </div>
This is where i'm rendering that partial in _profile_form.html.erb
<p id="tag">Add Some Photos!</p>
<div>
<%= f.fields_for :images do |image| %>
<%= render "image_fields", f: image %>
<% end %>
</div>
And then finally, in profile/edit.html.erb
<div class="profile-form">
<h1 class="page-title">Update Profile</h1>
<%= render 'profile_form' %>
</div>
My uploader looks like this
# Create different versions of your uploaded files:
process resize_to_fit: [300,300]
version :thumb do
process resize_to_fill: [200,200]
end
The thumb version only shows up after I press update profile and then refresh the page. For whatever reason it won't show the thumbnail version when I press choose file.
This is the confusing part of webdevelopment when you are starting out: what is executed in the client (browser) and what is executed on the server.
1) You are using cocoon to build a form, this means all data inside the form is only processed on the server once you submit the form.
2) You are using carrierwave, which explicitly only works in ruby on the server.
So together this means: only after submitting the form to the server, your uploader will create the thumbnail, and thus only after submitting the image_url will be defined.
What you want is, once you select the image, it will show a thumbnail, before uploading it to the server, and this means you either need
ajax to immediately post to the server (and let it render the thumbnail)
a javascript solution, which will read the contents of the file and show it (client-side, in the browser), before sending it to the server
Personally I do not believe cocoon is the right tool for the job here. I would suggest using something like
jquery-file-upload
dropzonejs
Is there a way with a has_many association (User --> Uploads) to work with a nested form? I have the strong params working fine. Users can have 5 images uploaded. I am using accepts_nested_attributes_for in the model and uploading is working, but there are some gotchas.
But for example when I try to edit the User, and build only new images using:
(5 - #user.uploads.count).times { #user.uploads.build }
...it builds 5 upload entries within the nested form, no matter what. Form section looks like this:
<%= f.simple_fields_for :uploads do |i| %>
<hr>
<% user.uploads.each do |upload| %>
<% if upload.image? %>
<%= image_tag(upload.image.url(:medium), class: 'img-rounded').html_safe %>
<br>
<%= i.input :_destroy, as: :boolean,
label: false,
inline_label: 'Remove picture',
wrapper_html: { class: 'text-center' } %>
<% end %>
<% end %>
<%= i.file_field :image %>
<h4>or</h4>
<%= i.input :image_remote_url, label: 'Enter an image URL' %>
<% end %>
Previously I had images uploading via a Dropzone ajax form, but as a nested resource and URL to a distinct Uploads controller. Now I have to make the uploads on the same form as the User profile edit. Ideally I would like to use a Dropzone on the profile edit page, but that seems even worse.
If anyone has tips on how to handle multiple file uploads (new / create AND edit / update actions), where I can have a limit of 5 uploads, I'd love to hear it. Also, implementation of multiple nested uploads via an embedded Dropzone would be even better if possible.
I'm working with Ruby on Rails to develop an application and I'm really struggling with the following issue.
I have setup Cloudinary http://cloudinary.com/documentation/rails_integration and also Attachinary https://github.com/assembler/attachinary for users to upload a profile image using the rails application, I also want to be able to load these images in the Rails application to show the user's profile image.
I have setup the following code in the user.rb Model file
has_attachment :avatar, :accept => [:jpg, :png, :gif]
The edit page for User's comes under the Devise view in my application - edit.html.erb. The following form is what I'm using to upload User avatars/profile images:
<%= simple_form_for(resource, :as => resource_name, :url => registration_path(resource_name), :html => { :method => :post }) do |f| %>
<%= cl_image_upload_tag(:avatar) %>
<%= f.button :submit %>
<% end %>
In the same View file I'm using the following code to retrieve the profile image:
<div class="profile-image" align="center">
<% if #user.avatar.present? %>
<img src="<%= cloudinary_url(#user.avatar.path) %>" width="180px" height="180px" alt=""/>
<% else %>
<img src="<%= asset_path "person.png" %>" width="180px" height="180px" alt=""/>
<% end %>
</div>
Upon the image being uploaded to Cloudinary it is given a random file name, for example: ecwc8x4ult960jzk8dp0
Am I uploading the image correctly and how do I retrieve them?
In the form try: <%= user.attachinary_file_field :avatar %>.
You should be able to retrieve them through the model like this: <%= image_tag user.avatar.url if user.avatar? %>, or like it's said in the Attachinary's documentation: <%= cl_image_tag(#user.avatar.path, { size: '180x180', crop: :thumb, gravity: :face }) %>. Omit the <img> tag and I suggest to not use inline css.
You could have 400 error for serving the images over HTTP instead of HTTPS. To fix that you should add secure: true to the cloudinary.yml or add :secure => true to the image tag.
I can't write comments... Are there any errors, could you post error logs?
snippet from my model:
attr_accessible :package1_file_name, :package2_file_name
has_attached_file :package1
has_attached_file :package2
from my _form (simplified version):
<%= form_for(#submission, :html => { :multipart => true, :id => "fileupload" }) do |f| %>
<%= f.file_field :package1%>
<%= f.file_field :package2%>
<% end %>
The problem is that paperclip will insert two separate entries for each file in the database.
However, I want it to insert into only one entries since I have two separate fields in my table: package1_file_name, package2_file_name.
Is there a way to achieve this?
Thank you!
For Christian Varga:
Maybe I shouldn't simplified the code in my original question, but my view actually look like this after using the jQuery file upload plugin:
<%= f.fields_for :uploads do |upload| %>
<div class="row fileupload-buttonbar">
<!-- The first upload field -->
<span class="btn btn-success fileinput-button">
<%= upload.file_field :package1 %>
</span>
<!-- The second upload field -->
<span class="btn btn-success fileinput-button">
<%= upload.file_field :package2 %>
</span>
</div>
<% end %>
Where upload is a child model of the current model
I am not sure whether the multipart makes the two file fields act like separate attachment, but I am trying to merge those two attachments into one.
Ok, so I've done a bit of research and I'm still unable to replicate your issue. I built a test application with that code, and it only inserts a single entry into the database.
Create Project (terminal)
rails new paperclip-test
cd paperclip-test
echo "gem 'paperclip'" >> Gemfile
bundle
rails generate scaffold submission
rails generate paperclip submission package1 package2
rake db:migrate
Update Model (submission.rb)
attr_accessible :package1, :package2
has_attached_file :package1, :styles => { :medium => "300x300>", :thumb => "100x100>" }
has_attached_file :package2, :styles => { :medium => "300x300>", :thumb => "100x100>" }
Update controller (submissions_controller.rb)
def create
# #submission = Submission.new(params[:submission])
#submission = Submission.create(params[:submission])
end
Update form (_form.html.erb)
<%= f.file_field :package1 %>
<%= f.file_field :package2 %>
Update view (show.html.erb)
<%= image_tag #submission.package1.url(:medium) %>
<%= image_tag #submission.package2.url(:medium) %>
Run app & create new submission
Go back to console:
sqlite3 db/development.sqlite3
select * from submissions;
Result:
1|2013-02-21 21:16:38.898602|2013-02-21 21:16:38.898602|image_1.jpg|image/jpeg|54231|2013-02-21 21:16:38.419947|image_2.jpg|image/jpeg|61766|2013-02-21 21:16:38.658720
Paperclip instructions from https://github.com/thoughtbot/paperclip#quick-start