Attempting to email a Paperclip attachment in Rails 3.
Invoice model:
class Invoice < ActiveRecord::Base
has_attached_file :attachment,
:url => "http://server/app/attachments/:id/:style/:basename.:extension",
:path => ":rails_root/public/attachments/:id/:style/:basename.:extension"
validates_attachment_presence :attachment
validates_attachment_size :attachment, :less_than => 5.megabytes
end
account_mailer:
def email_approver(invoice)
#subject = 'Invoice Approval Request'
#body["invoice"] = invoice
#attachment "application/octet-stream" do |a|
#a.body = File.read(invoice.attachment.to_file.path)
#a.filename = invoice.attachment_file_name
#end
#recipients = [invoice.approver_email, invoice.alternate_approver_email].compact
#from = "ADMIN"
#sent_on = Time.now
#headers = {}
end
error:
NoMethodError (undefined method `filename=' for #<Mail::Part:0x00000002566dd0>):
Any ideas?
Thanks!
Did you tries something like this
attachments[invoice.attachment_file_name] = File.read(invoice.attachment.to_file.path)
?
It's an old question, but here's my working solution:
attachments[mymodel.attachment.filename] = File.read(mymodel.attachment.path)
Related
I'm trying to upload multiple images with paperclip through 1 form, but I'm getting a Unpermitted parameters error.
This is my code:
Model:
class Recentjacket < ActiveRecord::Base
has_attached_file :jacketimage, :styles => { :medium => "300x300>", :thumb => "100x100>"}, :default_url => "/images/:style/missing.png"
end
Controller:
def recent
#recentjacket = Recentjacket.all
end
def update
params['recentjacket'].keys.each do |id|
#jacket = Recentjacket.find(id)
#jacket.update_attributes(recentjacket_params)
end
redirect_to '/recent'
end
private
def recentjacket_params
params.require(:recentjacket).permit(:jacketimage)
end
Html.slim
= form_for recent_path, html: { multipart: true } do |k|
- #recentjacket.each do |j|
= fields_for "recentjacket[]", j do |jacketfields|
= jacketfields.file_field :jacketimage
= k.submit "Update"
So basically there are 12 recentjackets in the database and when something is changed, it should overwrite the image.
Does anyone know how to fix this?
I fixed the problem:
def update
if params.has_key?(:jacket)
Recentjacket.update(params[:jacket].keys, params[:jacket].values)
redirect_to '/recent'
else
redirect_to '/recent/edit',
notice: 'No Files were selected to upload!'
end
end
I'm upgrading rails 2.3.2 app ot rails 3.
Have unknown error with sending email message in MailerFormError.
MailerFormError is my model: class MailerFormError < ActionMailer::Base
At 1st I have error with 'deliver_send' method (undefined method `deliver_sent' for MailerFormError:Class),
I change it to 'send'. Now I have this:
NoMethodError in LeadsController#create
undefined method `part' for #
My code in controller:
#msg = {}
#msg["errors"] = #lead.errors
#msg["params"] = params
#MailerFormError.deliver_sent(#msg)
MailerFormError.sent(#msg)
This is my class with sending method:
def sent(msg, sent_at = Time.now)
#subject = ("Ошибка при заполнении формы").force_encoding('iso-8859-1').encode('utf-8')
#recipients = 'mymail#gmail.com'
#from = 'mymail#gmail.com'
#sent_on = sent_at
#headers = {}
part( :content_type => "multipart/alternative" ) do |p|
p.part :content_type => "text/plain",
:body => render_message("sent.plain.erb", :msg=>msg )
end
end
1) for Rails 3, to send your notification in your controller , you have to write this :
MailerFormError.sent(#msg).deliver
2) And you have to rewrite your 'sent' method in the Rails 3 way :
def sent(msg, sent_at = Time.now)
...
mail(:to => '...', :from => '...', :subject => '...') do |format|
format.html
format.text
end
...
end
You can also create the text version and html in your view directory app/views/mail_form_error : sent.text.erb and sent.html.erb
I'm attempting to test the creation of an Reservation model that involves processing a payment with ActiveMerchant upon creation.
The initial setup for payment processing involved following the ActiveMerchant Railscasts. Payments are working fine within the app. (http://railscasts.com/episodes/145-integrating-active-merchant)
I've tried creating the credit_card object within the Reservation factory and within it's own ":valid_credit_card" factory...
The basic test is just attempting to verify the Reservation can be created.
Test results:
1) Reservation should have a valid factory
Failure/Error: #current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `credit_card=' for #<Reservation:0xb5f6173c>
# ./spec/models/reservation_spec.rb:11
The Reservation belongs_to a user and has_many rooms through reservation_sets
Factory.define :reservation do |f|
f.association :user
f.rooms { |a| [a.association(:room)] }
f.arrival Time.now + 2.weeks
f.nights 2
f.phone "555-123-1234"
f.credit_card :valid_credit_card
end
Factory.define :valid_credit_card, :class => ActiveMerchant::Billing::CreditCard do |f|
expiration_date = Time.zone.now + 1.year
f.type "visa"
f.number "4111111111111111"
f.verification_value "333"
f.month expiration_date.strftime("%m")
f.year expiration_date.strftime("%y")
f.first_name "Bob"
f.last_name "Smith"
end
And the spec/models/reservation_spec.rb. Using #credit_card Factory.build causes errors about "saving" the credit_card.
If I remove the line f.credit_card :valid_credit_card I get the NoMethodError for :month
even though :month is listed in attr_accessor. The creation of a reservation within the app does work.
1) Reservation should have a valid factory
Failure/Error: #current_reservation = Factory.create(:reservation)
NoMethodError:
undefined method `month' for nil:NilClass
describe Reservation do
before :each do
#smith = Factory.create(:user)
#room = Factory.create(:room)
##credit_card = Factory.build(:valid_credit_card)
end
it "should have a valid factory" do
#current_reservation = Factory.create(:reservation)
#current_reservation.should be_valid
end
end
What am I overlooking / doing incorrectly...?
Reservation model excerpts
class Reservation < ActiveRecord::Base
# relationships
belongs_to :user
has_many :reservation_sets,
:dependent => :destroy
has_many :rooms,
:through => :reservation_sets
has_many :transactions,
:class_name => 'ReservationTransaction',
:dependent => :destroy
attr_accessor :card_number, :card_verification, :card_expires_on, :card_type, :ip_address, :rtype, :month, :year
# other standard validations
validate :validate_card, :on => :create
# other reservation methods...
# gets paid upon reservation creation
def pay_deposit
# Generate active merchant object
ReservationTransaction.gateway =
ActiveMerchant::Billing::AuthorizeNetGateway.new({
:login => rooms[0].user.gateway_login,
:password => rooms[0].user.gateway_password
})
response = ReservationTransaction.gateway.purchase(deposit_price_in_cents, credit_card, purchase_options)
t = transactions.create!(:action => "purchase", :amount => deposit_price_in_cents, :response => response)
if response.success?
update_attribute(:reserved_at, Time.now)
# update state
payment_captured!
else
transaction_declined!
errors.add :base, response.message
end
t.card_number = credit_card.display_number
t.save!
response.success?
end
def validate_card
unless credit_card.valid?
credit_card.errors.full_messages.each do |message|
errors.add :base, message #_to_base message
end
end
end
def credit_card
#credit_card ||= ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
end
And the create action from the Reservation Controller
def create
#reservation = Reservation.new(params[:reservation])
#reservation.arrival = session[:arrival]
#reservation.nights = session[:nights]
#reservation.number_kids = session[:number_kids]
#reservation.number_adults = session[:number_adults]
session[:creating_reservation] = 1
#reservation.user_id = #reservation.rooms[0].user_id
session[:owner] = #reservation.user_id
#rooms = Room.all
#reservation.ip_address = request.remote_ip
# get room owner...
#owner = User.find(#reservation.user_id)
respond_to do |format|
if #reservation.save
if #reservation.pay_deposit
#set cc...
#reservation.transactions[0].card_number = #reservation.send(:credit_card).display_number
ReservationMailer.reservation_created(#reservation).deliver
ReservationMailer.reservation_notice(#reservation).deliver
session[:arrival] = nil
session[:reservation_id] = #reservation.id
if #owner
thanks_path = "#{#owner.permalink}/reservations/#{#reservation.id}"
else
thanks_path = #reservation
end
format.html { redirect_to #reservation, :notice => 'Reservation was successfully created.' }
format.json { render :json => #reservation, :status => :created, :location => #reservation }
# also trigger email sending or wherever that is
# receipt email and order notification
#
else
# set flash or show message problem w/ transaction
format.html { render :action => "new" }
end
else
format.html { render :action => "new" }
format.json { render :json => #reservation.errors, :status => :unprocessable_entity }
end
end
end
It looks like you are trying to assign credit_card a value, but you don't really have a class accessor. So where you are trying to call f.credit_card :valid_credit_card isn't going to work.
I would remove the f.credit_card :valid_credit_card from your factory and look into using rspec stubs, then you could do something like the following in your rspec test:
mock_cc = ActiveMerchant::Billing::CreditCard.new(
:type => card_type,
:number => card_number,
:verification_value => card_verification,
:month => card_expires_on.month,
:year => card_expires_on.year,
:first_name => first_name,
:last_name => last_name
)
Reservation.stub(:credit_card).and_return(mock_cc)
This would make it so when your model called credit_card it would return a mocked object.
I'm just following Ruby on Rails 3 Tutorials (Mhartl) chapter-7 at the stage of 7.3.2 name and Gravatar.
Here I am facing a problem when I open on my browser it's says:
ActiveRecord::RecordNotFound in UsersController#show
Couldn't find User with id=1
Rails.root: C:/RubyOnRails/MyWorkPlace/sample_app_1
Application Trace | Framework Trace | Full Trace
app/controllers/users_controller.rb:5:in `show'
Request
Parameters:
{"id"=>"1"}
Show session dump
Show env dump
Response
Headers:
None
Also I pasted below User_controller.rb and user.rb
user.rb:
require 'digest'
class User < ActiveRecord::Base
attr_accessor :pasword
attr_accessible :login,
:username,
:email,
:password,
:password_confirmation,
:remember_me
email_regex = /\A[\w+\-.]+#[a-z\-.]+\.[a-z]+\z/i
validates :name, :presence => true,
:length => { :maximum => 50 }
validates :email, :presence => true,
:format => { :with => email_regex },
:uniqueness => { :case_sensitive => false }
validates :pasword, :presence => true,
:confirmation => true,
:length => { :within => 6..40 }
def self.authenticate(email, submitted_password)
user = find_by_email(email)
return nil if user.nil?
return user if user.has_password?(submitted_password)
end
before_save :encrypt_password
def has_password?(submitted_password)
encrypted_password == encrypt(submitted_password)
end
private
def encrypt_password
self.salt = make_salt if new_record?
self.encrypted_password = encrypt(password)
end
def encrypt(string)
secure_hash("#{salt}--#{string}")
end
def make_salt
secure_hash("#{Time.now.utc}--#{password}")
end
def secure_hash(string)
Digest::SHA2.hexdigest(string)
end
end
users_controller.rb:
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#title = #user.name
end
def new
#title = "Sign up"
end
end
Are you sure you created any user with id=1 ?
To check, go to rails console and get the user with id 1. If there is no user, then create one.
At firest, I see you have attr_accessor :pasword
I think it should be :password
Ontopic:
There are some actions missing in the restful controller, so it wont be possible to create a user.
See http://guides.rubyonrails.org/getting_started.html#rest for more details on RESTful controllers.
class UsersController < ApplicationController
def show
#user = User.find(params[:id])
#title = #user.name
end
def new
#user = User.new #this creates a empty user object to be filled with signup data
#title = "Sign up"
end
def create
#user = User.new(params[:user]) #this creates a new user object with the data you entered before.
if #user.save #if the data is valid, save it
redirect_to user_path(#user) #and go to the #user show action
else
render :action => :new #edit the invalid user data
end
end
def edit
#user = User.find(params[:id])
end
def update
#user = User.find(params[:id])
if #user.update_attributes(params[:user])
redirect_to user_url(#user)
else
render edit_user_url(#user)
end
end
def index
#users = User.all
end
def destroy
#user = User.find(params[:id]
#user.destroy
redirect_to :action => :index
end
end
edit: complete restful actions
I had the same problema. In my case, my 'redirect_to' on my detroy action was missin a 's' in 'posts_path'. It was post_path Noob, but worth i had checked up.
The reason you could not find the "user/1" is when you Added microposts to the sample data(db/seeds.rb) by typing
users = User.order(:created_at).take(6)
50.times do
content = Faker::Lorem.sentence(5)
users.each { |user| user.microposts.create!(content: content) }
end
You forgot the "END" of the previous code, so the full picture of db/seeds.rb is
User.create!(name: "Example User",
email: "example#railstutorial.org",
password: "foobar",
password_confirmation: "foobar",
admin: true,
activated: true,
activated_at: Time.zone.now)
99.times do |n|
name = Faker::Name.name
email = "example-#{n+1}#railstutorial.org"
password = "password"
User.create!(name: name,
email: email,
password: password,
password_confirmation: password,
activated: true,
activated_at: Time.zone.now)
end
users = User.order(:created_at).take(6)
50.times do
content = Faker::Lorem.sentence(5)
users.each { |user| user.microposts.create!(content: content) }
end
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,