Paperclip association question - ruby-on-rails

I have two model
User and UserAgent
User has one UserAgent & UserAgent belongs to User
And UserAgent using Paperclip to upload file to server
Using this
has_attached_file :agreement,
:path => "#{Rails.root}/public/upload/new_agreements/:id/:basename.:extension"
This working fine.It is creating folders needed to upload the file.
But i need to create the folder like this
:path => "#{Rails.root}/public/upload/new_agreements/User:id/:basename.:extension"
That means I need to upload the file according to the User.id but not UserAgent.Id
Is there any way? You can ask questions if u don't understand the question.

Try that. I haven't test it, but you can modify it:
class UserAgent < ActiveRecord::Base
has_attached_file :file,
:path => lambda{ |a| "#{Rails.root}/public/upload/new_agreements/#{a.instance.user.id}/:id/:basename.:extension" }
end

Related

Rails Paperclip Gem - save parent model ID to path

I have a model of ThreesixtyViewer which also has a nested resource of the ThreesixtyViewerImage model. An image attribute is being saved via the paperclip gem - but I am having issues updating the file path how it's needed.
The images for each ThreesixtyViewer needs to be saved together within one directory that is associated with the specific viewer. For example:
/public/system/threesixty_viewer_images/12/large/filename.jpg
In this example, the 12 in the path would be the id of the specific threesixtyviewer - but I cannot find any examples with that functionality. If the ThreesixtyViewer had an ID of 57, then the path would look like so:
/public/system/threesixty_viewer_images/57/large/filename.jpg
threesixty_viewer.rb
belongs_to :article
has_many :threesixty_viewer_images, dependent: :delete_all
accepts_nested_attributes_for :threesixty_viewer_images, allow_destroy: true
threesixty_viewer_image.rb
belongs_to :threesixty_viewer
has_attached_file :image, styles: { small: "500x500#", large: "1440x800>" },
path: ':rails_root/public/system/:class/:VIEWER_ID/:size/:filename',
url: '/system/:class/:VIEWER_ID/:size/:filename'
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
I know the :path and :url attributes need to beupdated for the has_attached_file within the threesixty_viewer_image.rb - but I am unsure as to how I can get the id for the threesixty_viewer... for now I added a :VIEWER_ID in it's place.
Any help would be greatly appreciated! Thanks in advance for anyone who can lend an eye!
You can add any of the models attributes to that path for this object. I believe you can even go so far as adding anything that the method will respond to, so you can even create path helpers for returning specific strings (such as month it was saved, year, etc).
In your case, ThreesixtyViewerImage is a child model, your table should include a column for the parent model. In your case, that attribute is probably :threesixty_viewer_id
Here is what I think you need for setting that path on threesixty_viewer_image.rb:
has_attached_file :image,
styles: { small: "500x500#", large: "1440x800>" },
path: ":rails_root/public/system/:class/:threesixty_viwer_id/:size/:filename",
url: "/system/:class/:threesixty_viewer_id/:size/:filename"
validates_attachment_content_type :image, content_type: /\Aimage\/.*\Z/
EDIT
Everything I said above is dead wrong. My apologies! What you need to use is a Paperclip::Interpolation. Here's a link
Here's what I did to make use:
Create a new file: config/initializers/paperclip_interpolators
Place something like this in that file:
Paperclip.interpolates :threesixty_viewer_id do |attachment, style|
attachment.instance.threesixty_viewer_id
end
Restart your application
Regenerate your paths/folders for the attachments. Here's a Link
Anytime you want another attribute in your path, just add another interpolator! Sorry again for misleading you before.
#colin_hagan is on the right path - I would suggest you look into Paperclip Interpolations:
#app/models/threesixty_viewer_image.rb
class ThreesixtyViewerImage < ActiveRecord::Base
belongs_to :threesixty_viewer
has_attached_file :image,
path: ":rails_root/public/system/:class/:threesixty_viewer_id/:size/:filename",
url: "/system/:class/:threesixty_viewer_id/:size/:filename"
Paperclip.interpolates :threesixty_viewer_id do |attachment, style|
attachment.instance.threesixty_viewer_id
end
end
Notice the double quotes, rather than single.
Double quotes should be used for interpolation - single quotes are for literal strings (I think).
Another thing I found some time back is the paperclip_defaults option -- allowing you to specify styles etc for any attachments:
#config/application.rb
...
config.paperclip_defaults = {
styles: { small: "500x500#", large: "1440x800>" }
}
These can be overridden in your respective models - it's just handy for me, as it means you don't have to explicitly define styles each time you have an attachment.

How can I access current host and port on a model in Rails?

I am facing the following problem:
I am doing a Rails 4 webapp and we are using paperclip for profile images. If the user does not upload an image we provide a default one (like the facebook silhouette placeholder). So as paperclip eases handling default images, we are doing the following in the Profile model:
class Profile < ActiveRecord::Base
belongs_to :user
has_attached_file :image, :styles => { :medium => "300x300", :thumb => "100x100" }, :default_url => "assets/profiles/:style/placeholder.gif"
end
The big problem is that I need the complete URL of the image and NOT only the path so I am struggling to get the host and port before that path. Using action view helpers there did not help (asset_url helper)
I was thinking in initializing some constant or configuration or environment variable per environment. Will it be correct? Any other suggestions?
EDIT: I forgot to mention this: The resource (Profile) may have a custom picture or a default one. When it has a custom image, we store it in Amazon S3 and in that case profile.image.url returns full URL. In the other case, when it has not a custom picture it has a default image stored in app/assets/images and in that case profile.image.url returns just the path. I would like that the method image.url consistently return full URLs. – flyer88 just now edit
If, as you mention in your comment, you are providing an API endpoint, it might make more sense to determine the host, port, etc. in the controller. Something like this:
# routes.rb
get "/profile/:id" => "api#profile"
# profile.rb
def image_url_or_default request
if image
"#{request.protocol}#{request.host_with_port}#{image.url}"
else
"http://s3.amazon.com/my_bucket/default.jpg"
end
end
# api_controller.rb
def profile
profile = Profile.find params[:id]
render text:profile.image_url_or_default(request)
end
profile.image.url will be the full URL of the image.

paperclip - path in image.rb

I am using paperclip for uploading images in my rails application.
I have 2 models 'Image' and 'Book' where one book can have many Images and image belongs_to Book.
In my 'images' table, I have 4 columns:
id
book_id
data_file_path
data_file_name
column 'data_file_path' stores the path of the image and column 'data_file_name' stores the image name and extension
In my image.rb file, I have the following lines of code:
has_attached_file :data, :path => "http://www.test.org/book/book_images/:data_file_path/:book_id/:style/:basename.:extension",
:url => "http://www.test.org/book/book_images/:data_file_path/:book_id/:style/:basename.:extension"
Notice the ':data_file_path' in the code above.
In my view, when i do <%=image.data.url(:thumb)%> i get the following path:
http://www.test.org/book/book_images/data_file_path/9124/thumb/1897_EK91_201107.jpg
Instead of retrieving the data_file_path value from the d-base, it's displaying the variable name.
How to I get the data_file_path value in the url.
Thanks a lot for your precious help. I have struggling with that since a while now.
Ah, I finally figured it out. I needed to use Paperclip.interpolates.
I added the following in config/initializers/paperclip.rb file
Paperclip.interpolates :data_file_path do |attachment, style|
attachment.instance.data_file_path
end
Then just add 'data_file_path' to the path in image.rb:
has_attached_file :data, :path => "http://www.test.org/book/book_images/:data_file_path/:book_id/:style/:basename.:extension",
:url => "http://www.test.org/book/book_images/:data_file_path/:book_id/:style/:basename.:extension"
Hope this might be of help to somebody else :)
cheers

Custom Paperclip processor not being called

I have a user model that is generated using Devise. I am extending this model using paperclip to enable file upload and also the processing of a file using a custom paperclip processor.
My paperclip field is declared in the user model as follows. PaperClipStorage is a hash that I create with the paperclip variables. Also, the being stored on AWS S3.
has_attached_file :rb_resume, PaperclipStorageHash.merge(:style => { :contents => 'resume_contents'}, :processors => [:resume_builder])
validates_attachment_content_type :rb_resume, :if => lambda { |x| x.rb_resume? }, :content_type => ['application/pdf', 'application/x-pdf', 'application/msword', 'application/x-doc']
The validates_attachment_content_type check is being done to make sure that it only processes pdf and MS word files.
My processor looks as follows
module Paperclip
class ResumeBuilder < Processor
def initialize(file,options = {}, attachment = nil)
#file = file
#attachment = attachment
puts "Attachment is not null " if !attachment.nil?
end
def make
rb = MyModule::MyClass.new(#file.path) ### Do something with the file
section_layout = rb.parse_html
#attachment.instance_write(:whiny, section_layout)
#file
end
end
end
In my user model I also have an after_save callback that is supposed to take the section_layout generated in the processors make method. Code is as follows
after_save :save_sections
def save_sections
section_layout = rb_resume.instance_read(:whiny)
# Do something with section_layout...
end
Now my problem is that the processor code is never being called, and I can't figure out why.
Because of that the section_layout variable is always nil.
Another point to note is that the same model also has two other has_attached_file attributes. None of the other two use a custom processor.
I've been struggling with this for last 3 hours. Any help would be greatly appreciate.
Thanks
Paul
Error in my has_attached_file declaration
has_attached_file :rb_resume, PaperclipStorageHash.merge(:style => { :contents => 'resume_contents'}, :processors => [:resume_builder])
should actually be
has_attached_file :rb_resume, PaperclipStorageHash.merge(:styles => { :contents => 'resume_contents'}, :processors => [:resume_builder])
Notice the plural styles as opposed to singular style

Rails 3.1 Paperclip - better way to organize folder structure for uploaded files?

I am using Paperclip to save files for Rails 3.1 app. Everything works fine, although I am a bit confused by the fact that everything is saved to the Public folder..
I have this kind of structure:
class Photo < ActiveRecord::Base
belongs_to :photoable, :polymorphic => true
has_attached_file :photo, :styles => { :large => "800x600", :medium => "400x300>", :thumb => "100x100>" }
end
class Project < ActiveRecord::Base
attr_accessible :projectname, :photos_attributes
has_many :photos, :as => :photoable
accepts_nested_attributes_for :photos, :allow_destroy => true
end
Obviously, there can be another models which also has_many :photos, :as => :photoable
Then if I upload a photo, it is saved to Public/system/photos/1 (or /2 etc.). Everything works fine, but I wonder if there is a better way to organize it (so that the folder structure is a bit more human-readable (has usernames, project names etc.)?
Also correct me if I am wrong, but I thought that the files should go to assets and not Public folder?
Thanks
This is what the :path option is for in has_atached_file. Check out the "Storage" section of the README:
https://github.com/thoughtbot/paperclip
The files that are assigned as attachments are, by default, placed in
the directory specified by the :path option to has_attached_file. By
default, this location is
:rails_root/public/system/:attachment/:id/:style/:filename. This
location was chosen because on standard Capistrano deployments, the
public/system directory is symlinked to the app's shared directory,
meaning it will survive between deployments. For example, using that
:path, you may have a file at
Content that is uploaded by users should go into public/system folder, while design elements like stylesheets, images and javascripts should be placed in app/assets corresponding folder.
If you want to add to file path some additional information that is not supported by default (like username), then you should take a look at paperclip interpolations ( https://github.com/thoughtbot/paperclip/wiki/Interpolations )

Resources