Generating a unique file path with Polymorphic Paperclip - ruby-on-rails

I'm running into an issue with different users uploading files with the same name being overwritten with the Polymorphic Paperclip plugin. What I'd like to do is inject the current user's ID into the URL/path. Is this possible? Would I be better off generating a random name?
Here are my current :url and :path parameter values in asset.rb:
:url => "/assets/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/:id/:style/:basename.:extension"
What I'd like to be able to do is this:
:url => "/assets/#{current_users_id}/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/#{current_users_id}/:id/:style/:basename.:extension"

Use Paperclip interpolations:
file config/initializers/paperclip.rb:
module Paperclip
module Interpolations
def user_id(attachment, style)
current_user.id
end
end
end
has_ attached_file option:
:url => "/assets/:user_id/:id/:style/:filename"
(The syntax changed from Paperclip 2.x to 2.3; :path is not necessary; Use the latest version and have a look at the source, it's quite well documented.)

Every time I see the word random and it relates to strings, I think GUID. Perhaps they could work for you.

for me it didnt work bypaperclip.rb but it works like this:
In the model class:
class Micropost < ApplicationRecord
Paperclip.interpolates :user_id do |attachment, style|
attachment.instance.user_id
end
has_attached_file :pic1,
:url => "/Microposts/:user_id/:style/:basename.:extension"
In case if you want to do it by Paperclip interpolations you should find a path like this:
first find gem file path. type this in your terminal:
$ gem env
Then, it will show you a path in "- GEM PATHS:"
in my case this was the path :
:/usr/local/lib/ruby/gems/2.4.0/gems/paperclip-5.0.0/lib/paperclip
In this direction you can find "paperclip.rb" .

Related

Paperclip :url does not create Routes

What is the point of using the :url option with paperclip? The :path option does in fact change the location where the file is saved, but the :url option doesn't seem to do a thing. It only works when it points to a publicly accessible file location. At that point, the url is already accessible to anyone. If I change the url so that it doesn't match the path, it does not work. As far as I can tell, it does not create any routes either way. Is there something I am missing here. What is the point of this option? It seems overly confusing to let someone specify a :url without actually creating a route.
I found this post useful in understanding the difference between :path and :url.
:path sets the directory in your application where the file is stored.
:url sets the url that users can use to access the image.
You are right, paperclip does not create a route for you. However, the :url option does give you the ability to select which (existing) route your users can use to download a specific image.
:path and :url usually go hand in hand. If you stick to the paperclip :default_url the path is already configured for you. Just hit the url and everything will work fine.
Changing the file location
In this example I am rendering a users avatar:
<%= image_tag #user.avatar.url %>
Now, lets say that you wanted to change the location that images are stored, you can add the following code to your model:
has_attached_file :avatar,
:path => "public/system/:class/:id/:filename"
However, the image will not render successfully. This is because the new path, where your images are stored, does not match the :default_url. Therefore, you will also need to specify a new url:
has_attached_file :avatar,
:path => "public/system/:class/:id/:filename"
:url => "/system/:class/:id/:basename.:extension"
Now the image url matches the location that the file is stored on your server and the image renders successfully.
Path vs URL
To summarize, :url tells paperclip where abouts on the server to look for an image. :path tells paperclip where to upload an image, when creating or updating a record.
Both :path and :url should point to the same location, in order to render an image successfully.

Rails4 + Paperclip: Url and Path not matching

I use paperclip to upload a users avatar. The image is stored correctly in the /public directory. However I cant figure out how I can get the image displayed. I played with the :url and :path settings for about an hour and cant match them in a way the image will be displayed in the browser.
There is always a 'images/localhost' in the GET-requests path that I can not get rid of.
Here is my code:
user.rb
class User < ActiveRecord::Base
has_attached_file :avatar, :styles => { :medium => "300x300>", :thumb => "100x100>" }, :default_url => "missing.png",
:url => ':class/:id/:style.:extension',
:path => ':url'
validates_attachment_content_type :avatar, :content_type => /\Aimage\/.*\Z/
end
The path in the html-tag looked up by the request looks like this:
<img alt="Original" src="/images/localhost/users/1/original.png?1405249849" />
The correct request which returns the image would be
http://localhost:3000/users/1/original.png?1405248482.
How can I get the request match the correct file-system-path. Or: what is wrong with my settings?
I didnt change the application.rb or the development.rb
Best regards,
Kev
you should take url or path helpers of paperclip wherever possible. So to show the image use:
<%= image_tag #user.avatar.url(:medium) %>
Then:
the image url isn't a file system path. Depending on the storage you use in paperclip, images can reside in different places, see understanding storage of the paperclip gem.
If you use file storage, the files are store somewhere like
public/system/users/avatar/000/000/013/small/my_pic.png
Timestamp
What you're seeing is Paperclip's timestamp - the last time the file / object was updated.
Although I can't find any official reference to this number, it basically allows you to determine which files you're dealing with. According to the question referenced above, it's apparently there for if you want to ensure your visitors see the latest version of the file (IE never gets stored in the cache)
I'm not sure why there is a disparity between your stored image & your path. However, I would say the path is correct; you just need to be able to
--
Bottom line - if your image shows on the page, I don't think there's any systemic issue with your path; if it doesn't show on the page, can you provide logs / reference to the error?
This post, https://stackoverflow.com/a/26222093/1949363, which pointed to http://www.bwigg.com/2009/10/paperclip-customizing-paths-and-urls/ was the answer for me. I was having issues only in my test environment but I believe the fix should work in other environments as well.
Try the following settings:
:path => "public/system/:class/:id/:filename",
:url => "/system/:class/:id/:basename.:extension"

Rails Paperclip path and url NOT in public ... how?

So I am using paperclip to save images.
My problem is, that I have to store them out of the public-path.
When I try something like this:
:url => "users_pictures/:id/:basename.:extension",
:path => ":rails_root/assets/users_pictures/:id/:basename.:extension"
I get an error message, that the image isn't precompiled. If I remove :url and :path, everything works fine. So it is not a matter of my syntax in my view. I was thinking about access, but public has 710 and this assets-folder has 750. Do I have to modify my development/production.rb maybe ?
try this
:url => "users_pictures/:id/:basename.:extension",
:path => ":rails_root/public/assets/users_pictures/:id/:basename.:extension"

Paperclip image.url in Backbone.js Views

I am using paperclip to save images. Everything works fine and I am able to access the item's url with #item.image.url.
class Item
has_attached_file :image, :styles => {
:original => ['1920x1680>', :jpg],
:small => ['100x100>', :jpg],
:medium => ['250x250>', :jpg],
:large => ['500x500>', :jpg]
}
end
This is console:
> Item.last.image.url(:small)
=> "/system/images/items/1/small/chanel.jpg?1334005208"
This is straightforward and easy if I am templating HAML or ERB from the server and serving up the page to the user like this. items/show.html.haml:
.item
.item-image
= image_tag #item.image.url(:small)
However, with backbone.js, I am unable to construct the URL because I do not have the paperclip helpers in context. Essentially, I am sending the following attributes of the image to the page in json form.
#<Item:0x007fc97559b960> {
:id => 1,
:image_content_type => "image/jpeg",
:image_file_name => "chanel.jpg",
:image_file_size => 28880,
:image_updated_at => 2012-04-09 21:00:08 UTC
}
What is a ninja way to get the image.url included as an attribute on the item. How do I account for the style URLS? It would be nice to have an attribute like "image_small_url", "image_normal_url", etc predetermined and accessible. Thoughts?
I'm using Jbuilder to build the JSON views for a project I'm working on, so my index view, for example looks like this:
json.array!(#things) do |json, thing|
json.id thing.id
json.name thing.name
json.description thing.description
json.image_url thing.image.url
json.thumb_url thing.image.url(:thumb)
end
That way in my Backbone template, I can just say thing.get('image_url') and thing.get('thumb_url').
In brief, you'll want to use something like Jbuilder, or manually override as_json in your model. Personally, I like taking care of this at the view level, which is what Jbuilder allows you to do easily.
While generating JSON in controllers is doable, I greatly prefer wrapping up this kind of functionality in either decorators (e.g., Draper), or into frameworks designed for RESTful resources (e.g., Roar).
This keeps the mapping between models and their external representations highly localized, allows direct testing of representations outside of the web app framework, and so on.
For example, clem's answer would be isolated within a single class, roughly:
class ThingDecorator < Draper::Decorator
delegate_all
def image_url; object.image.url; end
def thumb_url; object.image.url(:thumb); end
end
Then in the controller, for example:
#things = Thing.some_scope.decorate # Or
#things = ThingDecorator.decorate_collection(Thing.all)
(Or whatever you need, and what works depends on the Rails version, see the Draper docs.)
Then expose the collection as JSON using normal means. IMO this is almost always cleaner.
Another simple example using jbuilder:
# index.json.jbuilder
json.array!(#shared_snap_casts) do |shared_snap_cast|
json.extract! shared_snap_cast, :id, :snap
end
Here the :snap is the paperclip attachment - the output from this example is:
[{"id":1,"snap":"/system/shared_snap_casts/snaps/000/000/001/original/some_icon.png?1388093936"}]
Hope this helps!

Paperclip won't save image in Rails app

I am trying to use Paperclip with my Rails app to add an avatar to a user but it won't save my image or update the database column when creating the user.
This is what the model looks like:
class User < ActiveRecord::Base
has_attached_file :avatar
And the registerform in haml:
- form_for :user, #user, :url => { :action => "signup" }, :html => { :multipart => true } do |f|
...
...
%li
%div{:class => "header"} Profilepicture
%div{:class => "input"}
= f.file_field :avatar
And when I look in the log this is what is being passed to the "signup" action:
Parameters: {"commit"=>"Save", "action"=>"signup", "controller"=>"user/register", "user"=>{"name"=>"Micke Lisinge", "birthmonth"=>"07", "password_confirmation"=>"[FILTERED]", "nickname"=>"lisinge", "avatar"=>#<File:/tmp/RackMultipart20100426-3076-1x04oxy-0>, "gen"=>"m", "birthday"=>"23", "password"=>"[FILTERED]", "birthyear"=>"1992", "email"=>"lisinge#gmail.coma"}}
[paperclip] Saving attachments.
Paperclip says it is saving the template but when I look in the public folder in my app it has created a system but the system folder is empty.
So it seems like it isn't saving the picture to the folder.
It gets handled by the form and saved in my /tmp folder.
Maybe you guys have any tips or know what this problem might be?
I got it to work.
I had to add :avatar to attr_accessible in my user model.
Posting this here and hopes that it helps someone sometime :)
Thanks guys for your help
Don't forget to set :multipart => true in your form declaration. This has bitten me once or twice.
has_attached_file :asset, :url => "/assets/:id/:style/:basename.:extension",
:path => ":rails_root/public/assets/:id/:style/:basename.:extension"
FYI, This code actually saved my files in the root directory of my machine "/" as the :rails_root param was failing. This is on Rails 3.0.0.rc
First check, if path is correct for the created attachment. You can use avatar.path to determine that. if it is not returning correct path, may be someone is overriding the default paperclip path?
Also check, if public/system is writable by the user as which you are running the application server.
Try setting the :path option
has_attached_file :avatar,
:path => ':rails_root/public/system/:id.:extension'

Resources