Rails 3: Contact form to send messages from User Profiles - ruby-on-rails

I worked through some basic tutorials on Rails 3. The goal is a community-website on abilities and activities. I am using Devise for authentication. The creation of user profiles with avatars worked well (thanks to paperclip).
As a next step, I want to enable registered users to send an e-mail to a user from his (or her) profile page. I found a great tutorial on creating a contact form using Google Apps:
http://matharvard.ca/posts/2011/aug/22/contact-form-in-rails-3/
The mailer class in this tutorial looks like:
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
My question: What is the best way to replace you#youremail.dev with the receivers E-Mail-Address? (from the User-Model)
Thanks in advance!

You can modify the new_message to accept the user (or list of users) to whom you want to send the email. Or an array of email addresses if you want to. Then pass the receiver's email address to the mail method as the :to option.
def new_message(receiver, message)
#message = message
mail(:subject => "[YourWebsite.tld] #{message.subject}",
:to => receiver.email_address) # or something similar
end
Then you can invoke your mailer like this
NotificationEmail.new_message(a_user, a_message).deliver
To read the API see here or here (I prefer APIdock).
Also a more comprehensive guide on ActionMailer is available here. If you are new to Rails, you can find more guides here.

Related

Altering an email address but not the associated name in a Ruby on Rails Mail interceptor

Background: in a Rails 3.2 app, I have an ActionMailer purchase confirmation email that is manipulated in a "stage" environment so that email destined for addresses associated with payment processor sandbox accounts will actually be sent to the email addresses of the people who manage the sandbox accounts. This is currently done inside the mailer class:
# app/mailers/purchase_mailer.rb
class PurchaseMailer < ActionMailer::Base
default :from => "\"#{SiteConfig.name}\" <#{SiteConfig.support_email}>"
def purchase_notification(purchase)
#purchase = purchase
mail :to => "\"#{purchase.customer_name}\" <#{address_filter(purchase.customer_email)}>",
:subject => "[#{SiteConfig.name}] Purchase Confirmation"
end
private
def address_filter(email_address)
# Check for and remove sandbox identifiers
if Rails.env.stage?
email_address.sub(/_\d+_p(er|re)#/, '#')
else
email_address
end
end
end
But, hey, that looks like a great use case for an interceptor, no? So I pulled out the address_filter method above and added this to the Rails app.
# config/initializers/mail.rb
Mail.register_interceptor(StageMailInterceptor) if Rails.env.stage?
# lib/stage_mail_interceptor.rb
class StageMailInterceptor
def self.delivering_email(message)
receivers = []
message.to.each do |to|
receivers << to.sub(/_\d+_p(er|re)#/, '#')
end
message.to = receivers
end
end
At first glance, this appears to work great. In the stage environment, the email is intercepted and the "to" address becomes the email address I want the email to go to. The person managing the sandbox account used to make the purchase receives the email. Perfect... except the name of the sandbox account is gone. What once was "Joe Example" <joe_1338142567_per#example.com> changed to "Joe Example" <joe#example.com> is now changed to joe#example.com
...the name is now gone.
Looking at the Mail message interface, I see that message.to= can be set with a name, but calling message.to gets me an array of just email addresses without names, whether the name was provided or not.
Question: what is the correct way to alter an email address without altering the name associated with the email address in a mail interceptor?
This doesn't seem like it's the "right" way to do this, but grabbing the "To" header of the message, doing the replacement, and setting with message.to= allows me to preserve the names while altering the email address. So my interceptor became:
# lib/stage_mail_interceptor.rb
class StageMailInterceptor
def self.delivering_email(message)
message.to = message.header["To"].to_s.gsub(/_\d+_p(er|re)#/, '#')
end
end

Devise Confirmable - Welcome Message

So I am setting up a welcome message when a user signs up the website - previously I had set it up using gmail (http://stackoverflow.com/questions/5793296/rails-actionmailer-w-devise-google-apps-in-development-mode), but it's going to be using google apps - so if I'm correct another stackoverflow user claimed the set up is similar so that's not a problem. But since I only want a welcome email, I was thinking can I just use the confirmable set up so they get an email, and then in the config set it so that the user doesn't have to confirm till after say 1000 years or something large so basically it's not really a confirmation email? (If there is a better way to do this I'd appreciate such input)
you don't need to twist the Confirmable feature to achieve this, you can do it more elegantly with an ActiveRecord::Observer. Basically when you register/save a user the observer will get notified and from there you can call a mailer. You can see an example below.
app/mailers/user_mailer.rb
class UserMailer < ActionMailer::Base
default from: "something#something.com"
def welcome_mail(email)
mail(:to => email, :subject => "Welcome to Something").deliver
end
end
app/models/user_observer.rb
class UserObserver < ActiveRecord::Observer
# We check if it's a new user
def before_save(user)
#is_new_record = user.new_record?
true
end
def after_save(user)
# If it's not a new user we don't want to send them another welcome email
if #is_new_record then
UserMailer.welcome_mail(user.email)
end
end
end
Finally you need to configure rails to register the observer.
config/application.rb (just a extract)
config.active_record.observers = :user_observer
it's probably awfully late to answer, but i think there's after_create callback to shrink the solution above since you don't need to check if it's a new record!

Ruby on rails super simple signup page

How would I be able to make a signup page with ruby on rails?
Like, I have a beta page and a user enters their email address and then I can add it to the database.
Also, I could send them an email confirming their signup
EDIT: I want something real simple. Like, just plain adding a row in a database simple. I don't need a password box and a username box because that just further complicates things. I'm a beginner so I like to have things simple.
At the terminal:
$ rails new foobar
$ rm public/index.html
$ git init
$ git commit -m "Initial commit"
$ rails g scaffold subscription email:string
Open up your editor:
# app/models/subscription.rb
class Subscription < ActiveRecord::Base
validates :email, :presence => true # optionally validate format of email
end
# app/controllers/subscriptions_controller.rb
class SubscriptionsController < ApplicationController
def new
#subscription = Subscription.new
end
def create
#subscription = Subscription.new params[:subscription]
if #subscription.save
# queue a task to send a confirmation email (see below)
Resque.enqueue(SendConfirmationEmail, #subscription.email)
redirect_to root_path, :notice => 'Thanks for signing up.'
else
render :new
end
end
end
You can delete all of the other methods/actions from your SubscriptionsController, and you can cleanup routes.rb by restricting the actions available on the subscriptions resource with resources :subscriptions, :only => [:new, :create].
This doesn't really cover how to send the email. There are a lot of ways to do it, and the best practice is to not send it in the request/response flow for performance/responsiveness. I've got a line in there queuing a Resque job to do it, but you could easily add DelayedJob or another deferred/async process tool there instead.
This is the kind of thing that is very easy to do in Rails and you shouldn't need any extra gems. Here are the steps you will need to do:
Use a migration to create a model (i.e. database table) called Signup with a string field called "email".
Create an action that can be called with a "GET" request. This action will return the sign up form.
Create the view that serves as the signup form. It should have an HTML form element (<form method="POST">...</form>) that contains a text box (<input type="text" .../>) in it and a submit button (<input type="submit" />). Rails has all sorts of helper methods that will help you make those HTML tags, but you don't have to use them if you don't want to.
Create an action that can be called with a "POST" request that processes the form and adds the info to the database.
The action can be very simple:
def create_signup
Signups.create! :email => params[:email]
end
Does this make sense? Now that I have given you the general guide, you should be able to ask new questions that are more focussed on specific parts that you don't know how to do. You should also search the web because there are probably tutorials available for all of these steps.
This question is too broad to answer with the code itself, but here are some great links to point you in the right direction:
Devise (most common Rails auth & signup plugin):
https://github.com/plataformatec/devise
Devise tutorial:
http://railscasts.com/episodes/209-introducing-devise
Mailer tutorial:
http://railscasts.com/episodes/206-action-mailer-in-rails-3
Other Auth tutorials:
http://railscasts.com/episodes/250-authentication-from-scratch
http://railscasts.com/episodes/270-authentication-in-rails-3-1
I made an app for this. Launchrock offers a good solution, but if you have two types of users then you are hosed. Our future site will have multiple types of users and we wanted to record which type they were. So we made an app and it's on Github for the world to use and change. :D Fork and clone the repo to make it your own. I included social plugin's as well. It's not styled and you'll have to change a few things to fit your needs, but I tried to make note of those in the README.rd.
Launchpage-rails
You could have a look at the 'Devise' gem -
https://github.com/plataformatec/devise
Railscasts episode on 'Devise'
http://railscasts.com/episodes/209-introducing-devise
The excellent 'Rails Tutorial' also takes you through building a sign-up/authentication system from scratch -
http://ruby.railstutorial.org/ruby-on-rails-tutorial-book

Rails 3 mail to users

I want send newsletter to all registered users, but only the last user (in database) receive the mail.
def letter(nletter)
#nletter = nletter
#users=Newsletter.all
#users.each do |users|
mail(:to => users.email, :subject => #nletter.subject)
end
end
Whats wrong?
If the code you showed us is in your Mailer class, it's because the mail method just sets various attributes on a Mail object. When you loop through all your users and call mail for each one, you're just resetting the subject and (more importantly) the recipient on a single Mail object. So when the function finishes and the Mail is sent out, the current recipient is the last user you set it to - the last user in your database.
You can get around this in two different ways. If it's a generic e-mail (everybody gets the same exact message), you can just pass an array of e-mail addresses as :to:
Note: As Josh points out in the comments, you'll pretty much always want to use :bcc instead of :to, so you don't end up broadcasting your entire mailing list.
def letter(nletter)
#nletter = nletter
#users=Newsletter.all
mail(:to => #users.map(&:email), :subject => #nletter.subject)
end
But if each user gets a custom e-mail ("Hi, #{username}!" or somesuch), you'll have to create a new Mail object for each user. You can do this by calling Mailer.deliver_letter(nletter, user) for each user:
# Somewhere outside of your Mailer:
nletter = "...whatever..."
Newsletter.all.each do |user|
Mailer.deliver_letter(nletter, user)
end
# And your mailer function would look like:
def letter(nletter, user)
#nletter = nletter
mail(:to => user.email, :subject => #nletter.subject)
end
Hope this helps!

what is the best way to make a newsletter in rails3

Is there a gem to do this, and if not, what is the best approach. I'm assuming i'd store the emails in a newsletter database, and would want a form that emails everyone at once. thanks!
No gem for this that I know of.
Actually, due to processing issues, the best way would be to use external bulk email service provider via provider's API.
However, building your own newsletter system is no different from building your regular MVC. Only addition are mailers and mailer views.
(1) So you create model that deals with registration data (:name, :email, :etc...) and model that deals with newsletter itself.
(2) Controller that deals with it (CRUD) + (:send). Send takes each recipient, sends data to mailer which creates email and then sends it.
def send
#newsletter = Newsletter.find(:params['id'])
#recipients = Recipient.all
#recipients.each do |recipient|
Newsletter.newsletter_email(recipient, #newsletter).deliver
end
end
(3) Mailer builds an email, makes some changes in each email if you want to do something like that and returns it to controller action send for delivery.
class Newsletter < ActionMailer::Base
default :from => "my_email#example.com", :content_type => "multipart/mixed"
def newsletter_email(recipient, newsletter)
# these are instance variables for newsletter view
#newsletter = newsletter
#recipient = recipient
mail(:to => recipient.email, :subject => newsletter.subject)
end
end
(4) Ofc, you need mailer views which are just like regular views. Well in multipart there is:
newsletter_email.html.erb (or haml)
newsletter_email.txt.erb
When you want to send both html and text only emails. Instance variables are defined in mailer ofc.
And... that is it. Well you could use delayed job to send them since sending more than several hundred emails can take a while. Several ms times n can be a lot of time.
Have fun.
Please check the maktoub gem there is a blog post over it.
No gem that I know of too and building on #Krule's answer, here's a screencast of setting up mailers in Rails.
How to create, preview and send email from your rails app
I was looking for something similar when I found this. I think with a bit of customization, it can easily be used to create newsletter emails too.
Save money! Spend somewhere else.

Resources