I have a Rails 3.1 app that makes use of the paperclip gem (v 3.4.0). In a nutshell. I have a story model and a post model. A story can have many posts.
#story.rb
class Story < ActiveRecord::Base
attr_accessible :title, :user_id, :username, :posts_attributes
belongs_to :user
has_many :posts, :dependent => :destroy,
:order => "created_at DESC"
accepts_nested_attributes_for :posts, :reject_if => lambda { |t| t['contents'].nil? }
end
#post.rb
class Post < ActiveRecord::Base
attr_accessible :contents, :photo, :dimensions
belongs_to :story, :touch => true
belongs_to :user, :touch => true
has_attached_file :photo,
:styles => {
:medium => { :geometry => "400x400>" },
:thumb => { :geometry => "100x100>" },
},
:processors => [:thumbnail],
:storage => :s3,
:s3_credentials => "#{Rails.root.to_s}/config/s3.yml",
:path => "/:style/:id/:filename"
before_save :extract_dimensions
serialize :dimensions
validates :contents, :presence => true,
:length => { :maximum => 399,
:minimum => 5 }
validates :user_id, :presence => true
validates_attachment_content_type :photo,
:content_type => ['image/jpeg', 'image/png', 'image/gif', 'image/jpg'],
:message => "Sorry, we don't support that type of image format"
end
As you can see, posts may have a photo attachment. I use paperclip to manage these attachments.
I generate the form that POSTs these posts dynamically on the client with javascript/jquery. My problem is this . . . If the post does NOT include a photo attachment everything works perfectly. IF, HOWEVER, A POST HAS A PHOTO ATTACHMENT, I receive the following error message and the post doesn't POST:
WARNING: Can't verify CSRF token authenticity
User Load (0.5ms) SELECT "users".* FROM "users" WHERE "users"."id" = 61 LIMIT 1
(0.3ms) BEGIN
(0.2ms) COMMIT
Completed 401 Unauthorized in 238ms
As a result, my session data is destroyed, and I can't even see the request headers with Firebug. The put request simply does not appear in firebug.
Now, not surprisingly, I can get around this problem with the following in the PostController:
skip_before_filter :verify_authenticity_token, :only => [:create]
But I don't want to give up this security. I have also tried adding the CSRF header to my form via js/jquery:
jQuery.ajaxSetup({
beforeSend: function(xhr) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-
token"]').attr('content'));
}
});
But that doesn't solve the problem, and as I said above, I can't even see the request header data to see the header.
Can anyone come-up with a reason why paperclip triggers the problem?
I know that it's been a while since I first posted the above question, but people are still finding it in their searches, so I thought I'd update things with an answer.
The problem I discussed above had nothing to do with Paperclip. The form is being submitted without a csrf token because I am using remotipart.js to handle the submission of forms that have file attachments. Remotipart enables an ajax-like submission of a form by copying the form data into an i-frame, which then makes a normal (i.e., non-ajax) submission while your site stays active. See this article for a more detailed description of ajax file uploads via i-frame.
In previous versions of remotipart the csrf token was not copied over to the form being submitted by the i-frame. The good people supporting remotipart have now fixed this shortcoming. You can find the fix here
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With