How to update avatar/photo of a model directly? - ruby-on-rails

This is rails 3.0.x. I was just wondering how to update an attribute of a model's photo/avatar directly without prompting the user to upload from his/her system?
I am using Paperclip to attach a photo to a model; It has the extension so that a user can use a URL to upload a photo. This works.
Now, I was looking at Canvas2Image, and it returns an image of the canvas so user's can download them.
I was wondering how to use the URL that Canvas2Image returns so I can update the current model's photo directly?
For now, I have this form that prompts the user to update the current model's avatar/photo:
<% form_for(#prototype,
:url=>{:controller=>"prototypes",
:action=>"update"},
:html => { :multipart => true }) do |f| %>
<%= f.file_field :avatar %><br><br>
<%= f.text_field :image_url %><br><br>
<%= submit_tag "Save Prototype" %>
<% end %>
Any help is appreciated, thanks!

From your link to Canvas2Image above it looks to me like you are trying to handle Base64-encoded images (like data:image/octet-stream;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wB).
Paperclip expects a Tempfile object, which is created behind the scenes for you when you upload an image. It is possible to fake a Tempfile by using a StringIO object and adding content_type and original_filename instance methods.
I posted a gist with the code I used to accomplish this in one of my projects. https://gist.github.com/1012107.
For you to do something similar you'd need to remove the beginning portion of the Canvas2Image URIs data:image/octet-stream;base64, and use the remaining Base64 code as the image_data. You'd need a way to provide or work around the content-type and filename.
If you just want to use normal URLs like http://example.com/image.jpg then you have several available options.
You could simply save the URL and use it as an image source on your pages. I know this isn't always an option, and you have no control over the availability of the image.
Otherwise, there are several utilities such as net/http and curl that you could use to download the image. If you think you want to go this route then you might also consider downloading the images using delayed jobs or a similar background process. That way your UI doesn't hang if the image download is slow.

If you want to fetch the gravatar using users' email address you can use the following code snippet.
In a helper:
def avatar_url(user)
gravatar_id = Digest::MD5.hexdigest(user.email.downcase)
return "http://gravatar.com/avatar/#{gravatar_id}.png?s=48&d=#{CGI.escape(default_url)}"
end
In your view:
<%= link_to(image_tag(avatar_url(user)), user_path(user))%>
That's it! You need not to ask user to upload your photo in your system. It will show the photo of his gravatar account. Please let me know whether it solves your problem.

This link might be what you're looking for
However, if you haven't done much work with paperclip yet, I would recommend you to swap to CarrierWave.
The same thing is done with two lines of code:
#prototype.image_remote_url = canvas2image_url #you should change this
#prototype.save

Related

Creating a If statement to post a themify image next to a post title

I created a simple blog and I'm using paperclip to be able to add images to a Post. I installed the 'themify-icons-rails' gem and what I want to do is automatically add a picture icon next to the title of a post when the post has a image that's been uploaded, to show that the post has a image. I'm guessing I would need a If statement somewhere but I'm fairly new to rails and I'm not sure where to put it.
<h2 class="ti-gallery"><%= link_to post.title, post %></h2> this adds the "Ti-gallery" icon to every post.
Any Help will be greatly appreciated, Thank you before hand. Oh and one more questions, Is rails Video friendly? i can't seem to find any tutorials on uploading videos to a rails app.
You can try to check if there is image posted, by checking the return data as you render it in page, like:
I assume you have the following field names under
Posts Table (image_file_name, image_content_type, image_file_size),
since you are using Paperclip, if yes? Then you have codes in Post Model for image upload.
My answer should be in index.html.erb as your
Posts controller render like #posts.
Finally you can do inside interation, like :
Key: post.image returns application root path as generated by paperclip.
Example: "/images/posts/1/original/sample.jpg"
<% unless post.image.nil? %>
// render image here
<% else %>
// render default image
<span class="ti-image"></span>
<% end %>
Please modify the code, as what you need.
Note, that you can use if statement instead of unless. No problem with that.
The unless statement checks if the image is present or not nil.
Additional Info:
https://github.com/hpoydar/themify-icons-rails
http://themify.me/themify-icons

Preventing users of my web application from modifying image id while uploading to cloudinary

I am building a rails web application where users can upload images from the browser to cloudinary. I am thinking a bit ahead, and want to prevent users from playing with the parameters being passed, in order not to have undesirable output in may pages (empty images).
In my view I have the code for the cloudinary uploader:
<%= form_tag(some_path, :method => :post) do %>
<%= cl_image_upload_tag(:image_id) %>
...
<% end %>
Now, when the user upload the image it goes directly to cloudinary, and the process returns :image_id. When the user accepts the image, I receive it in my controller like this:
if params[:image_id].present?
preloaded = Cloudinary::PreloadedFile.new(params[:image_id])
raise "Invalid upload signature" if !preloaded.valid?
#model.image_id = preloaded.identifier
end
That image ID gets saved in my database for future retrieve.
Now what if the user uses a tool such as "curl", or any other method that would allow him to modify the returned :image_id before submitting it to the controller ? I will have a wrong value in my database that would be difficult to find and an empty image when I try to show it in my pages. What is the best method of avoiding this ?
Regards,
When using cl_image_upload_tag, the value of params[:image_id] will contain a signature. The signature is validated by PreloadedFile#valid? You can know for sure that this public_id and version were returned by Cloudinary. If needed, you can also verify the version (unix timestamp) is reasonably recent.

image uploads using carrierwave backgrounder, then listening for finished uploads so I can reload the page

I am using jquery-fileupload-rails/carrierwave/carrierwave_background/sidekiq/fog+s3 to do this:
Allow user to upload an image, process this image (create multiple versions/sizes) in the background with sidekiq, then upload these versions + original to Amazon S3. This works fine. (Though I suspect this is probably a really inefficient/crappy way to do this, and I should be uploading directly using client-side javascript. But I don't know how to do that.) The user goes to a new photo page to upload a photo, and then gets redirected to the photo index page which shows all the photos. The problem is that since it takes a while to process the images, when the user is redirected to the index, the processing hasn't happened yet. Instead the user sees a 'processing image...' text where the image would be, based on a flag that is set on the image record. (I picked most of this up from a ryan bates railscast.) This is, obviously, not a great way to ingratiate to your users!
Is there any way to have the index page listen for the flag to be (un)set, or for something else to happen so that it will reload itself when it's ready to display the photo?
My new photo form looks something like this:
= simple_form_for #photo, url: user_photos_path(#user) do |f|
%span.fileupload-new
Choose a file
= f.file_field :image, label: "Choose a file:", id: 'upload-field'
= f.button :submit, 'Upload photo'
the photos#index looks something like this:
%ol
- photos.each do |photo|
%li
%figure
- if photo.image_processing?
%em processing photo...
- else
= image_tag(photo.image_url(:standard))
Any advice would be appreciated, whether it is a solution or just a different way of approaching this. Thanks.

Fragment Caching and User avatars/images

We use Gravatar on our website, but we want to let users upload their profile images directly in an effort to improve user experience similarly to what Stackexchange has been doing.
On our website users can follow each other, comment, 'like' and interact in ways that cause content to be generated directly and indirectly.
This means that cache-fragments with user avatars are scattered all over the place, and we can't find a reasonable way to invalidate it without negatively affecting render performance.
Here are the possible solutions we've looked at:
Option 1) Take the Gravatar approach and set very short Expires/Cache-Control max-age headers and recycle the same image filename.
Option 2) Use a placeholder image for all users with a data attribute containing the user ids that are read by JavaScript and used to make a second Ajax request asking the server for up-to-data avatars.
Is there any better way to solve this problem? Are we overlooking something?
I think I understand your question, but Im not sure I understand option 2 as a solution, which may indicate that its not a great solution. If it was me I would just cache the html surrounding the user gravatar, which is being reused, in a top level cache key, keyed by the users id. I.E.
<% cache("user_#{user.id}_profile_image") do %>
<img src="blahblahblah or gravatar helper code or whatev">
<% end %>
If you're concerned about a user uploading a gravatar, and subsequently having a cached default gravatar image, I would say your best options are:
1) In the users profile area where you send them to upload a gravatar, have a refresh link which points to a refresh action which actually invalidates that users cache fragment. i.e.
expire_fragment "user_#{user.id}_profile_image"
(http://guides.rubyonrails.org/caching_with_rails.html)
2) you could instead of using the default gravatar redirect to upload an image, you could intercept the click, send it to your own controller, schedule a background task to be run in 15 minutes or so, and then render a javascript response which redirects them to the actual gravatar page to upload their pic. The background worker would then clear the fragment at a later time when it ran. This assumes they actually upload their image and is alltogether I would say a terrible idea.
Honestly though, Im not sure why you are concerned about caching the gravatar to begin with. It's hitting gravatars servers so it causes no load on your server, storing it yourself seems a bit self defeating to the point of using gravatar. Hopefully your question was simpler (and was just: how to clear default cached gravatar image when user uploads their own image), which can be solved by #1), which will allow you to expire the cached gravatar image and recache it using your own image, after the user uploads their image. (which, next time the page was rendered would recache the image because youd have some logic like:
<% cache("user_#{user.id}_profile_image") do %>
<% if user.has_uploaded_image? %>
<%= display_profile_image %>
<% else %>
<%= display_gravatar_image %>
<% end %>
<% end %>

Keep form data when form is loaded a second time

I have a from that does two things.
Gets user text input.
Users can select an image or upload their own.
Problem occurs when user uploads their image.
The file field must submit the information to upload the image. It does all works.
But when the form is shown with the uploaded image, the text the user entered is gone. I understand that the instance variables won't keep the data.
How can I make this work so the text is not lost?
Must I use AJAX?
Thank you in advance.
if you are using form_for,
# your_controller.rb
def new # method where you show the form
#some_model = SomeModel.new(params[:some_model])
end
# new.html.haml - i like haml
- form_for #some_model do
... # all your inputs (they will be pre-set if you submit the form and it stays in new method
if you are using form_tag
# new.html.haml
- form_tag do
= text_field_tag :some_attribute_name, params[:some_attribute_name]
= select_tag :another_attribute_name, options_for_select(['option1', 'option2', 'and so on'], params[:another_attribute_name])
so depends on what you using, choose the respective way ;-) hope this helps =)
HOWEVER
i think the image should be submitted together with the form and saved together, i.e. it shouldn't be a separate process, unless of course you are talking about the form is saved and you are redirecting to an edit page... either way, both methods should work =)

Resources