acts_as_emailable

Posted by matt on June 05, 2007

Quite often when building a site, I find that it would be nice if users could email each other within the site. In my previous post I explained how to set up the models and relationships for this. Today I’ve gone one step further and packaged them up into a plugin: acts_as_emailable. Here is how to use it:

Setup
=====
First up you need to install the plugin. This can be done like so:

script/plugin install svn://matt-beedle.com:3396/acts_as_emailable

Then generate the model and migration for the emails table.

script/generate acts_as_emailable_model Email
rake db:migrate

Now you are ready to go. Just add the following line of code to your User model:

class User < ActiveRecord::Base
  acts_as_emailable
  #
  # The rest of you code
end

Usage
=====
After the plugin is installed the following methods become available to your User class.

These methods are the associations. They return what you would expect:

user.users_whom_i_have_emailed
user.users_who_have_emailed_me

At the moment there is only bare-bones functionality, but if any interest is shown or I feel the need, I will build in some more useful methods and make it more complete…

UPDATE
I am really pleased with all the interest and feedback I have received, especially from egze who basically did all the work for these changes. I have now added in three new functions with two aliases as I couldn’t decide on the which I preferred:
These two are really the same, they both return unread mail, although you need to make sure you update the ‘read_at’ field in the emails table when an email is read by the receiver.

user.unread_mail
or
user.new_mail

These two return all read emails, although I’m not sure if there will be much use for it.

user.read_mail
or
user.old_mail

Finally this returns all users who have emailed or been emailed by the user.

user.all_mail

I have a couple more ideas for new functions but suggestions are welcome. I was also intending to write some example code but haven’t had the chance. I’ll try to do that this week.

UPDATE: EXAMPLE CODE

In a REST based application the code may look something like this to send an email. The current_user that is referred to in the create method of the emails controller can be whatever way you get the current user. In my case I usually use Rick Olson’s Restful Authentication plugin which does this for me.
app/views/emails/new.rhtml

<% form_for :email, @email, :url => emails_path(:user_id => params[:user_id]) do |f| %>
<%= render :partial => ‘form’, :locals => {:f => f} %>
<%= submit_tag 'Send' %>
<% end %>

app/views/emails/_form.rhtml

<fieldset>
    <legend>Email</legend>
    <%= f.hidden_field :receiver_id %>
    <div>
        <label for="subject">Subject</label><br/>
        <%= f.text_field :subject %>
    </div>
    <div>
        <label for="body">Message</label><br/>
        <%= f.text_area :body %>
    </div>
</fieldset>

emails_controller.rb

def index
  @emails = User.find(params[:user_id]).all_mail
end

def new
  @email = Email.new
end

def create
  current_user.send_mail(User.find(params[:user_id]), Email.new(params[:email]))
  respond_to do |format|
    format.html do
      flash[:notice] = 'Email Sent'
      redirect_to emails_path
      false;
    end
  end
rescue ActiveRecord::RecordInvalid
  render :action => 'new'
end
Trackbacks

Use this link to trackback from your own site.

Comments

Leave a response

  1. […] UPDATE: I have now packaged all of this code up into a plugin. For install instructions read this post. […]

  2. cies breijs Tue, 05 Jun 2007 23:14:00 BST

    great work man… contributions like this make RoR shine!

    the zen-like simplicity.

    beautiful.

  3. bkaer101 Fri, 08 Jun 2007 10:31:16 BST

    Hi, Sorry for the noob question, but how does one email another user on the forum? am i to assume that i can have an email form on my site with email address hidden, and users can use this system to send email to each other?

    thanks,

  4. matt Fri, 08 Jun 2007 11:47:10 BST

    Thats right. You can create a form without needing the email address at all. The users are keyed to each other through their ids, and the email subject and body are added to the relationship via the Email model. If you wanted to you could create a Mailer which sends a notification to the users actual email address telling they have new mail on the site. I will try to write some sample code to do that this weekend. If you do not need to user a Mailer then really you do not need to store the users email address at all, unless you are using it for login… ;)

  5. helmut ebritsch Fri, 08 Jun 2007 15:12:25 BST

    it would be great to have some samples… :) - because i’m thinking of writing my own internal mailer - or may be use this little nice thing :) but i install it now anyway…
    thank you for your submisson….

  6. Egze Sat, 09 Jun 2007 13:15:43 BST

    Hi,

    Very nice plugin. I renamed it to acts_as_messageable after I downloaded it. It is messages that users send one another on my site, not emails. It doesn’t matter much, I just don’t like the emailable name :)

    What I find missing is the possibility to get messages that I’ve read or new messages.
    I added a field “read_at” to the message model, now I’ll add some stuff like:

    has_many :new_messages,
    :foreign_key => ‘receiver_id’,
    :class_name => ‘Message’,
    :conditions => ‘read_at IS NULL’

    What is also missing is delete mechanism. If I send a message to my friend, it should be in my sent folder, and in his inbox. But it is the same entry in the database, they are not two different messages. If I want to delete the message from my sent folder, the message should still be in the inbox folder of my friend.

    What are your thoughts on this Matthew?

  7. baker Sun, 10 Jun 2007 15:26:18 BST

    Hi, me again and back with more noob questions. but first id like to say thanks for sharing!

    my questions is, how or what action does your plugin need to know that an email has been sent to a user? if i choose to not send email to the user with actionmailer and do a messaging system like Egze, how will a user know that a message has been sent?

    for example if i had something like this

    #some form
    form (:action => ’send_user_a_priv_message, :id => ‘current_user.id’)
    text_area :message
    text_field :user “that is recieving the message”
    end

    #action
    def send_user_a_priv_message
    …find user, add message to users message box, etc…
    end

    do i need to do anything so act_as_emalible knows that a message has been sent to the user?

    thanks!

  8. Neebone Mon, 18 Jun 2007 21:39:42 BST

    For the delete issue, you’ll want to add two delete flags. One for the sender, one for the receiver. When, say, the sender goes to delete the message, their flag is set. This effectively makes the message invisible (you’ll have to check for this). Then when the receiver deletes, their flag gets set. You could also check, each time, if both flags are set; if so, purge the message.

    If you want to have multiple recipients for a message, you’ll have to put the sender/receiver in a separate table all with flags. You just check all the recipients/senders who reference the message itself (which is in its own table) and again set flags/check for all flags checked.

    If you want to test for mail read, you could write a custom accessor which sets this once the recipient has read the message, that way you dont need to set it manually.

  9. Scott Tue, 03 Jul 2007 04:56:23 BST

    I am somewhat new to ROR (like most I think) and I must admit I am completely stumped as to how to display messages using the plugin. I am aiming to get an “inbox” type display of unread messages, so I used a block:

    @current_user.unread_mail.each do |m| to set it up.

    But from there I have tried everything to get the syntax right to show the specifics on each message… to no avail. I used debug to confirm that the data is present on my page, but I am not sure of the syntax to output the message subject, sender_id, etc without circumventing the plugin and setting up the objects in the controller separately.

    Can anyone help?

  10. matt Tue, 03 Jul 2007 09:05:43 BST

    Scot,

    I have made a change to the select statements on the unread_mail and read_mail associations. This should work now if you update:

    @current_user.unread_mail.each do |m|
    m.subject
    end

  11. Scott Tue, 03 Jul 2007 15:14:22 BST

    Hey Matt,

    Thanks for your help, it works great now!

  12. Richard Tue, 17 Jul 2007 17:35:03 BST

    Any ideas when the the link to svn://matt-beedle.com:3396/acts_as_emailable will be back up and running?It looks like a good plugin and I would like to try it out.

  13. matt Wed, 18 Jul 2007 07:41:15 BST

    As far as I am aware svn://matt-beedle.com:3396/acts_as_emailable is running fine. I just checked out a copy to make sure. What exactly is the error your receiving Richard?

  14. […] was looking for Rails plug-in to provide simple messaging between users on a website. I came across Acts_As_Emailable by Matt Beedle. It was a good start but only gave me a model and some methods but I would still […]

  15. Richard Wed, 18 Jul 2007 22:35:11 BST

    Hi Matt,

    When I click the link I get “Page cannot be displayed”. Usually it should be a repository list or something. I first tried to install the plugin and noticed that I did not get any messages at all and there was no new acts_as_emailable folder in my plugin folder. I tried this at two different internet connections so I have no idea why I cannot see anything at that page.

  16. Richard Wed, 18 Jul 2007 22:57:53 BST

    I just realized the problem is my end. I don’t know how to install a plugin from svn sources. I tried to install another plugin starting with svn but with no success. If you have any ideas let me know. Im using InstantRails on XP not a Linux station.

  17. GSIY … Ruby-Rails Portal Tue, 18 Sep 2007 20:21:00 BST
  18. Wahoo Sat, 06 Oct 2007 08:17:06 BST

    Thank you for sharing!

  19. links for 2007-10-10 « Bloggitation Wed, 10 Oct 2007 00:21:00 BST

    […] acts_as_emailable (tags: ruby rails email programming) […]

  20. Matt Grande Wed, 10 Oct 2007 20:31:29 BST

    Richard,

    The problem is you don’t have SVN installed on your machine. I had the same problem. Now, I have another problem, that I emailed you about Matt (Beedle).

    I tried installing your “acts_as_emailable” plugin, but I received the following message:

    svn: Can’t connect to host ‘matt-beedle.com’: No connection could be made because the target machine actively refused it.

    Any idea why this would happen?

    - Matt Grande.

    (PS - Sorry for emailing & commenting, and sorry if that’s frowned upon)

  21. matt Wed, 10 Oct 2007 22:00:26 BST

    Thanks for letting me know. My hosts appear to have been fiddling with the server, and the svn daemon process had been killed. I’ve restarted it, and everything appears to be working now.

  22. […] Beedle for writing and releasing Acts_As_Emailable which was my starting point with Easy_Message and now […]

  23. nerb Wed, 13 Feb 2008 02:21:24 GMT

    just wondering if you could fill in that new.rhtml code above. currently it’s blank. also, in your ego surfing have you found anyone who takes your plugin from tit to tail, at all? meaning… you did an excellent job with the plugin, but wondered if you’ve seen a blog post, tutorialize your plugin… showing how to setup an inbox for a user, how to recieve emails… how to send… that kind of thing?

  24. Hip-Hop Sun, 25 May 2008 05:40:36 BST

    Thanks for the share!!!!!!!!!!!

  25. JohnB Mon, 16 Jun 2008 09:54:30 BST

    Matt - your repository is not allowing access right now!

    ta,

    johnb.

  26. matt Mon, 16 Jun 2008 10:03:37 BST

    Hey,

    My sh*t shared hosts in their infinite wisdom decided to do some sort of OS upgrade and broke SVN over two months ago! Despite my many “urgent” tickets, they have never done anything about it.

    I have since moved all of my important day-to-day stuff to EC2, but never had time to do so with acts_as_emailable. If you would like a copy, please mail me, and I will send a tarball, although you would probably be better off taking a look at Sam Schroeders EasyMessages plugin.

Comments