Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
pkg/
simple-private-messages.gemspec
.svn
76 changes: 60 additions & 16 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -1,16 +1,43 @@
= Simple Private Messages
= Simple Private Messages + jQuery + jQuery-UI

Now Rails 3 compatible!

For Rails 2.3.x users there is an appropriately named branch that can be used.
For Rails 3!

This plugin provides basic private messaging functionality between the users
of a site. It's not big on features but the idea is that it's nice and simple
and light on resources.

It's not bound to specific model names and plays nice with will_paginate.

= Setup
== Requirements

* Rails 3.x

Required only if ui.multiselect is used to select multiple recipients (in the view) in a comfortable way. The plugin also works without jQuery and ui.multiselect.

* jQuery >= 1.4.x (Included in the plugin)
* jQuery-UI >= 1.8.x (Included in the plugin)

== Install

Use the rake tasks to install all required javascripts and stylesheets or do the installation manually.

=== With rake tasks

This rake task install all js and css files to public/javascripts/jquery and public/stylesheets/jquery.

rake simple_private_messages:install # Copy javascripts, stylesheets and images to public

=== Manual installation

Copy all jQuery javascript files from vendor/plugins/simple-private-messages/javascripts to:

public/javascripts/jquery

Copy all CSS stylesheets and images files from vendor/plugins/simple-private-messages/stylesheets to:

public/stylesheets/jquery

== Setup

First create the private message model by running the simple_private_messages:model
generator, passing two parameters - the name you want to use for the Message
Expand All @@ -20,33 +47,50 @@ For all examples in the readme, we will use Message and User.

rails generate simple_private_messages:model User Message

Now you can run the scaffold generator that generates a complete view and a controller

rails generate simple_private_messages:scaffold User Message

Now add the following entry to the model which will have the messages

has_private_messages

If you have used anything other than "Message", you will have to pass the
correct class name along as :class_name.

Add the following line on top (Between <head> ... </head> tag) of your app/view/layout/application.html.erb file:

<%= yield :simple_private_messages %>

That's it.

= Usage
=== Rake Tasks

rake simple_private_messages:install # Copy javascripts, stylesheets and images to public
rake simple_private_messages:uninstall # Remove javascripts, stylesheets and images from public

== Usage

Examples assume you're using Restful Authentication or AAA, with a user model
of User and message model of Message.

== Creating / sending a message:
=== Creating / sending a message:

frank = User.find_by_login("frank")
george = User.find_by_login("george")

mc = MessageContent.new
mc.subject = "Happy Festivus, son"
mc.body = "It's time for the Feats of Strength."
mc.save

message = Message.new
message.subject = "Happy Festivus, son"
message.body = "It's time for the Feats of Strength."
message.sender = frank
message.recipient = george
message.message_content = mc
message.save

== Reading a message
=== Reading a message

message = Message.read(id, user)

Expand All @@ -58,7 +102,7 @@ You can also check if a message has been read with the following:

message.read?

== Retrieving a user's received mail
=== Retrieving a user's received mail

newman = User.find_by_login("newman")
newman.received_messages
Expand All @@ -71,19 +115,19 @@ Or the following for true or false on whether there are unread messages:

newman.unread_messages?

== Retrieving a user's sent mail
=== Retrieving a user's sent mail

newman = User.find_by_login("newman")
newman.sent_messages

== Custom finds
=== Custom finds

newman.sent_messages.find(:all,
:conditions => ["read_at < ?", 2.days.ago],
:limit => 20,
:order => "created_at ASC")

== Deleting a message
=== Deleting a message

newman = User.find_by_login("newman")
message = newman.received_messages.find(3)
Expand All @@ -101,7 +145,7 @@ Now that both sender and recipient have marked the message deleted, it
gets destroyed. Should a message be sent to oneself, it will be deleted
in one step due to the sender and recipient being the same.

= Scaffold
== Scaffold

A generator is included to create a basic controller and set of views.

Expand All @@ -116,7 +160,7 @@ Then uncomment the entry at the top of the message model to establish the

You should now have working messaging.

= Tests
== Tests

Unit tests are provided for the model extensions but not for the generated
scaffold. Running these requires sqlite3.
Expand Down
2 changes: 1 addition & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ begin
Jeweler::Tasks.new do |gem|
gem.name = "simple-private-messages"
gem.summary = "Simple private messages plugin for Rails 3"
gem.files = Dir["{lib}/**/*", "{app}/**/*", "{config}/**/*"]
gem.files = Dir["{lib}/**/*", "{javascripts}/**/*","{stylesheets}/**/*", "{test}/**/*"]
gem.email = "ferdinand.niedermann@gmail.com"
gem.authors = ["Jon Gilbraith","Ferdinand Niedermann"]
gem.homepage="http://github.com/nerdinand/simple-private-messages"
Expand Down
10 changes: 10 additions & 0 deletions install.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
require "pathname"

puts "\nCopy all jQuery javascript files from vendor/plugins/simple-private-messages/javascripts to:\n " + (Pathname.getwd + "javascripts")
puts "\nCopy all CSS stylesheets and images files from vendor/plugins/simple-private-messages/stylesheets to:\n " + (Pathname.getwd + "stylesheets")

puts "
Add the following line on top (Between <head> ... </head> tag) of your app/view/layout/application.html.erb file:

<%= yield :simple_private_messages %>
"
23 changes: 18 additions & 5 deletions lib/generators/simple_private_messages/model/model_generator.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,11 +40,24 @@ def go
@plural_lower_case_parent = user_model_name.pluralize.underscore

#directory "app/models"
template "model.rb", "app/models/#{singular_lower_case_name}.rb"

migration_template "migration.rb", "db/migrate/create_#{plural_lower_case_name}", :assigns => {
:migration_name => "Create#{plural_camel_case_name}"
}
# Removed
# template "model.rb", "app/models/#{singular_lower_case_name}.rb"
# Added two models
template "model_head.rb", "app/models/#{singular_lower_case_name}.rb"
template "model_ref.rb", "app/models/#{singular_lower_case_name}_content.rb"

# Removed
# migration_template "migration.rb", "db/migrate/create_#{plural_lower_case_name}", :assigns => {
# :migration_name => "Create#{plural_camel_case_name}"
# }

# Added two migrations (messages and message_contents)
migration_template "migration_head.rb", "db/migrate/create_#{plural_lower_case_name}", :assigns => {
:migration_name => "Create#{plural_camel_case_name}"
}
migration_template "migration_ref.rb", "db/migrate/create_#{singular_lower_case_name}_contents", :assigns => {
:migration_name => "Create#{singular_camel_case_name}Contents"
}
end
end
end
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,7 @@ def self.up
create_table :<%= plural_lower_case_name %> do |t|
t.integer :sender_id, :recipient_id
t.boolean :sender_deleted, :recipient_deleted, :default => 0
t.string :subject
t.text :body
t.references :<%= singular_lower_case_name + "_content" %>
t.datetime :read_at
t.timestamps
end
Expand All @@ -13,4 +12,4 @@ def self.up
def self.down
drop_table <%= plural_lower_case_name %>
end
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
class <%= "Create#{singular_camel_case_name}Contents" %> < ActiveRecord::Migration
def self.up
create_table :<%= singular_lower_case_name + "_contents" %> do |t|
t.string :subject
t.text :body
t.timestamps
end
end

def self.down
drop_table <%= singular_lower_case_name + "_contents" %>
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ class <%= singular_camel_case_name %> < ActiveRecord::Base

is_private_message<% unless singular_camel_case_parent == "User" %> :class_name => "<%= "#{singular_camel_case_parent}" %>"<% end %>

# The :to accessor is used by the scaffolding,
# uncomment it if using it or you can remove it if not
#attr_accessor :to

belongs_to :<%= singular_lower_case_name + '_content' %>

end
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
class <%= singular_camel_case_name + "Content" %> < ActiveRecord::Base

# Process only attributes that comes from the html post
attr_accessor :to, :no_save

# Process only attributes that comes from the html post
attr_accessible :to, :no_save, :subject, :body

# Relations between models
has_many :<%= plural_lower_case_name %>

# Validations of all attributes
validates_presence_of :subject
validates_presence_of :body
validates_presence_of :to
validates_inclusion_of :no_save, :in => ['false', 'true'],
:allow_nil => true

end
Original file line number Diff line number Diff line change
Expand Up @@ -8,53 +8,73 @@ def index
else
@<%= plural_lower_case_name %> = @<%= singular_lower_case_parent %>.received_messages
end
respond_to do |format|
format.html # index.html.erb
end
end

def show
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.read(params[:id], current_user)
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.read(params[:id], current_<%= singular_lower_case_parent %>)
end

def new
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.new
@<%= singular_lower_case_name %>_content = <%= singular_camel_case_name %>Content.new
@<%= singular_lower_case_name %>_content.to = []

if params[:reply_to]
@reply_to = @<%= singular_lower_case_parent %>.received_messages.find(params[:reply_to])
@reply_to = current_<%= singular_lower_case_parent %>.received_messages.find(params[:reply_to])
unless @reply_to.nil?
@<%= singular_lower_case_name %>.to = @reply_to.sender.login
@<%= singular_lower_case_name %>.subject = "Re: #{@reply_to.subject}"
@<%= singular_lower_case_name %>.body = "\n\n*Original message*\n\n #{@reply_to.body}"
@<%= singular_lower_case_name %>_content.to = [@reply_to.sender.id]
@<%= singular_lower_case_name %>_content.subject = "Re: #{@reply_to.<%= singular_lower_case_name %>_content.subject}"
@<%= singular_lower_case_name %>_content.body = "\n\n*Original <%= singular_lower_case_name %>*\n\n #{@reply_to.<%= singular_lower_case_name %>_content.body}"
end
end
end

def create
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.new(params[:<%= singular_lower_case_name %>])
@<%= singular_lower_case_name %>.sender = @<%= singular_lower_case_parent %>
@<%= singular_lower_case_name %>.recipient = <%= singular_camel_case_parent %>.find_by_login(params[:<%= singular_lower_case_name %>][:to])

if @<%= singular_lower_case_name %>.save
flash[:notice] = "Message sent"
redirect_to user_<%= plural_lower_case_name %>_path(@<%= singular_lower_case_parent %>)
else
render :action => :new
def create
@<%= plural_lower_case_parent %> = (<%= singular_camel_case_parent %>.find(params[:<%= singular_lower_case_name %>_content][:to]) if params[:<%= singular_lower_case_name %>_content][:to])
@<%= singular_lower_case_name %>_content = <%= singular_camel_case_name %>Content.new(params[:<%= singular_lower_case_name %>_content])

respond_to do |format|
if @<%= singular_lower_case_name %>_content.save
@<%= plural_lower_case_name %> = []
for <%= singular_lower_case_parent %> in @<%= plural_lower_case_parent %> do
<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.new
<%= singular_lower_case_name %>.sender = current_<%= singular_lower_case_parent %>
<%= singular_lower_case_name %>.recipient = <%= singular_lower_case_parent %>
<%= singular_lower_case_name %>.sender_deleted = 1 if params[:<%= singular_lower_case_name %>_content][:no_save] == 'true'
@<%= plural_lower_case_name %> << <%= singular_lower_case_name %>
end
@<%= singular_lower_case_name %>_content.<%= plural_lower_case_name %> = (@<%= plural_lower_case_name %> || [])

format.html { redirect_to(<%= singular_lower_case_parent %>_<%= plural_lower_case_name %>_path(@<%= singular_lower_case_parent %>), :notice => "<%= singular_camel_case_name %> sent") }
format.xml { render :xml => @<%= singular_lower_case_name %>_content, :status => :created, :location => @<%= singular_lower_case_name %>_content }
else
format.html { render :action => "new" }
format.xml { render :xml => @<%= singular_lower_case_name %>_content.errors, :status => :unprocessable_entity }
end
end
end

def delete_selected
if request.post?
if params[:delete]
params[:delete].each { |id|
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.find(:first, :conditions => ["<%= plural_lower_case_name %>.id = ? AND (sender_id = ? OR recipient_id = ?)", id, @<%= singular_lower_case_parent %>, @<%= singular_lower_case_parent %>])
@<%= singular_lower_case_name %>.mark_deleted(@<%= singular_lower_case_parent %>) unless @<%= singular_lower_case_name %>.nil?
params[:delete].each { |id|
@<%= singular_lower_case_name %> = <%= singular_camel_case_name %>.where("<%= singular_lower_case_name %>.id = ? AND (sender_id = ? OR recipient_id = ?)", id, current_<%= singular_lower_case_parent %>, current_<%= singular_lower_case_parent %>).first()
unless @<%= singular_lower_case_name %>.nil?
counter = <%= singular_camel_case_name %>.where("<%= singular_lower_case_name %>_content_id = ? AND (sender_deleted = 0 OR recipient_deleted = 0)", @<%= singular_lower_case_name %>.<%= singular_lower_case_name %>_content_id).count
@<%= singular_lower_case_name %>.mark_deleted(current_<%= singular_lower_case_parent %>, counter) unless @<%= singular_lower_case_name %>.nil?
end
}
flash[:notice] = "Messages deleted"
flash[:notice] = "<%= plural_camel_case_name %> deleted"
end
redirect_to user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, @<%= plural_lower_case_name %>)
end
end


private
def set_user
@<%= singular_lower_case_parent %> = User.find(params[:<%= singular_lower_case_parent %>_id])
@<%= singular_lower_case_parent %> = <%= singular_camel_case_parent %>.find(params[:<%= singular_lower_case_parent %>_id])
end
end
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,9 @@
<td><%%= check_box_tag "delete[]", <%= singular_lower_case_name %>.id %></td>
<td>
<%% if <%= singular_lower_case_name %>.read? %>
<%%= link_to h(<%= singular_lower_case_name %>.subject), user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %>
<%%= link_to h(<%= singular_lower_case_name %>.<%= singular_lower_case_name %>_content.subject), user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %>
<%% else %>
<%%= link_to "#{h(<%= singular_lower_case_name %>.subject)} (unread)", user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %>
<%%= link_to "#{h(<%= singular_lower_case_name %>.<%= singular_lower_case_name %>_content.subject)} (unread)", user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %>
<%% end %>
</td>
<td><%%= link_to h(<%= singular_lower_case_name %>.sender.login), user_path(@<%= singular_lower_case_parent %>) %></td>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
<%% for <%= singular_lower_case_name %> in @<%= plural_lower_case_name %> %>
<tr>
<td><%%= check_box_tag "delete[]", <%= singular_lower_case_name %>.id %></td>
<td><%%= link_to h(<%= singular_lower_case_name %>.subject), user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %></td>
<td><%%= link_to h(<%= singular_lower_case_name %>.<%= singular_lower_case_name %>_content.subject), user_<%= singular_lower_case_name %>_path(@<%= singular_lower_case_parent %>, <%= singular_lower_case_name %>) %></td>
<td><%%= link_to h(<%= singular_lower_case_name %>.recipient.login), user_path(@<%= singular_lower_case_parent %>) %></td>
<td><%%=h <%= singular_lower_case_name %>.created_at.to_s(:long) %></td>
</tr>
Expand Down
Loading