acts_as_emailable
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_mailoruser.new_mail
These two return all read emails, although I’m not sure if there will be much use for it.
user.read_mailoruser.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.
[…] UPDATE: I have now packaged all of this code up into a plugin. For install instructions read this post. […]
great work man… contributions like this make RoR shine!
the zen-like simplicity.
beautiful.
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,
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… ;)
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….
[…] http://matt-beedle.com/2007/06/05/acts_as_emailable/ […]
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?
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!
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.
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?
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
Hey Matt,
Thanks for your help, it works great now!
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.
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?
[…] 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 […]
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.
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.
[…] I found this http://matt-beedle.com/2007/06/05/acts_as_emailable/ […]
Thank you for sharing!
[…] acts_as_emailable (tags: ruby rails email programming) […]
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)
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.
[…] Beedle for writing and releasing Acts_As_Emailable which was my starting point with Easy_Message and now […]
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?