Paperclip use params in :url option - ruby-on-rails

I have two models: photos and properties. A property has_many photos. When uploading a photo via paperclip I want the directory structure to be something like properties/the_property_id/:id.:style (of course, the second :id here would be the image id since thats what model were in).
A photo is added and edited via the properties model (accepts_nested_attributes_for). So, while viewing the property edit page I need a way of passing the property id (params[:id]) to the photos model so paperclip can use something like :url => properties/params[:id]/:style/:id.:extension. (properties/6/small/2.jpg)
Looking for advice on the best way to do this... How would you accomplish this task?

You need to use Paperclip interpolations(see https://github.com/thoughtbot/paperclip/wiki/Interpolations for details). Then you can have something like this:
Paperclip.interpolates :param_value do |attachment, style|
attachment.instance.property.params[attachment.instance.id]
end
And use it in your model in such way:
:url => properties/:param_value/:style/:id.:extension

Related

How to define url/path for each style with Paperclip

I'm trying to have a different URL definition for each style, something like:
has_attached_file :asset, styles: {
original: "1920x1920>",
cropped: {:geometry => "200x200#", :processors => [:cropper] }
},
urls: {
original: "/images/:hash_path/:filename",
cropped: "/images/:hash_path/cropped/:filename"`
}
The goal is to store the same image only once according to the MD5 checksum (fingerprint), but use the checksum of the current style (like thumb, cropped) instead of the original file.
Example: 10 students uploaded the same school photo and selected area of their face for avatar creation. The large school photo should be saved only once in the storage, but keep each avatar is necessary.
So far I haven't found a easy way how to do it with Paperclip which is able to save fingerprint just for the original image now. I'm curious if there is a way how to define url per style? That could particularly solve this.
Thanks for any other suggestions how to proceed.
Edit: By /:hash_path I mean some kind of interpolation like mentioned here http://jonathanng.com/ruby-on-rails/getting-around-ext3-inode-limitations-using-md5-file-paths-and-paperclip-interpolations/
One suggestion to proceed is to use interpolations https://github.com/thoughtbot/paperclip/wiki/Interpolations
Set url something like:
:url => "/attachments/:hash_path/:basename_:style.:extension",
then in the interpolations:
Paperclip.interpolates :hash_path do |attachment, style|
hash_path = "whatever_#{style}" # generate hash path here
end
this should put whatever hash_path interpolation returns into url replacing the :hash_path key.

Ruby on Rails, pass Image from one object to another or from NEW to CREATE

I'm pretty new to Ruby on Rails.
I changed this thread, because i recognized that I was searching for my problems' solution at the wrong end.
Here's my Problem:
I got a Class ProfileProposal which I upload an Image with(Using CarrierWave).
Now I want to convert ProfileProposal to another class, called Profile.
So I pass all the Information to the NEW-Form of Profile.
Works fine with strings, but not with Images.
What I've already tried/done:
Pass the Image as GET Param to the Create Method:
<%= form_for #profile, :url => { :action => "create", :controller => "profiles", :image => #profile_proposal.image } do |f| %>
#
Which now works, so I DO have the image-url.
What's not working is the following:
#profile = Profile.new(params[:profile], :image => new_image_url)
# OR
#profile.image = new_image_url
#profile.image still has the default value given by Carrierwave.
Thanks in advance!
I'm coming from using paperclip, not carrierwave, so I'll try to keep this high level. But I have an idea for you. Maybe you can set the filename of the new attachment before it exists, then move the image to that path. With paperclip this would play out like:
#profile.image_file_name = "profile.jpg"
# creates the directory of the new path. There's probably a better way to do this:
FileUtils.mkdir_p #profile.image_file_path.gsub(/[^\/]*$/,'')
FileUtils.mv #profile_proposal.image_path #profile.image_path
You should embed a hidden field in that Profile form, referencing ProfileProposal by some ID. Then while handling the form server side, after everything is validated and ready for save, you should copy the image using some read/write methods, from ProfileProposal instance to Profile instance. I'm not sure how CarrierWave wants you to do this.
I finally fixed that problem, by using paperclip and creating a new Instance via
Profile.create(:name => #profile_proposal.name, :image => #profile_proposal.image)

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