conversations 0.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/.gitignore +8 -0
- data/CHANGELOG.md +7 -0
- data/Gemfile +17 -0
- data/Gemfile.lock +146 -0
- data/MIT-LICENSE +20 -0
- data/README.md +55 -0
- data/Rakefile +32 -0
- data/TODO.md +4 -0
- data/app/assets/javascripts/conversations.js +5 -0
- data/app/assets/javascripts/jquery.tokeninput.js +860 -0
- data/app/assets/stylesheets/conversations.css +4 -0
- data/app/assets/stylesheets/token-input-facebook.css +122 -0
- data/app/assets/stylesheets/token-input-mac.css +204 -0
- data/app/assets/stylesheets/token-input.css +113 -0
- data/app/controllers/conversations/conversations_controller.rb +26 -0
- data/app/controllers/conversations/messages_controller.rb +17 -0
- data/app/controllers/conversations/user_conversations_controller.rb +28 -0
- data/app/models/conversations/conversation.rb +19 -0
- data/app/models/conversations/message.rb +11 -0
- data/app/models/conversations/user_conversation.rb +22 -0
- data/app/views/conversations/conversations/new.html.erb +19 -0
- data/app/views/conversations/user_conversations/index.html.erb +17 -0
- data/app/views/conversations/user_conversations/show.html.erb +35 -0
- data/config/routes.rb +12 -0
- data/conversations.gemspec +33 -0
- data/lib/conversations.rb +19 -0
- data/lib/conversations/engine.rb +29 -0
- data/lib/conversations/models/conversationalist.rb +22 -0
- data/lib/conversations/version.rb +3 -0
- data/lib/generators/conversations/conversations_generator.rb +20 -0
- data/lib/generators/conversations/templates/20120105153739_create_conversations.rb +9 -0
- data/lib/generators/conversations/templates/20120105153800_create_user_conversations.rb +12 -0
- data/lib/generators/conversations/templates/20120105153812_create_messages.rb +11 -0
- data/lib/tasks/conversations_tasks.rake +4 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +10 -0
- data/spec/dummy/app/assets/stylesheets/application.css +24 -0
- data/spec/dummy/app/controllers/application_controller.rb +13 -0
- data/spec/dummy/app/controllers/users_controller.rb +44 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/spec/dummy/app/mailers/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/user.rb +7 -0
- data/spec/dummy/app/views/layouts/application.html.erb +15 -0
- data/spec/dummy/app/views/users/_form.html.erb +5 -0
- data/spec/dummy/app/views/users/edit.html.erb +3 -0
- data/spec/dummy/app/views/users/index.html.erb +7 -0
- data/spec/dummy/app/views/users/new.html.erb +3 -0
- data/spec/dummy/app/views/users/show.html.erb +13 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +45 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +25 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +60 -0
- data/spec/dummy/config/environments/test.rb +39 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +10 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +69 -0
- data/spec/dummy/db/migrate/20120105152859_create_users.rb +9 -0
- data/spec/dummy/db/migrate/20120105153739_create_conversations.rb +9 -0
- data/spec/dummy/db/migrate/20120105153800_create_user_conversations.rb +12 -0
- data/spec/dummy/db/migrate/20120105153812_create_messages.rb +11 -0
- data/spec/dummy/db/schema.rb +45 -0
- data/spec/dummy/db/seeds.rb +12 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +26 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/factories.rb +29 -0
- data/spec/integration/conversations_controller_spec.rb +54 -0
- data/spec/integration/messages_controller_spec.rb +37 -0
- data/spec/integration/user_conversations_controller_spec.rb +51 -0
- data/spec/models/conversation_spec.rb +28 -0
- data/spec/models/message_spec.rb +23 -0
- data/spec/models/user_conversation_spec.rb +18 -0
- data/spec/spec_helper.rb +42 -0
- metadata +300 -0
@@ -0,0 +1,17 @@
|
|
1
|
+
module Conversations
|
2
|
+
class MessagesController < ::ApplicationController
|
3
|
+
include ApplicationHelper
|
4
|
+
|
5
|
+
def create
|
6
|
+
@user = User.find(params[:user_id])
|
7
|
+
@conversation = UserConversation.find params[:conversation_id]
|
8
|
+
@message = @conversation.conversation.messages.build params[:conversations_message]
|
9
|
+
@message.user = @user
|
10
|
+
if @message.save
|
11
|
+
redirect_to user_conversation_path(@user, @conversation)
|
12
|
+
else
|
13
|
+
render template: 'conversations/user_conversations/show'
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Conversations
|
2
|
+
class UserConversationsController < ::ApplicationController
|
3
|
+
include ApplicationHelper
|
4
|
+
|
5
|
+
def index
|
6
|
+
@user = User.find params[:user_id]
|
7
|
+
@conversations = @user.user_conversations
|
8
|
+
end
|
9
|
+
|
10
|
+
def show
|
11
|
+
@user = User.find params[:user_id]
|
12
|
+
@conversation = UserConversation.find params[:id]
|
13
|
+
@message = @conversation.conversation.messages.build
|
14
|
+
end
|
15
|
+
|
16
|
+
def mark_as_read
|
17
|
+
@conversation = UserConversation.find params[:id]
|
18
|
+
@conversation.update_attributes :read => true
|
19
|
+
redirect_to user_conversation_path(current_user, @conversation)
|
20
|
+
end
|
21
|
+
|
22
|
+
def mark_as_unread
|
23
|
+
@conversation = UserConversation.find params[:id]
|
24
|
+
@conversation.update_attributes :read => false
|
25
|
+
redirect_to user_conversation_path(current_user, @conversation)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Conversations
|
2
|
+
class Conversation < ActiveRecord::Base
|
3
|
+
attr_accessible :subject, :to_tokens
|
4
|
+
attr_accessor :to_tokens
|
5
|
+
|
6
|
+
has_many :user_conversations
|
7
|
+
has_many :users, :through => :user_conversations
|
8
|
+
has_many :messages
|
9
|
+
|
10
|
+
accepts_nested_attributes_for :messages
|
11
|
+
|
12
|
+
validates :subject, :presence => :true
|
13
|
+
|
14
|
+
def to_tokens=(ids)
|
15
|
+
self.user_ids = ids.split(",")
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Conversations
|
2
|
+
class UserConversation < ActiveRecord::Base
|
3
|
+
attr_accessible :user_id, :conversation_id, :deleted, :read
|
4
|
+
|
5
|
+
belongs_to :user
|
6
|
+
belongs_to :conversation
|
7
|
+
has_many :messages, :through => :conversation
|
8
|
+
|
9
|
+
accepts_nested_attributes_for :conversation
|
10
|
+
|
11
|
+
delegate :subject, :to => :conversation
|
12
|
+
delegate :users, :to => :conversation
|
13
|
+
|
14
|
+
validates :user_id, :presence => true
|
15
|
+
|
16
|
+
# TODO: Add more attributes like :username, :first_name, :last_name
|
17
|
+
def participants
|
18
|
+
self.users.collect { |u| u.name }.join(', ')
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
<h1>New Conversation</h1>
|
2
|
+
|
3
|
+
<%= form_for(@conversation, :url => user_conversations_path) do |f| %>
|
4
|
+
<div>
|
5
|
+
<%= f.label :to_tokens %>
|
6
|
+
<%= f.text_field :to_tokens %>
|
7
|
+
</div>
|
8
|
+
<div>
|
9
|
+
<%= f.label :subject %>
|
10
|
+
<%= f.text_field :subject %>
|
11
|
+
</div>
|
12
|
+
<%= f.fields_for :messages do |m| %>
|
13
|
+
<div>
|
14
|
+
<%= m.label :body %><br />
|
15
|
+
<%= m.text_area :body %>
|
16
|
+
</div>
|
17
|
+
<% end %>
|
18
|
+
<%= f.submit %>
|
19
|
+
<% end %>
|
@@ -0,0 +1,17 @@
|
|
1
|
+
<h1><%= @user.name %>'s Conversations</h1>
|
2
|
+
|
3
|
+
<ul>
|
4
|
+
<% for conversation in @conversations do %>
|
5
|
+
<li class="<%= conversation.read? ? 'read' : 'unread' %>">
|
6
|
+
<%= conversation.participants %>
|
7
|
+
-
|
8
|
+
<%= link_to conversation.subject, user_conversation_path(conversation.user, conversation) %>
|
9
|
+
-
|
10
|
+
<%=l conversation.created_at, :format => :short %>
|
11
|
+
</li>
|
12
|
+
<% end %>
|
13
|
+
</ul>
|
14
|
+
|
15
|
+
<%= link_to "Create a New Conversation", new_user_conversation_path(@user) %>
|
16
|
+
<br>
|
17
|
+
<%= link_to "Back to User", user_path(@user) %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<h1><%= @conversation.subject %></h1>
|
2
|
+
|
3
|
+
<div>
|
4
|
+
<h4>From: <%= @user.name %></h4>
|
5
|
+
<h4>To:</h4>
|
6
|
+
<ul>
|
7
|
+
<%# TODO: move method into model %>
|
8
|
+
<% for user in @conversation.users.reject! { |u| u == @user } do %>
|
9
|
+
<li><%= link_to user.name, user %></li>
|
10
|
+
<% end %>
|
11
|
+
</ul>
|
12
|
+
</div>
|
13
|
+
|
14
|
+
<% for message in @conversation.messages do %>
|
15
|
+
<div class="message"><%= time_ago_in_words(message.created_at) %> ago, <%= message.user.name %> wrote:
|
16
|
+
<div class="message_body"><%= message.body %></div>
|
17
|
+
</div>
|
18
|
+
<% end %>
|
19
|
+
|
20
|
+
<%= form_for(@message, :url => user_conversation_messages_path(@conversation.user, @conversation)) do |f| %>
|
21
|
+
<div>
|
22
|
+
<%= f.label :body %><br />
|
23
|
+
<%= f.text_area :body %>
|
24
|
+
</div>
|
25
|
+
<%= f.submit %>
|
26
|
+
<% end %>
|
27
|
+
|
28
|
+
<% if current_user == @conversation.user && !@conversation.read? %>
|
29
|
+
<%= link_to "Mark as read", mark_as_read_user_conversation_path(@conversation.user, @conversation), :method => :post %>
|
30
|
+
<% elsif current_user == @conversation.user && @conversation.read? %>
|
31
|
+
<%= link_to "Mark as unread", mark_as_unread_user_conversation_path(@conversation.user, @conversation), :method => :post %>
|
32
|
+
<% end %>
|
33
|
+
<br />
|
34
|
+
|
35
|
+
<%= link_to "Back to conversations", user_conversations_path(@user) %>
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
Rails.application.routes.draw do
|
2
|
+
resources :users do
|
3
|
+
resources :conversations, :controller => "conversations/conversations", :only => [:new, :create]
|
4
|
+
resources :conversations, :controller => "conversations/user_conversations", :except => [:new, :create] do
|
5
|
+
resources :messages, :controller => "conversations/messages"
|
6
|
+
member do
|
7
|
+
post :mark_as_read
|
8
|
+
post :mark_as_unread
|
9
|
+
end
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
|
4
|
+
# Maintain your gem's version:
|
5
|
+
require "conversations/version"
|
6
|
+
|
7
|
+
# Describe your gem and declare its dependencies:
|
8
|
+
Gem::Specification.new do |s|
|
9
|
+
s.name = "conversations"
|
10
|
+
s.version = Conversations::VERSION
|
11
|
+
s.platform = Gem::Platform::RUBY
|
12
|
+
s.authors = ["Patrick Bartels"]
|
13
|
+
s.email = ["patrick@bartels.ug"]
|
14
|
+
s.homepage = %q{https://github.com/roughneck/conversations}
|
15
|
+
s.summary = "Summary of Conversations."
|
16
|
+
s.description = "Description of Conversations."
|
17
|
+
|
18
|
+
s.files = `git ls-files`.split("\n")
|
19
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
20
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
21
|
+
s.require_paths = ["lib"]
|
22
|
+
|
23
|
+
s.rubyforge_project = "conversations"
|
24
|
+
|
25
|
+
s.add_dependency "rails", "~> 3.1.3"
|
26
|
+
s.add_dependency "jquery-rails", "~> 1.0.19"
|
27
|
+
|
28
|
+
s.add_development_dependency "sqlite3", "~> 1.3"
|
29
|
+
s.add_development_dependency "rspec-rails", "~> 2.8"
|
30
|
+
s.add_development_dependency "capybara", "~> 1.1"
|
31
|
+
s.add_development_dependency "factory_girl_rails", "~> 1.4"
|
32
|
+
s.add_development_dependency "simplecov", "~> 0.5"
|
33
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Conversations
|
2
|
+
module Models
|
3
|
+
autoload :Conversationalist, 'conversations/models/conversationalist'
|
4
|
+
end
|
5
|
+
|
6
|
+
# Our host application root path
|
7
|
+
# We set this when the engine is initialized
|
8
|
+
mattr_accessor :app_root
|
9
|
+
|
10
|
+
# Yield self on setup for nice config blocks
|
11
|
+
class << self
|
12
|
+
def setup
|
13
|
+
yield self
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# Require engine
|
19
|
+
require "conversations/engine"
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Conversations
|
2
|
+
|
3
|
+
class Engine < Rails::Engine
|
4
|
+
|
5
|
+
initializer "conversations.load_app_instance_data" do |app|
|
6
|
+
Conversations.setup do |config|
|
7
|
+
config.app_root = app.root
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
initializer "conversations.load_static_assets" do |app|
|
12
|
+
app.middleware.use ::ActionDispatch::Static, "#{root}/public"
|
13
|
+
end
|
14
|
+
|
15
|
+
initializer "conversations.models.conversationalist" do
|
16
|
+
ActiveSupport.on_load(:active_record) do
|
17
|
+
include Conversations::Models::Conversationalist
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
initializer 'conversations.controller' do
|
22
|
+
ActiveSupport.on_load(:action_controller) do
|
23
|
+
# include Conversations::ConversationsController::InstanceMethods
|
24
|
+
# extend Conversations::ConversationsController::ClassMethods
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Conversations
|
2
|
+
module Models
|
3
|
+
module Conversationalist
|
4
|
+
def self.included(mod)
|
5
|
+
mod.extend(ClassMethods)
|
6
|
+
end
|
7
|
+
|
8
|
+
module ClassMethods
|
9
|
+
def has_conversations
|
10
|
+
has_many :user_conversations, :class_name => "Conversations::UserConversation"
|
11
|
+
has_many :conversations, :through => :user_conversations
|
12
|
+
has_many :messages, :through => :conversations
|
13
|
+
|
14
|
+
include InstanceMethods
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'rails/generators'
|
2
|
+
require 'rails/generators/migration'
|
3
|
+
|
4
|
+
class ConversationsGenerator < Rails::Generators::Base
|
5
|
+
include Rails::Generators::Migration
|
6
|
+
def self.source_root
|
7
|
+
@source_root ||= File.join(File.dirname(__FILE__), 'templates')
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.next_migration_number(dirname)
|
11
|
+
next_migration_number = current_migration_number(dirname) + 1
|
12
|
+
ActiveRecord::Migration.next_migration_number(next_migration_number)
|
13
|
+
end
|
14
|
+
|
15
|
+
def create_migration_file
|
16
|
+
migration_template '20120105153739_create_conversations.rb', 'db/migrate/create_conversations.rb'
|
17
|
+
migration_template '20120105153800_create_user_conversations.rb', 'db/migrate/create_user_conversations.rb'
|
18
|
+
migration_template '20120105153812_create_messages.rb', 'db/migrate/create_messages.rb'
|
19
|
+
end
|
20
|
+
end
|
data/spec/dummy/Rakefile
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
# Add your own tasks in files placed in lib/tasks ending in .rake,
|
3
|
+
# for example lib/tasks/capistrano.rake, and they will automatically be available to Rake.
|
4
|
+
|
5
|
+
require File.expand_path('../config/application', __FILE__)
|
6
|
+
|
7
|
+
Dummy::Application.load_tasks
|
@@ -0,0 +1,10 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into including all the files listed below.
|
2
|
+
// Add new JavaScript/Coffee code in separate files in this directory and they'll automatically
|
3
|
+
// be included in the compiled file accessible from http://example.com/assets/application.js
|
4
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
5
|
+
// the compiled file.
|
6
|
+
//
|
7
|
+
//= require jquery
|
8
|
+
//= require jquery_ujs
|
9
|
+
//= require conversations
|
10
|
+
//= require_tree .
|
@@ -0,0 +1,24 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll automatically include all the stylesheets available in this directory
|
3
|
+
* and any sub-directories. You're free to add application-wide styles to this file and they'll appear at
|
4
|
+
* the top of the compiled file, but it's generally better to create a new file per style scope.
|
5
|
+
*= require_self
|
6
|
+
*= require conversations
|
7
|
+
*= require_tree .
|
8
|
+
*/
|
9
|
+
|
10
|
+
.read {
|
11
|
+
font-style: italic;
|
12
|
+
}
|
13
|
+
|
14
|
+
.unread {
|
15
|
+
font-weight: bold;
|
16
|
+
}
|
17
|
+
|
18
|
+
.message {
|
19
|
+
border-bottom: 1px dotted gray;
|
20
|
+
}
|
21
|
+
|
22
|
+
.message_body {
|
23
|
+
margin: 10px 20px;
|
24
|
+
}
|
@@ -0,0 +1,13 @@
|
|
1
|
+
class ApplicationController < ActionController::Base
|
2
|
+
protect_from_forgery
|
3
|
+
|
4
|
+
helper_method :current_user
|
5
|
+
|
6
|
+
def current_user
|
7
|
+
begin
|
8
|
+
session[:current_user_id] ? User.find(session[:current_user_id]) : nil
|
9
|
+
rescue ActiveRecord::RecordNotFound
|
10
|
+
nil
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class UsersController < ApplicationController
|
2
|
+
def index
|
3
|
+
@users = User.all
|
4
|
+
|
5
|
+
respond_to do |format|
|
6
|
+
format.html
|
7
|
+
format.json { render :json => User.where("name like ?", "%#{params[:q]}%").map(&:attributes) }
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
def show
|
12
|
+
@user = User.find params[:id]
|
13
|
+
end
|
14
|
+
|
15
|
+
def edit
|
16
|
+
@user = User.find params[:id]
|
17
|
+
end
|
18
|
+
|
19
|
+
def update
|
20
|
+
@user = User.find params[:id]
|
21
|
+
@user.update_attributes params[:user]
|
22
|
+
redirect_to @user
|
23
|
+
end
|
24
|
+
|
25
|
+
def new
|
26
|
+
@user = User.new
|
27
|
+
end
|
28
|
+
|
29
|
+
def create
|
30
|
+
@user = User.create params[:user]
|
31
|
+
redirect_to @user
|
32
|
+
end
|
33
|
+
|
34
|
+
def signin
|
35
|
+
@user = User.find params[:id]
|
36
|
+
session[:current_user_id] = @user.id if @user
|
37
|
+
redirect_to @user
|
38
|
+
end
|
39
|
+
|
40
|
+
def signout
|
41
|
+
session.delete(:current_user_id)
|
42
|
+
redirect_to users_path
|
43
|
+
end
|
44
|
+
end
|