Paperclip + Rails 3 + ActionMailer (receive) + s3 - amazon-s3

I am trying to save an image attachment sent to my rails app to s3 using paperclip however I am hitting these problems:
Its getting to the attachment loop and failing with a
NoMethodError (undefined method `size' for #<Mail::Part:
0x2b62856e8030>):
app/mailers/user_mailer.rb:23:in `receive'
app/mailers/user_mailer.rb:14:in `each'
app/mailers/user_mailer.rb:14:in `receive'
app/controllers/emails_controller.rb:10:in `create'
which is line
:photo_file_size => attachment.size,
commenting out that line, i hit this error when it tries to create:
NoMethodError (undefined method `to_tempfile' for #<Mail::Part:
0x2ac5eb944220>):
Here is my code below.
Appreciate the help..
class UserMailer < ActionMailer::Base
def receive(email)
#user = User.find_or_create_by_email(
#:name => FIXME,
:email => email.from,
:password => 'password',
:password_confirmation => 'password'
)
#item = Item.create(:title => email.subject, :user => #user, :price => 50)
if email.has_attachments?
for attachment in email.attachments
#item.photos.create(
:photo => attachment,
:photo_file_name => attachment.original_filename,
:photo_content_type => attachment.content_type,
:photo_file_size => attachment.size,
:photo_updated_at => Time.now.to_datetime)
#item.photos << attachment
end
end
end
end
Doing an inspect on my attachment object gives me this:
#<Mail::Part:23597877753640, Multipart: false, Headers: <Date: Wed, 25 Aug 2010 16:55:07 -0700>, <Mime-Version: 1.0>, <Content-Type: image/JPG; name="photo.jpeg">, <Content-Transfer-Encoding: base64>, <Content-Disposition: inline; filename=photo.jpeg>, <Content-ID: <4c75ad5b3cbed_52fe15764b0bf938695a#railgun64.30856.mail>>>

I experienced the same issue with rails 3.0.0 + paperclip + ActionMailer. I was able to work around the issue (ugly but working) by:
if mail_message.has_attachments?
for attachment in mail_message.attachments
tempfile=File.open(attachment.original_filename,'w')
tempfile.write_nonblock(attachment.body)
asset = Asset.new(:photo => File.open(tempfile))
asset.save!
tempfile.close
end
end

I did a short blog post on this here at http://minimul.com/full-proof-attachment-size-in-rails-3.html
In short do this
photo_file_size => defined?(attachment.decoded) ? attachment.decoded.length : attachment.size,

Related

Issue updating file attachment(image) using Attachment_fu

I am able to upload image files as attachments using Attachment_fu but when I try to edit/ modify images which were already uploaded, it does not work.
In my Controller I have this:
def update
#sponsor_account = SponsorAccount.find( params[:id] )
if params[:showcase_category_image_file] &&
!params[:showcase_category_image_file].blank?
#sponsor_account.showcase_category_image =
ShowcaseCategoryImage.new(:uploaded_data =>
params[:showcase_category_image_file])
***This logs - Now the file name is: ***
Rails.logger.info("Now the file name is: #
{#sponsor_account.showcase_category_image.filename}")
end
#sponsor_account.update_attributes( params[:sponsor_account] )
if #sponsor_account.save
flash[:notice] = "Showcase category #{#sponsor_account.name} was updated!"
else
flash[:errors] = #sponsor_account.errors
end
redirect_to sponsor_accounts_path
end
ShowcaseCategoryImage is defined as follows:
has_attachment :content_type => :image,
:storage => :file_system,
:max_size => 5.megabytes,
:thumbnails => { :large => [350, 100], :medium => [200, 90], :thumb =>
[35,35], :preview => [60,60] }
validates_as_attachment
The view has a file_field_tag as follows:
<%= file_field_tag :showcase_category_image_file%>
and my SponsorAccount model says:
has_one :showcase_category_image, :as => :owner, :dependent => :destroy
validates_presence_of :showcase_category_image, :on => :create
Almost similar code works perfectly ok in 'create' but here in 'update' action where there is already a value, this code is not working.
I am getting the below error msgs:
Completed 500 Internal Server Error in 1089ms
ActionView::Template::Error (undefined method `public_filename' for nil:NilClass):
Obviously this error is in the index action where it tries to list all records and their attachments. Since this attachment is empty after the update, this error is thrown in the redirect_to part.
I am using REE1.8.7 and rails 3.2.9
Please help!
This issue was solved when I added :multipart => true in the 'View'. I am using rails 3.2.9 and the rails api has this to say about the 'file_field_tag':
file_field_tag(name, options = {}) Link
Creates a file upload field. If you are using file uploads then you will also need to set the multipart option for the form tag:

Rspec, testing for update controller not working?

This is a homework I am working towards to familiar myself with TDD and Rspec. But somehow
I don't understand why the following test failed:
describe 'update' do
fixtures :movies
before :each do
#fake_movie = movies(:star_wars_movie)
end
it 'should retrieve the right movie from Movie model to update' do
Movie.should_receive(:find).with(#fake_movie.id.to_s).and_return(#fake_movie)
put :update, :id => #fake_movie.id, :movie => {:rating => #fake_movie.rating}
end
it 'should prepare the movie object available for update' do
put :update, :id => #fake_movie.id, :movie => {:rating => #fake_movie.rating}
assigns(:movie).should == #fake_movie
end
it 'should pass movie object the new attribute value to updated' do
fake_new_rating = 'PG-15'
#fake_movie.stub(:update_attributes!).with("rating" => fake_new_rating).and_return(:true)
put :update, :id => #fake_movie.id, :movie => {:rating => fake_new_rating}
#fake_movie.should_receive(:update_attributes!).with("rating" => fake_new_rating).and_return(:true)
end
end
The error message I got is:
Failures:
1) MoviesController update should pass movie object the new attribute value to updated
Failure/Error: #fake_movie.should_receive(:update_attributes!).with("rating" => fake_new_rating).and_return(:true)
(#<Movie:0xd39ea38>).update_attributes!({"rating"=>"PG-15"})
expected: 1 time
received: 0 times
# ./spec/controllers/movies_controller_spec.rb:99:in `block (3 levels) in <top (required)>'
Finished in 0.60219 seconds
12 examples, 1 failure
Failed examples:
rspec ./spec/controllers/movies_controller_spec.rb:95 # MoviesController update should pass movie object the new attribute value to updated
Basically it says that my last line of test failed #fake_movie.should_receive(:update_attributes!).with("rating" => fake_new_rating).and_return(:true), and I think it didn't receive the function call 'update_attributes!` at all, but why?
And the controller code:
def update
#movie = Movie.find params[:id]
#movie.update_attributes!(params[:movie])
flash[:notice] = "#{#movie.title} was successfully updated."
redirect_to movie_path(#movie)
end
Thanks in advance
Should be:
it 'should pass movie object the new attribute value to updated' do
fake_new_rating = 'PG-15'
Movie.stub(:find).and_return(#fake_movie)
#fake_movie.should_receive(:update_attributes!).with("rating" => fake_new_rating).and_return(:true)
put :update, :id => #fake_movie.id, :movie => {:rating => fake_new_rating}
end
Otherwise, the line #movie = Movie.find params[:id] would query against the model.

Devise:: Cannot create user through rake db:seed (failure confirmation_instructions)

User model has a function
def self.createadmin(
User.create(:email => "abc#gmail.com", :password => "123456e", :password_confirmation => "123456e", :terms_of_service => '1')
end
In rake db:seed, I have to call User.createadmin
However, this fails
ActionView::Template::Error: ActionView::Template::Error
from /Users/bever/Projects/tr/app/views/devise/mailer/confirmation_instructions.html.erb:3:in `_app_views_devise_mailer_confirmation_instructions_html_erb___1974818942364630283_2154906860'
Then I changed the code in createadmin
begin
User.create(:email => "abc#gmail.com", :password => "123456e", :password_confirmation => "123456e", :terms_of_service => '1')
rescue => e
User.create(:email => "abc#gmail.com", :password => "123456e", :password_confirmation => "123456e", :terms_of_service => '1')
end
It works! Any clue why this is happening?
Have you tried seeding from the db/seeds.rb file instead of the model? When you try to do it on the model, devise is probably trying to send the conformation mail.
You should create your admin user on the seeds.rb file like this
User.create(:email => "abc#gmail.com", :password => "123456e", :password_confirmation => "123456e", :terms_of_service => '1')
Remember that if you are using confirmable module of devise you should add this field to the query.
:confirmed_at => Time.now
Maybe you should add the confirmation tokens and other fields useful to administrate your admin account via your rails app and not on the console.
PD: Probably if you post more of the error shown and maybe the line in the view I can help you more.
Greetings

Sending email with Rails 3 error

I am learning to how send email with Rails 3 with Agile Web Development Book, Task H. However, I keep getting the following error:
ArgumentError in OrdersController#create
wrong number of arguments (1 for 0)
Rails.root: /Applications/XAMPP/xamppfiles/htdocs/rails_projects/TUTORIALS/depot
Application Trace | Framework Trace | Full Trace
app/mailers/notifier.rb:4:in `order_received'
app/controllers/orders_controller.rb:57:in `block in create'
app/controllers/orders_controller.rb:52:in `create'
I have looked at similar discussions on gmail configuration, using setup_mail.rb here and there, but wasn't able to remove the error.
My config/environment.rb file (because i want same for dev/test/production)has my gmail details with xxxx and yyyyy:
Depot::Application.configure do
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:address => "smtp.gmail.com",
:port => 587,
:domain => "gmail.com",
:authentication => "plain",
:user_name => "xxxxxx#gmail.com",
:password => "yyyyyyy",
:enable_starttls_auto => true
}
end
model/notifier/order_received.text.erb has this:
Dear <%= #order.name %>
Thank you for your recent order from The Pragmatic Store.
You ordered the following items:
<%= render #order.line_items %>
We'll send you a separate e-mail when your order ships.
and finally, models/controller/orders_controller has def create method with the line Notifier:
def create
#order = Order.new(params[:order])
#order.add_line_items_from_cart(current_cart)
respond_to do |format|
if #order.save Cart.destroy(session[:cart_id])
session[:cart_id] = nil
Notifier.order_received(#order).deliver
format.html { redirect_to(store_url, :notice => 'Thank you for your order.') }
else
format.html { render :action => "new" }
format.xml { render :xml => #order.errors, :status => :unprocessable_entity }
end
end
end
I feel my email configuration was probably not done correctly, but not sure which one. Thanks!
EDIT: I managed to solve it! Instead of smtp i used sendmail.
As for the number of arguments error, the app/mailers/notifer.rb looks like this:
class Notifier < ActionMailer::Base
default :from => 'Sam Ruby <depot#example.com>'
def order_received(order)
#order = order
mail :to => order.email, :subject => 'Pragmatic Store Order Confirmation'
end
def order_shipped(order)
#order = order
mail :to => order.email, :subject => 'Pragmatic Store Order Shipped'
end
end
Although my emails and everything still works, i'm curious whether anyones know why the smtp doesn't work, and sendmail does.
You've got a space in your order_received definition:
def order_received (order)
That should be this:
def order_received(order)
Is it this line in create?
if #order.save Cart.destroy(session[:cart_id])
If that's what you really have then Ruby will try to pass whatever Cart.destroy returns to #order.save as an argument, the above is equivalent to this:
if(#order.save(Cart.destroy(session[:cart_id])))
However, the save method doesn't take any arguments so you get a "wrong number of arguments (1 for 0) in OrdersController#create" error message. I'd guess that you mean:
if #order.save
Cart.destroy(session[:cart_id])
# etc.

Rails 3 ActionMailer Google Apps: Timeout::Error

I've been trying to fix this for way too many hours. I looked at Railscast, official Rails Guides, lots of blog posts and none of them help.
I'm trying to send email from my Rails 3 app using ActionMailer 2.2.5 via my Google Apps account. I verified the username and password. I can see on the console the message to be sent. I'm getting a Timeout::Error from the deliver call in my controller.
Can someone shed any light on this?
Here's the code:
# config/environments/development.rb
config.action_mailer.raise_delivery_errors = true
config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
:enable_starttls_auto => true,
:tls => true,
:address => 'smtp.gmail.com',
:port => "587",
:authentication => :plain,
:domain => 'test.com',
:user_name => 'user#test.com',
:password => 'mypass'
}
# app/mailers/test_mailer.rb
class PostMailer < ActionMailer::Base
default :from => "no-reply#test.com"
def activate_email( post )
#post = post
mail( :to => post.email,
:subject => "Testing" )
end
end
# app/controllers/test_controller.rb
class TestController < ApplicationController
def create
#post = Post.new( params[:post] )
TestMailer.activate_email( #post ).deliver
end
end
I would try two things. First off make port a number instead of a string:
:port => 587
Also in my code I have the following line before the actionmailer config:
Net::SMTP.enable_tls(OpenSSL::SSL::VERIFY_NONE)
Is there any reason that you are using an old version of actionmailer with rails 3? I would recommend using the version of actionmailer that corresponds to your rails version.
Hope this helps.