inboxes 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ .DS_Store
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in inboxes.gemspec
4
+ gemspec
@@ -0,0 +1,60 @@
1
+ #Inboxes
2
+
3
+ Inboxes is a young messaging system for Rails app. It:
4
+
5
+ - provides 3 models for developers: Discussion, Message and Speaker
6
+ - read/unread discussions counter
7
+ - any user can be invited to discussion by the member of this discussion, so you can chat with unlimited number of users
8
+
9
+ ##Requirements and recommendations
10
+
11
+ Inboxes requires Rails 3.x and [Devise](https://github.com/plataformatec/devise) for user identification (surely, messaging system is not possible without users). Now the gem is tested only with Ruby 1.8.7 and REE.
12
+
13
+ We recommend to use Inboxes with [Faye](https://github.com/jcoglan/faye), because it's really sexy with it.
14
+
15
+ Remember that unfortunately, Inboxes reserve 3 resources names: Discussion, Message and Speaker.
16
+
17
+ ##Installation
18
+
19
+ *Make sure that Devise is already installed and configured!*
20
+
21
+ 1. Add `gem "inboxes"` to your `Gemfile` and run `bundle install`
22
+ 2. Execute `rails generate inboxes:install`. This command will generate migration for messaging system. Don't forget to run migrations: `rake db:migrate`
23
+ 3. Add `inboxes` to your User model like [here](https://gist.github.com/1330080)
24
+ 4. Now Inboxes is ready to use. Open `http://yoursite.dev/discussions` to see the list of discussions. You can start new one.
25
+
26
+ Default Inboxes views are ugly, so you can copy into your app and make anything with them: `rails generate inboxes:views`
27
+ If you have problems with installation, you can check [code of demo app](https://github.com/kirs/inboxes-app)
28
+
29
+ ## I18n
30
+
31
+ By default, the gem provides localized phrases for Russian and English languages. You can easily override any of them. [Here is](https://github.com/kirs/inboxes/blob/master/config/locales/en.yml) list of all I18n phrases.
32
+
33
+ #Integration with Faye
34
+
35
+ 1. Add `gem "faye"` to your Gemfile and run `bundle install`. Install Faye by [the screencast](http://railscasts.com/episodes/260-messaging-with-faye)
36
+ 2. Create `messaging.js` in `app/assets/javascripts/` with these lines:
37
+
38
+ /*
39
+ = require inboxes/faye
40
+ */
41
+
42
+ 3. Copy or replace 2 views from Inboxes example app to your application: [app/views/inboxes/messages/_form](https://github.com/kirs/inboxes-app/blob/master/app/views/inboxes/messages/_form.html.haml) and [app/views/inboxes/messages/create](https://github.com/kirs/inboxes-app/blob/master/app/views/inboxes/messages/create.js.erb)
43
+
44
+ 4. Add config parameters to your application config (last 2 are not necessary):
45
+
46
+ config.inboxes.faye_enabled = true
47
+ config.inboxes.faye_host = "inboxes-app.dev" # localhost by default
48
+ config.inboxes.faye_port = 9292 # 9292 by default
49
+
50
+ 5. Faye installation is finished. If you have any troubles, check the [example app](https://github.com/kirs/inboxes-app/)
51
+
52
+ ##Todo
53
+
54
+ - Add RSpec tests
55
+
56
+ ##Authors
57
+
58
+ - [Kir Shatrov](https://github.com/kirs/) (Evrone Company)
59
+
60
+ ##Feel free for pull requests!
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,3 @@
1
+ class Inboxes::BaseController < ApplicationController
2
+
3
+ end
@@ -0,0 +1,67 @@
1
+ class Inboxes::DiscussionsController < Inboxes::BaseController
2
+ before_filter :authenticate_user!
3
+ before_filter :init_and_check_permissions, :only => :show
4
+ before_filter :load_and_check_discussion_recipient, :only => [:create, :new]
5
+
6
+ def index
7
+ @discussions = current_user.discussions
8
+ end
9
+
10
+ # GET /discussions/1
11
+ # GET /discussions/1.json
12
+ def show
13
+ @discussion.mark_as_read_for(current_user)
14
+ end
15
+
16
+ # GET /discussions/new
17
+ # GET /discussions/new.json
18
+ def new
19
+ # @discussion = Discussion.new
20
+ @discussion.messages.build
21
+ end
22
+
23
+ # POST /discussions
24
+ # POST /discussions.json
25
+ def create
26
+ # @discussion = Discussion.new(params[:discussion])
27
+ @discussion.add_recipient_token current_user.id
28
+
29
+ @discussion.messages.each do |m|
30
+ m.discussion = @discussion
31
+ m.user = current_user
32
+ end
33
+
34
+ if @discussion.save
35
+ redirect_to @discussion, :notice => t("inboxes.discussions.started")
36
+ else
37
+ render :action => "new"
38
+ end
39
+ end
40
+
41
+ private
42
+
43
+ def init_and_check_permissions
44
+ @discussion = Discussion.includes(:messages, :speakers).find(params[:id])
45
+ redirect_to discussions_url, :notice => t("inboxes.discussions.can_not_participate") unless @discussion.can_participate?(current_user)
46
+ end
47
+
48
+ def load_and_check_discussion_recipient
49
+ # initializing model fir new and create actions
50
+ @discussion = Discussion.new((params[:discussion] ? params[:discussion] : {}))
51
+ # @discussion.recipient_tokens = params[:recipients] if params[:recipients] # pre-population
52
+
53
+ # checking if discussion with this user already exists
54
+ if @discussion.recipient_ids && @discussion.recipient_ids.size == 1
55
+ user = User.find(@discussion.recipient_ids.first)
56
+ discussion = Discussion.find_between_users(current_user, user)
57
+ if discussion
58
+ # it exists, let's add message and redirect current user
59
+ @discussion.messages.each do |message|
60
+ Message.create(:discussion => discussion, :user => current_user, :body => message.body) if message.body
61
+ end
62
+ # перекидываем на нее
63
+ redirect_to discussion_url(discussion), :notice => t("inboxes.discussions.exists", :user => user[Inboxes::config.user_name])
64
+ end
65
+ end
66
+ end
67
+ end
@@ -0,0 +1,18 @@
1
+ class Inboxes::MessagesController < Inboxes::BaseController
2
+
3
+ def create
4
+ @discussion = Discussion.find(params[:discussion_id])
5
+ redirect_to root_url, :notice => t("inboxes.discussions.can_not_participate") unless @discussion.can_participate?(current_user)
6
+
7
+ @message = Message.new(params[:message])
8
+ @message.user = current_user
9
+ @message.discussion = @discussion
10
+ @message.save
11
+
12
+ respond_to do |format|
13
+ format.html { redirect_to @message.discussion }
14
+ format.js
15
+ end
16
+ end
17
+
18
+ end
@@ -0,0 +1,26 @@
1
+ class Inboxes::SpeakersController < Inboxes::BaseController
2
+ before_filter :init_and_check_permissions
3
+
4
+ def create
5
+ # check permissions
6
+ raise ActiveRecord::RecordNotFound unless params[:speaker] && params[:speaker][:user_id]
7
+ @user = User.find(params[:speaker][:user_id])
8
+
9
+ flash[:notice] = t("views.speakers.added") if @discussion.add_speaker(@user)
10
+ redirect_to @discussion
11
+ end
12
+
13
+ def destroy
14
+ @speaker = Speaker.find(params[:id])
15
+ @speaker.destroy
16
+ flash[:notice] = @speaker.user == current_user ? t("inboxes.discussions.leaved") : t("inboxes.speakers.removed")
17
+ redirect_to @discussion.speakers.any? && @discussion.can_participate?(current_user) ? @discussion : discussions_url
18
+ end
19
+
20
+ private
21
+
22
+ def init_and_check_permissions
23
+ @discussion = Discussion.find(params[:discussion_id])
24
+ redirect_to discussions_url, :notice => t("inboxes.discussions.can_not_participate") unless @discussion.can_participate?(current_user)
25
+ end
26
+ end
@@ -0,0 +1,9 @@
1
+ require 'net/http'
2
+ module InboxesHelper
3
+ def inboxes_faye_broadcast(channel, &block)
4
+ message = {:channel => channel, :data => capture(&block), :ext => {:auth_token => defined?(FAYE_TOKEN) ? FAYE_TOKEN : ""}}
5
+ uri = URI.parse("http://#{Inboxes::config.faye_host}:#{Inboxes::config.faye_port}/faye")
6
+ # Rails.logger.info "Faye URL: #{uri}"
7
+ res = Net::HTTP.post_form(uri, :message => message.to_json)
8
+ end
9
+ end
@@ -0,0 +1,116 @@
1
+
2
+ class Discussion < ActiveRecord::Base
3
+ attr_accessor :recipient_tokens, :recipient_ids
4
+ attr_reader :recipient_ids
5
+
6
+ # paginates_per 10
7
+
8
+ # создатель
9
+ has_many :messages, :dependent => :destroy
10
+
11
+ # участники
12
+ has_many :speakers, :dependent => :destroy
13
+ has_many :users, :through => :speakers
14
+
15
+ # отметки о прочтении юзеров
16
+
17
+ scope :unread_for, (lambda do |user_or_user_id|
18
+ user = user_or_user_id.is_a?(User) ? user_or_user_id.id : user_or_user_id
19
+ joins(:speakers).where("discussions.updated_at >= speakers.updated_at AND speakers.user_id = ?", user)
20
+ end)
21
+
22
+ accepts_nested_attributes_for :messages
23
+
24
+ validate :check_that_has_at_least_two_users # не даем создать дискуссию, у которой нет получателей
25
+
26
+ # добавляем записи об указанных собеседников
27
+ after_save(:on => :create) do
28
+ # Rails.logger.info("Repicients ids: #{recipient_ids.inspect}")
29
+
30
+ if recipient_ids.kind_of?(Array)
31
+ recipient_ids.uniq!
32
+ recipient_ids.each do |id|
33
+ recipient = User.find(id)
34
+ add_speaker(recipient) if recipient
35
+ end
36
+ end
37
+ end
38
+
39
+ def recipient_tokens=(ids)
40
+ self.recipient_ids = ids
41
+ end
42
+
43
+ def add_recipient_token id
44
+ self.recipient_ids << id if self.recipient_ids
45
+ end
46
+
47
+ def add_speaker(user)
48
+ raise ArgumentError, "You can add speaker only to existing Discussion. Save your the Discussion object firstly" if new_record?
49
+ Speaker.create(:discussion => self, :user => user)
50
+ end
51
+
52
+ def remove_speaker(user)
53
+ speaker = find_speaker_by_user(user)
54
+ speaker.destroy if speaker
55
+ end
56
+
57
+ def user_invited_at(user)
58
+ speaker = find_speaker_by_user(user)
59
+ speaker.created_at
60
+ end
61
+
62
+ def can_participate?(user)
63
+ speaker = find_speaker_by_user(user)
64
+ speaker ? true : false
65
+ end
66
+
67
+ # проверяет, есть ли уже беседа между пользователями
68
+ # TODO вынести в отдельный метод а в этом возращать true/false, а то неправославно как-то
69
+ def self.find_between_users(user, user2)
70
+ dialog = nil
71
+ discussions = self.joins(:speakers).includes(:users).where("speakers.user_id = ?", user.id)
72
+ Rails.logger.info "Searching for ids: #{user.id}, #{user2.id}"
73
+ discussions.each do |discussion|
74
+ dialog = discussion if discussion.private? && ((discussion.users.first == user && discussion.users.last == user2) || (discussion.users.first == user2 && discussion.users.last == user))
75
+ end
76
+ dialog
77
+ end
78
+
79
+ # приватная/групповая
80
+ def private?
81
+ self.users.size <= 2
82
+ end
83
+
84
+ # дата последнего сообщения в дискуссии
85
+ # def last_message_at
86
+ # self.messages.last ? self.messages.last.created_at : nil
87
+ # end
88
+
89
+ # проверка, является ли дискуссия непрочитанной для пользователя
90
+ def unread_for?(user)
91
+ speaker = find_speaker_by_user(user)
92
+ if speaker
93
+ self.updated_at >= speaker.updated_at
94
+ else
95
+ true
96
+ end
97
+ end
98
+
99
+ # пометить как прочитанная
100
+ def mark_as_read_for(user)
101
+ speaker = Speaker.find_or_create_by_user_id_and_discussion_id(user.id, self.id)
102
+ # flag.update_attributes(:updat => Time.zone.now)
103
+ speaker.touch
104
+ end
105
+
106
+ def find_speaker_by_user user
107
+ Speaker.find_by_discussion_id_and_user_id(self.id, user.id)
108
+ end
109
+
110
+ private
111
+
112
+ def check_that_has_at_least_two_users
113
+ errors.add :recipient_tokens, t("inboxes.discussions.choose_at_least_one_recipient") if !self.recipient_ids || self.recipient_ids.size < 2
114
+ end
115
+
116
+ end
@@ -0,0 +1,22 @@
1
+ class Message < ActiveRecord::Base
2
+
3
+ default_scope order(:created_at)
4
+
5
+ belongs_to :discussion, :counter_cache => true
6
+ belongs_to :user
7
+
8
+ validates :user, :discussion, :body, :presence => true
9
+
10
+ after_save :touch_discussion_and_mark_as_read
11
+
12
+ def visible_for? user
13
+ self.created_at.to_i >= self.discussion.user_invited_at(user).to_i
14
+ end
15
+
16
+ private
17
+
18
+ def touch_discussion_and_mark_as_read
19
+ self.discussion.touch
20
+ self.discussion.mark_as_read_for(self.user)
21
+ end
22
+ end
@@ -0,0 +1,16 @@
1
+ class Speaker < ActiveRecord::Base
2
+ belongs_to :user
3
+ belongs_to :discussion
4
+
5
+ validates_uniqueness_of :user_id, :scope => :discussion_id
6
+ validates :user, :discussion, :presence => true
7
+
8
+ after_destroy :destroy_discussion
9
+
10
+ private
11
+
12
+ def destroy_discussion
13
+ self.discussion.destroy unless self.discussion.speakers.any?
14
+ end
15
+
16
+ end
@@ -0,0 +1,12 @@
1
+ = form_for @discussion do |f|
2
+ %p
3
+ = f.label :recipient_tokens
4
+ %br
5
+ = select_tag "discussion[recipient_tokens]", options_from_collection_for_select(User.all, :id, Inboxes::config.user_name), :multiple => true, :size => "4"
6
+ %p
7
+ = f.fields_for :messages do |j|
8
+ = j.label :body
9
+ %br
10
+ = j.text_area :body
11
+
12
+ %p= f.submit
@@ -0,0 +1,19 @@
1
+ %h1 Discussions list
2
+ %p
3
+ Unread messages:
4
+ %table
5
+ %tr
6
+ %th Last message
7
+ %th Members
8
+ %th Unread
9
+ - @discussions.each do |discussion|
10
+ %tr
11
+ %td
12
+ = discussion.updated_at
13
+ %td
14
+ = link_to discussion.users.collect{|u| u[Inboxes::config.user_name]}.join(', '), discussion
15
+ %td
16
+ = discussion.unread_for?(current_user) ? "Yes" : "No"
17
+
18
+ %p
19
+ = link_to "Create new", new_discussion_path
@@ -0,0 +1,5 @@
1
+ %h1 New discussion
2
+
3
+ = render "form"
4
+
5
+ %p= link_to "All discussions", discussions_path
@@ -0,0 +1,31 @@
1
+ - if Inboxes::config.faye_enabled
2
+ = javascript_include_tag "messaging"
3
+
4
+ %h1 Discussion
5
+
6
+ %h3
7
+ Members
8
+ - @discussion.speakers.each do |speaker|
9
+ %div
10
+ = speaker.user[Inboxes::config.user_name]
11
+ = link_to '(remove)', discussion_speaker_path(@discussion, speaker), :method => :delete
12
+
13
+ - available_users = User.all.map { |u| u unless @discussion.users.include?(u) }.delete_if { |w| w.nil? }
14
+ - if available_users.any?
15
+ = form_for Speaker.new, :url => discussion_speakers_path(@discussion) do |f|
16
+ = f.label :user_id, "Add speaker"
17
+ = f.collection_select :user_id, available_users, :id, :name
18
+ = f.submit "Add"
19
+
20
+
21
+ %h3 Messages
22
+
23
+ #messages_box
24
+ = render @discussion.messages, :as => :message
25
+
26
+ %h3 Add message
27
+ = render "inboxes/messages/form"
28
+
29
+ %p
30
+ = link_to "Leave discussion", discussion_speaker_path(@discussion, @discussion.find_speaker_by_user(current_user)), :method => :delete unless @discussion.private?
31
+ = link_to "All discussions", discussions_path
@@ -0,0 +1,7 @@
1
+ .message_form
2
+ = form_for Message.new, :url => discussion_messages_path(@discussion.id), :method => :post do |f|
3
+ %p
4
+ = f.label :body
5
+ %br
6
+ = f.text_area :body
7
+ %p= f.submit
@@ -0,0 +1,8 @@
1
+ .message
2
+ %p
3
+ %span
4
+ = message.user[Inboxes::config.user_name]
5
+ @
6
+ = l(message.created_at)
7
+ =":"
8
+ %b= message.body
@@ -0,0 +1,15 @@
1
+ en:
2
+ activerecord:
3
+ attributes:
4
+ discussion:
5
+ recipient_tokens: "Recipients"
6
+ inboxes:
7
+ speakers:
8
+ added: "Speaker was added to discussion"
9
+ removed: "Speaker was removed from discussion"
10
+ discussions:
11
+ started: "Discussion started"
12
+ leaved: "You leaved the discussion"
13
+ exists: "Discussion between you and %{user} already exists"
14
+ can_not_participate: "You are not listed in this discussion"
15
+ choose_at_least_one_recipient: "You should choose at least one recipient of discussion"
@@ -0,0 +1,17 @@
1
+ ru:
2
+ activerecord:
3
+ attributes:
4
+ discussion:
5
+ recipient_tokens: "Получатели"
6
+ message:
7
+ body: "Сообщение"
8
+ inboxes:
9
+ discussions:
10
+ started: "Чат начат"
11
+ leaved: "Вы покинули дискуссию"
12
+ exists: "Дискуссия между вами и %{user} уже существует"
13
+ can_not_participate: "Вы не состоите в этой дискуссии"
14
+ choose_at_least_one_recipient: "Укажите хотя бы одного получателя"
15
+ speakers:
16
+ added: "Участник дискуссии добавлен"
17
+ removed: "Участник дискуссии удален"
@@ -0,0 +1,11 @@
1
+ Rails.application.routes.draw do
2
+
3
+ resources :discussions, :except => :edit, :module => :inboxes do
4
+ resources :messages, :only => [:create, :index]
5
+ resources :speakers, :only => [:create, :destroy]
6
+ member do
7
+ post 'leave'
8
+ end
9
+ end
10
+
11
+ end
@@ -0,0 +1,33 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "inboxes/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "inboxes"
7
+ s.version = Inboxes::VERSION
8
+ s.authors = ["Kir Shatrov"]
9
+ s.email = ["razor.psp@gmail.com"]
10
+ s.homepage = "http://evrone.com/"
11
+ s.summary = %q{Messaging system for Rails 3 app}
12
+ s.description = %q{Messaging system for Rails 3 app}
13
+
14
+ s.rubyforge_project = "inboxes"
15
+
16
+ s.files = `git ls-files`.split("\n")
17
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
19
+ s.require_paths = ["lib"]
20
+
21
+ # specify any dependencies here; for example:
22
+ # s.add_development_dependency "ruby-debug"
23
+ s.add_runtime_dependency "haml-rails"
24
+ # s.add_runtime_dependency "inherited_resources"
25
+
26
+ # s.add_development_dependency 'dm-sqlite-adapter', ['>= 1.1.0']
27
+ s.add_development_dependency 'rspec', ['>= 0']
28
+ s.add_development_dependency 'rspec-rails', ['>= 0']
29
+ # s.add_development_dependency 'rr', ['>= 0']
30
+ # s.add_development_dependency 'steak', ['>= 0']
31
+ # s.add_development_dependency 'capybara', ['>= 0']
32
+ s.add_development_dependency 'database_cleaner', ['>= 0']
33
+ end
@@ -0,0 +1,40 @@
1
+ require 'rails/generators'
2
+ require 'rails/generators/migration'
3
+
4
+ module Inboxes
5
+ module Generators
6
+ class InstallGenerator < Rails::Generators::Base
7
+ include Rails::Generators::Migration
8
+
9
+ source_root File.expand_path("../templates", __FILE__)
10
+
11
+ # desc "Generates migration for Discussion, Message, Speaker and DiscussionView models"
12
+
13
+ def self.orm
14
+ Rails::Generators.options[:rails][:orm]
15
+ end
16
+
17
+ # def self.source_root
18
+ # File.join(File.dirname(__FILE__), 'templates', (orm.to_s unless orm.class.eql?(String)) )
19
+ # end
20
+
21
+ def self.orm_has_migration?
22
+ [:active_record].include? orm
23
+ end
24
+
25
+ def self.next_migration_number(dirname)
26
+ if ActiveRecord::Base.timestamped_migrations
27
+ migration_number = Time.now.utc.strftime("%Y%m%d%H%M%S").to_i
28
+ migration_number += 1
29
+ migration_number.to_s
30
+ else
31
+ "%.3d" % (current_migration_number(dirname) + 1)
32
+ end
33
+ end
34
+
35
+ def copy_migration
36
+ migration_template 'install.rb', 'db/migrate/install_inboxes.rb'
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,29 @@
1
+ class InstallInboxes < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :discussions do |t|
4
+ t.integer :messages_count, :default => 0 # counter cache
5
+ t.timestamps
6
+ end
7
+
8
+ create_table :messages do |t|
9
+ t.references :user
10
+ t.references :discussion
11
+ t.text :body
12
+
13
+ t.timestamps
14
+ end
15
+
16
+ create_table :speakers do |t|
17
+ t.references :user
18
+ t.references :discussion
19
+
20
+ t.timestamps
21
+ end
22
+ end
23
+
24
+ def self.down
25
+ drop_table :speakers
26
+ drop_table :discussions
27
+ drop_table :messages
28
+ end
29
+ end
@@ -0,0 +1,24 @@
1
+ require 'rails/generators'
2
+
3
+ module Inboxes
4
+ module Generators
5
+ class ViewsGenerator < Rails::Generators::Base
6
+ source_root File.expand_path('../../../../app/views', __FILE__)
7
+ #class_option :template_engine, :type => :string, :aliases => '-e', :desc => 'Template engine for the views. Available options are "erb" and "haml".'
8
+
9
+ # TODO support of both haml and erb
10
+ def copy_or_fetch
11
+ filename_pattern = File.join self.class.source_root, "*" #/*.html.#{template_engine}"
12
+ Dir.glob(filename_pattern).map {|f| File.basename f}.each do |f|
13
+ directory f.to_s, "app/views/#{f}"
14
+ end
15
+ end
16
+
17
+ # private
18
+
19
+ # def template_engine
20
+ # # options[:template_engine].try(:to_s).try(:downcase) || 'erb'
21
+ # end
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,33 @@
1
+ require "inboxes/version"
2
+ require "inboxes/railtie"
3
+ require "inboxes/engine"
4
+ require "inboxes/active_record_extension"
5
+
6
+ module Inboxes
7
+
8
+ def self.configure(&block)
9
+ yield @config ||= Inboxes::Configuration.new
10
+ end
11
+
12
+ # Global settings for Inboxes
13
+ def self.config
14
+ @config
15
+ end
16
+
17
+ # need a Class for 3.0
18
+ class Configuration #:nodoc:
19
+ include ActiveSupport::Configurable
20
+ config_accessor :user_name
21
+ config_accessor :faye_host
22
+ config_accessor :faye_port
23
+ config_accessor :faye_enabled
24
+
25
+ def param_name
26
+ config.param_name.respond_to?(:call) ? config.param_name.call() : config.param_name
27
+ end
28
+ end
29
+
30
+ # adding method inboxes for models
31
+ ActiveRecord::Base.extend(Inboxes::ActiveRecordExtension)
32
+
33
+ end
@@ -0,0 +1,11 @@
1
+ module Inboxes
2
+ module ActiveRecordExtension
3
+ def inboxes(options = {})
4
+ # field = options[:as] || name
5
+ # prefix = options[:prefix] || "with"
6
+
7
+ has_many :speakers, :dependent => :destroy
8
+ has_many :discussions, :through => :speakers
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,4 @@
1
+ module Inboxes
2
+ class Engine < ::Rails::Engine
3
+ end
4
+ end
@@ -0,0 +1,18 @@
1
+ require 'rails'
2
+
3
+ module Inboxes
4
+ class Railtie < ::Rails::Railtie
5
+ config.inboxes = ActiveSupport::OrderedOptions.new
6
+
7
+ initializer "inboxes.configure" do |app|
8
+ Inboxes.configure do |config|
9
+ config.user_name = app.config.inboxes[:user_name] || "email"
10
+ config.faye_enabled = app.config.inboxes[:faye_enabled] || false
11
+ config.faye_host = app.config.inboxes[:faye_host] || "localhost"
12
+ config.faye_port = app.config.inboxes[:faye_port] || "9292"
13
+ end
14
+
15
+ # app.config.middleware.insert_before "::Rails::Rack::Logger", "Inboxes::Middleware"
16
+ end
17
+ end
18
+ end
@@ -0,0 +1,3 @@
1
+ module Inboxes
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,3 @@
1
+ /*
2
+ = require_directory ./faye
3
+ */
@@ -0,0 +1,9 @@
1
+ $ ->
2
+ fayeUrl = window.location.origin + ":9292/faye" # change port for post of your Faye daemon
3
+ fayeJS = fayeUrl + ".js"
4
+ $.getScript(fayeJS, (e)->
5
+ faye = new Faye.Client(fayeUrl)
6
+ faye.subscribe(window.location.pathname, (data)->
7
+ eval(data)
8
+ )
9
+ )
metadata ADDED
@@ -0,0 +1,152 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: inboxes
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Kir Shatrov
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-11-16 00:00:00 Z
19
+ dependencies:
20
+ - !ruby/object:Gem::Dependency
21
+ name: haml-rails
22
+ prerelease: false
23
+ requirement: &id001 !ruby/object:Gem::Requirement
24
+ none: false
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ hash: 3
29
+ segments:
30
+ - 0
31
+ version: "0"
32
+ type: :runtime
33
+ version_requirements: *id001
34
+ - !ruby/object:Gem::Dependency
35
+ name: rspec
36
+ prerelease: false
37
+ requirement: &id002 !ruby/object:Gem::Requirement
38
+ none: false
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ hash: 3
43
+ segments:
44
+ - 0
45
+ version: "0"
46
+ type: :development
47
+ version_requirements: *id002
48
+ - !ruby/object:Gem::Dependency
49
+ name: rspec-rails
50
+ prerelease: false
51
+ requirement: &id003 !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ type: :development
61
+ version_requirements: *id003
62
+ - !ruby/object:Gem::Dependency
63
+ name: database_cleaner
64
+ prerelease: false
65
+ requirement: &id004 !ruby/object:Gem::Requirement
66
+ none: false
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ hash: 3
71
+ segments:
72
+ - 0
73
+ version: "0"
74
+ type: :development
75
+ version_requirements: *id004
76
+ description: Messaging system for Rails 3 app
77
+ email:
78
+ - razor.psp@gmail.com
79
+ executables: []
80
+
81
+ extensions: []
82
+
83
+ extra_rdoc_files: []
84
+
85
+ files:
86
+ - .gitignore
87
+ - Gemfile
88
+ - README.md
89
+ - Rakefile
90
+ - app/controllers/inboxes/base_controller.rb
91
+ - app/controllers/inboxes/discussions_controller.rb
92
+ - app/controllers/inboxes/messages_controller.rb
93
+ - app/controllers/inboxes/speakers_controller.rb
94
+ - app/helpers/inboxes_helper.rb
95
+ - app/models/discussion.rb
96
+ - app/models/message.rb
97
+ - app/models/speaker.rb
98
+ - app/views/inboxes/discussions/_form.html.haml
99
+ - app/views/inboxes/discussions/index.html.haml
100
+ - app/views/inboxes/discussions/new.html.haml
101
+ - app/views/inboxes/discussions/show.html.haml
102
+ - app/views/inboxes/messages/_form.html.haml
103
+ - app/views/inboxes/messages/_message.html.haml
104
+ - config/locales/en.yml
105
+ - config/locales/ru.yml
106
+ - config/routes.rb
107
+ - inboxes.gemspec
108
+ - lib/generators/inboxes/install_generator.rb
109
+ - lib/generators/inboxes/templates/install.rb
110
+ - lib/generators/inboxes/views_generator.rb
111
+ - lib/inboxes.rb
112
+ - lib/inboxes/active_record_extension.rb
113
+ - lib/inboxes/engine.rb
114
+ - lib/inboxes/railtie.rb
115
+ - lib/inboxes/version.rb
116
+ - vendor/assets/javascripts/inboxes/faye.js
117
+ - vendor/assets/javascripts/inboxes/faye/init.js.coffee
118
+ homepage: http://evrone.com/
119
+ licenses: []
120
+
121
+ post_install_message:
122
+ rdoc_options: []
123
+
124
+ require_paths:
125
+ - lib
126
+ required_ruby_version: !ruby/object:Gem::Requirement
127
+ none: false
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ hash: 3
132
+ segments:
133
+ - 0
134
+ version: "0"
135
+ required_rubygems_version: !ruby/object:Gem::Requirement
136
+ none: false
137
+ requirements:
138
+ - - ">="
139
+ - !ruby/object:Gem::Version
140
+ hash: 3
141
+ segments:
142
+ - 0
143
+ version: "0"
144
+ requirements: []
145
+
146
+ rubyforge_project: inboxes
147
+ rubygems_version: 1.8.11
148
+ signing_key:
149
+ specification_version: 3
150
+ summary: Messaging system for Rails 3 app
151
+ test_files: []
152
+