Sending email with Rails 3 error - ruby-on-rails-3

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.

Related

Unpermitted parameters although controller has them whitelisted when creating user

In migrating a rails application from 3.2 to 4.1, I am hitting some issues with user creation. As there is a need to distinguish the current_user form a local_user. The controller create action
def create
#local_user = User.new(user_params)
respond_to do |format|
if #local_user.save
if params[:user][:avatar].present?
format.html { render :crop }
else
format.html { redirect_to(admin_user_path(#local_user), :notice => 'User was successfully created.') }
end
else
format.html { render :action => "new" }
end
Generates a console error: Unpermitted parameters: name, surname, pen_name[...], yet the User controller defines them:
def user_params
params.require(:user).permit(:name, :surname, :pen_name, [...])
end
The form call is:
<%= form_for(resource, :as => resource_name, :url => registration_path(resource_name), :method => :post, :validate => true) do |f| %>
This is necessarily a devise issue for a user can be created with the scaffolding for the User class with the exact same variables. There is some logic that devise is going through which does not pull all the controller logic ; what am I missing?
Needs a devise specific initializer, as per this demo, where all variables can be entered as an array.

Rails 3.2.13 Contact Form Only Sending Subject

So I followed this wonderfully flawed tutorial:
http://matharvard.ca/posts/2011/aug/22/contact-form-in-rails-3/
...on making contact forms. It works great. The only problem is that it ONLY sends the subject. I think maybe the problem is in the notifications mailer:
notifications_mailer.rb
class NotificationsMailer < ActionMailer::Base
default :from => "noreply#youdomain.dev"
default :to => "you#youremail.dev"
def new_message(message)
#message = message
mail(:subject => "[YourWebsite.tld] #{message.subject}")
end
end
I would, of course, like it to send ALL the info the user submitted... (name, email address, subject, and body.
Also I was wondering how I could do a simple version of this with just the body where the subject is set to a default. (I want to have a small comment box that would send an email to me with the comment.) Would I have to make a whole new controller and model for that, or could this handle both?
UPDATE
Notifications Mailer View / new.html.erb
Name: <%= #message.name %>
Email: <%= #message.email %>
Subject: <%= #message.subject %>
Body: <%= #message.body %>
contact controller
class ContactController < ApplicationController
def new
#message = Message.new
end
def create
#message = Message.new(params[:message])
if #message.valid?
NotificationsMailer.new_message(#message).deliver
flash[:success] = "Message was successfully sent."
redirect_to(root_path)
else
flash[:error] = "Please fill all fields."
render :new
end
end
end
message.rb
class Message
include ActiveModel::Validations
include ActiveModel::Conversion
extend ActiveModel::Naming
attr_accessor :name, :email, :subject, :body
validates :name, :email, :subject, :body, :presence => true
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
def initialize(attributes = {})
attributes.each do |name, value|
send("#{name}=", value)
end
end
def persisted?
false
end
end
Basically it works... but it only sends the subject. I also got it to send a complete mail once with everything BUT the subject... but I can't remember how I did it.
Should I just smash this computer into a million pieces and go on a rampage?
Sigh...
UPDATE AGAIN
This is what the emails say with the above settings:
Subject: [liquid.radio] Whatever The Subject is. Body: Completely
blank
This is what they said after whatever the hell I did two weeks ago.
Subject: Message from liquid.radio
Body:
A contact enquiry was made by Richard Pryor at 2013-06-17 23:36.
Reply-To: richard#pryor.com
Subject: Scared for no reason Body: Oh
no... Oh God no! What is that?!
All I did was mess around with the notifications controller. Although I don't remember... for the life of me... what I did. But, as you can see... it send the complete message as it should... but a completely different subject.
Really kinda need help here.
First, this project places production settings in config/application.rb. Move the GMail ActionMailer settings to config/environments/production.rb. Add the letter_opener gem to your Gemfile's development group.
# Gemfile
group :development do
gem 'letter_opener'
end
Add the letter_opener settings to your development environment.
# config/environments/development.rb
config.action_mailer.default_url_options = { host: 'localhost', port: 3000 }
config.action_mailer.delivery_method = :letter_opener
config.action_mailer.perform_deliveries = true
config.action_mailer.raise_delivery_errors = true
Add active_attr gem
# Gemfile
gem 'active_attr'
Make sure you run bundle install
Replace your messages model with robust ActiveAttr implementation.
# app/models/message.rb
class Message
include ActiveAttr::Model
attribute :name
attribute :email
attribute :subject
attribute :body
validates_presence_of :name, :email, :subject, :body
validates :email, :format => { :with => %r{.+#.+\..+} }, :allow_blank => true
end
Improve the routes.
# config/routes.rb
get 'contact' => 'contact#new', :as => 'contact'
post 'contact' => 'contact#create', :as => 'contact'
Make sure your email template is correct
# app/views/notifications_mailer/new_message.text.erb
Name: <%= #message.name %>
Email: <%= #message.email %>
Subject: <%= #message.subject %>
Body: <%= #message.body %>
Update: December 12, 2013
I've created a Rails 3.2 project on GitHub to assist anyone searching for a modern solution to creating contact forms in Rails. Merry Christmas!
https://github.com/scarver2/contact_form_app
Ultimately here's what I did... I realize this isn't a true solution. But I still don't have a different one.
notifications_mailer.rb
class NotificationsMailer < ActionMailer::Base
default :from => "example#gmail.com"
default :to => "example#gmail.com"
def new_message(message)
#message = message
mail(:subject => "[liquid.radio] #{message.subject}", :body => "
From: #{message.name}
Reply to: #{message.email}
Subject: #{message.subject}
Message: #{message.body}")
end
end
Not how the mailer is supposed to work at all... but at least it sends a complete message.
If you're in a time crunch... like I was... this will get you there. I will accept a real answer (probably scarver2's) once I stop getting blank emails any other way.

render partial from controller with :layout => !request.xhr? returns missing template?

I cloned and tweak this rails app and I am experiencing some trouble with rendering a partial when on ajax request, in the logs I see that the guilty line is in the registrations_controller.rb (Devise)
class RegistrationsController < Devise::RegistrationsController
def create
build_resource
if resource.save
if resource.active_for_authentication?
sign_in(resource_name, resource)
(render(:partial => 'thankyou', :layout => false) && return) if request.xhr?
respond_with resource, :location => after_sign_up_path_for(resource)
else
resource.update_attribute(:encrypted_password, nil) # make sure there is no password
expire_session_data_after_sign_in!
(render(:partial => 'thankyou', :layout => false) && return) if request.xhr?
respond_with resource, :location => after_inactive_sign_up_path_for(resource)
end
else
clean_up_passwords resource
render :partial => 'email_capture', :action => :new, :layout => !request.xhr?**
end
end
protected
def after_inactive_sign_up_path_for(resource)
'/thankyou.html'
end
def after_sign_up_path_for(resource)
redirect_to root_path
end
end
The error message returned is this:
ActionView::MissingTemplate - Missing partial
with {:locale=>[:en], :formats=>[:html], :handlers=>[:erb, :builder,
:coffee, :haml]}. Searched in: *
"/Users/Davide/Documents/Jobsite/rails-prelaunch-signup-1click/app/views"
* "/Users/Davide/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/devise_invitable-1.1.8/app/views"
* "/Users/Davide/.rbenv/versions/1.9.3-p194/lib/ruby/gems/1.9.1/gems/devise-2.2.4/app/views"
Interestingly if I remove the :layout => !=request.xhr? parameter the partial gets found but the page refreshes and the loses all the stylesheets and other assets.
Any idea where should I start looking?
Thanks!
I have also cloned and modified that project, and ran into nearly the same issue. For me, the problem would appear after the second failure of saving a bad email address--but the result was identical.
By using context and information from the following question/answer:
form returned from AJAX request is not recognized as 'remote' when submitted
I was able to make a change that resolved my issue. In _email_capture.html.erb, add :remote => true, to the simple_form_for line. In my case, the whole revised line is:
<%= simple_form_for resource, :as => resource_name, :remote => true, :url => registration_path(resource_name) , :html => {:class => 'form-inline'} do |f| %>
Hope this helps you, too!

Rails 3 Unknown Action even though its define in my routes

I have an app that I am working on that directs users to a "bundle" page when purchasing one product so that they have the opportunity to add another product to "bundle" their purchase for a discount.
Here is my routes:
resources :orders, :path_names => { :new => 'checkout' }
match "/orders/bundle" => "orders#bundle", :as => 'bundle_order'
match "/orders/add_product" => "orders#add_product", :as => 'add_product'
Here is my Controller#Action
def bundle
op_client = Client.find_by_name(opposite_client(current_client))
#product = Product.find_by_client_id_and_type_and_status(op_client.id, "subscription", "Active")
respond_with #product
end
For some reason when I redirect_to this method, I receive this error:
Unknown action
The action 'show' could not be found for OrdersController
I don't have a show method in my OrdersController cause I don't need it. Why would I be seeing this issue?
This error could be caused by two diferent things.
first:
are you using something like: <%= link_to #order_object %> ?? if you are, this is the problem.
second:
on routes.rb change this line:
resources :orders, :path_names => { :new => 'checkout' }
to
resources :orders, :path_names => { :new => 'checkout' }, :except => [:show]
this should work. if not, please give more details about the code you are using to do the redirect_to

respond_with location ignored on GET request

At each step in my checkout process, an order is updated via a PUT request. However, one of the states has a form that submits to a third party which redirects back to my site, calling the update method with GET (no control over this).
Why does my respond_with code appear to be totally ignored and I get a Missing Template checkout/update error? It should be hitting #edit.
CheckoutController.rb
before_filter :load_order
def update
if #order.update_attributes(params[:order])
#order.next
end
respond_with(#order, :location => checkout_state_url(#order.state))
end
routes.rb
match '/checkout/update/:state' => 'checkout#update', :as => :update_checkout
match '/checkout/:state' => 'checkout#edit', :as => :checkout_state
match '/checkout' => 'checkout#edit', :state => 'client_details', :as => :checkout
It looks like respond_with does different things depending upon the HTTP verb and whether the resource has errors. See here and here.
The following code worked for me:
def update
if #order.update_attributes(params[:order]) && #order.next
respond_with(#order) { |format| format.html { redirect_to checkout_state_url(#order.state) } }
else
respond_with(#order) { |format| format.html { render :edit } }
end
end