Paperclip not saving attachment - ruby-on-rails-3

I am unable to get Paperclip to save my attachment. Rather than saving a single image (such as an avatar as seems to be the common usage), I need to be able to upload/save multiple files; therefore I have a User model and an Asset model. The file information gets properly stored in the asset table, but the attachment itself is not saved in the filesystem as expected.
My log shows the message:
"[paperclip] Saving attachments."
but the attachment is not saved.
Here's a gist with the details: https://gist.github.com/1717415
It's gotta be something simple that I'm missing...

OK... found the problem and it's now working.
The first issue was my naming of the columns in the asset model. I had used simple names: i.e., :description, :file_name, :file_size, :content_type. What I needed to use was: :upload_description, :upload_file_name, :upload_file_size, :upload_content_type where the 'upload' (or whatever you want to use) is a prefix that Paperclip will recognize.And of course that changed my Asset model to reference :upload not :asset, as in:
has_attached_file :upload
Secondly (and this post Adding :multipart => true throws Undefined Method "name" error was key to understanding this) was that you cannot specify the full column name (:upload_file_name) in your view, just specify the prefix and Paperclip magically understands what you want.
Hope this helps someone else!

Did you install ImageMagick?
Did you added image_magick command_path via initializer?
if not, checkout this answer:
Weird paperclip error message

Related

PostgreSQL & DataMapper issues

Been scratching my head for a while on this one and despite trying many variations I cannot see the mistake. After writing the app file, which contains what looks like the correct DataMapper.setup code for using PostgreSQL (?), and upon trying to play around in IRB/PRY, i just get a 'FATAL database not created' message even after i have called 'Song.auto_migrate!', here is my code, can anyone help me get past this? Thanks in advance:
require 'data_mapper'
require 'dm-core' #main DataMapper gem
require 'dm-migrations' #extra DataMapper functionality extension
DataMapper.setup(:default, "postgres://localhost/development")
class Song
include DataMapper::Resource
property :id, Serial
property :title, String
property :lyrics, Text
property :length, Integer
property :released_on, Date
end
DataMapper.finalize
I require the file all fine in irb, then call Song.auto_migrate! and it runs the 'database does not exist' error. What am i doing wrong?
You need to do this in command line:
psql
and then
CREATE DATABASE development;
before even trying to run Data Mapper setup code.
Perhaps you are missing this line: DataMapper.auto_upgrade!
On a side note, remember that auto_migrate! will wipe any existing data, whereas auto_upgrade! doesn't: http://datamapper.org/getting-started.html

Where did my filename extension go in the parameter list

I am following this answer while trying to figure out how to display images located in my app directory Rails 3, displaying jpg images from the local file system above RAILS_ROOT
I've created a controller as shown there, added the match line to routes.rb, and in a test webpage I want to load up an image called test.jpg using the code
<img src="/serve_image/test.jpg" />
But I get an error saying the file <...>/public/images/test was not found.
Then I went and renamed my image so that the .jpg was gone, and then the script found my image and loaded it up as wanted.
Any ideas where the extension went? I am not sure how to debug this issue.
By default, Rails doesn't match dots in a dynamic segment. So for this route:
match '/serve_image/:filename' => 'images#serve'
:filename will only match up to the first dot it finds. So /serve_image/test.jpg will match test as the filename and will think you're expecting a JPG as a response. What you need to do is tell the router that you want to include the dot in the filename, something like this:
match '/serve_image/:filename' => 'images#serve', :constraints => {:filename => /[^\/]+/}
That will match anything except a forward slash, giving you your complete filename in params[:filename]
See the Rails Routing guide section on Dynamic Segments for more info.

Missing routes in rails after using resource keyword

Not sure what the issue is here, but I have a basic line in my routes.rb:
resource :videos
But I don't see all the paths. Namely:
GET /videos/:id
I only see the following when running "rake routes":
videos POST /videos(.:format) videos#create
new_videos GET /videos/new(.:format) videos#new
edit_videos GET /videos/edit(.:format) videos#edit
GET /videos(.:format) videos#show
PUT /videos(.:format) videos#update
DELETE /videos(.:format) videos#destroy
What am I missing? Thanks!
You make videos a singular resource, but videos is a collection so you have to do :
resources :videos
http://guides.rubyonrails.org/routing.html#crud-verbs-and-actions
Change your line to resources :videos, and the missing route will magically appear

Systematic way to upgrade from attachment_fu to carrierwave?

I'm working on upgrading an app to Rails 3, and attachment_fu is broken so I'm moving to carrierwave. Is there a systematic process that I can go through to upgrade from attachment_fu to carrierwave? Or a tutorial for it? Right now, I'm more interested in getting everything on the database end right. I'm using the filesystem store option for attachment_fu and carrierwave.
I've found a module, UploaderFu from http://ruby.simapse.com/2011/03/migrate-attachmentfu-to-carrierwave.html that tells carrierwave to use the same directories and filenames as attachment_fu. But it's not the entire answer, just part of it.
For example, in the db, I have a UserImage model, with :filename, :content_type, :size, :width, :height, and :user_id attributes. I added a :user_avatar column, and the following to my model
attr_accessible :user_avatar
mount_uploader :user_avatar, UserAvatarUploader
What exactly gets stored in :user_avatar. Is it just the filename? or something else? Do I just need to write a migration to move the data in :filename (stored like "hello_world.png") to :user_avatar? If that's the case I should just use the original :filename instead of creating a :user_avatar column, right?
The column you mount the uploader on is supposed to store an "identifier" for the uploaded file. By default it's just the filename, but you can override it to be almost anything apart from the ID of the record (because you can't know what that is until after saving).
To override: in your uploader class, add this definition :
def identifier
# This is what gets put in the database column!
model.created_on
end
In this example I've used the created_on attribute from the model. If you want to create your own storage mechanism then you need to be able to uniquely identify files by this identifier so be careful what you choose.
I would suggest renaming the column so it describes the file that's being uploaded (like in the carrierwave example). Then you can always change the identifier from filename to something else later.

Rails - Use same attachment for all emails using layout

I'm probably missing something obvious, but I've got a logo I'd like to include in all of the emails I send from my app. I have a master layout I'm using for all of those Mailers. I assume there's a way to do keep it DRY and not have to add the line of code to attach the file in every mailer method. Can someone point me in the right direction or correct my line of thought.
Thanks!
Callbacks using before_filter and after_filter will be supported in a future Rails release:
http://github.com/rails/rails/commit/4f28c4fc9a51bbab76d5dcde033c47aa6711339b
Since they will be implemented using AbstractController::Callbacks, you can do the following to mimic the functionality that will be present in ActionMailer::Base once Rails 4 is released:
class YourMailer < ActionMailer::Base
if self.included_modules.include?(AbstractController::Callbacks)
raise "You've already included AbstractController::Callbacks, remove this line."
else
include AbstractController::Callbacks
end
before_filter :add_inline_attachments!
private
def add_inline_attachments!
attachments.inline["footer.jpg"] = File.read('/path/to/filename.jpg')
end
end
This includes the module that will be used in a future rails version, so the callback hooks available to you will be the same to ensure future compatibility. The code will raise when you try to upgrade to a Rails version that already includes AbstractController::Callbacks, so you will be reminded to remove the conditional logic.
I hacked a little something, it's not ideal, but it works.
If you use
default "SOMEHEADER", Proc.new { set_layout }
And then define set_layout
def set_layout
attachments.inline["logo.png"] = File.read("logopath.png")
attachments.inline["footer.jpg"] = File.read("footerpath.png")
"SOME HEADER VALUE"
end
Then because set_layout gets called to set the header, it also adds the inline attachments. It basically creates a callback for adding attachments.
An actual callback system in ActionMailer would be preferable, but this works too.
Thought I would share since I was looking for this answer on this question earlier today.
in the layout file that your mailer uses u can add the following
<%= image_tag('logo.png') %>
I am assuming that the mail being sent out is html or multipart.
Also you will need to make changes in the environment files. ActionMailer does not get a default base_url. For e.g in environments/development.rb I added the following
config.action_mailer.default_url_options = { :host => "localhost:3000" }
If you want to do it in a dRY manner (and as an attachment) maybe you could do something like
class MyMailer < ActionMailer::Base
default :attachment => File.read(File.join(Rails.root,'public','images','logo.png'))
end
I know you've asked about attaching inline images, but here's a different approach that achieves the same thing with less complexity..
Using inline base64 encoded images in the html layout - no attachments required!
Basically just change the src="..." of your logo image to the format:
<img alt="example logo"
width="32px"
height="32px"
src="data:image/png;base64,iVBORw0KGgoAAA....."/>
I use the online base64 encoder / decoder tool at http://www.base64-image.net for generating the complete <img /> tag
This approach has a few benefits:
- no attachment code, which makes the backend server code cleaner and easier to read
- no increase in email size - inline image attachments are converted to base64 anyway so this approach doesn't make the email payload any larger
- it's widely supported - if the receiving email client is showing html, it's pretty likely it also supports this method