[refs #54] Add subscribes and notifications

This commit is contained in:
konstantin.grabar 2011-12-26 19:48:57 +04:00
parent 5237939f49
commit ce6746f7a9
19 changed files with 218 additions and 8 deletions

View File

@ -0,0 +1,31 @@
class SubscribesController < ApplicationController
def create
@subscribe = @subscribeable.subscribes.build(:user_id => current_user.id)
if @subscribe.save
flash[:notice] = I18n.t("flash.subscribe.saved")
redirect_to :back
else
flash[:error] = I18n.t("flash.subscribe.saved_error")
redirect_to :back
end
end
def destroy
@subscribe = Subscribe.find(params[:id])
@subscribe.destroy
flash[:notice] = t("flash.subscribe.destroyed")
redirect_to :back
end
private
def find_subscribeable
params.each do |name, value|
if name =~ /(.+)_id$/
return $1.classify.constantize.find(value)
end
end
nil
end
end

View File

@ -0,0 +1,2 @@
module SubscribesHelper
end

View File

@ -5,7 +5,31 @@ class UserMailer < ActionMailer::Base
def new_user_notification(user) def new_user_notification(user)
@user = user @user = user
mail(:to => user.email, :subject => "Регистрация на проекте «#{APP_CONFIG['project_name']}»") do |format| mail(:to => user.email, :subject => I18n.t("notifications.subjects.new_user_notification", :project_name => APP_CONFIG['project_name'])) do |format|
format.html
end
end
def new_comment_notification(comment, user)
@user = user
@comment = comment
mail(:to => user.email, :subject => I18n.t("notifications.subjects.new_comment_notification")) do |format|
format.html
end
end
def new_issue_notification(issue, user)
@user = user
@issue = issue
mail(:to => user.email, :subject => I18n.t("notifications.subjects.new_issue_notification")) do |format|
format.html
end
end
def issue_assign_notification(issue, user)
@user = user
@issue = issue
mail(:to => user.email, :subject => I18n.t("notifications.subjects.issue_assign_notification")) do |format|
format.html format.html
end end
end end

View File

@ -3,4 +3,20 @@ class Comment < ActiveRecord::Base
belongs_to :user belongs_to :user
validates :body, :user_id, :commentable_id, :commentable_type, :presence => true validates :body, :user_id, :commentable_id, :commentable_type, :presence => true
after_create :deliver_new_comment_notification
protected
def deliver_new_comment_notification
#UserMailer.new_comment_notification(self, self.commentable.user).deliver
#UserMailer.new_comment_notification(self, self.commentable.project.owner).deliver
recipients = self.commentable.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
recipients = recipients | [self.commentable.user_id]
recipients = recipients | [self.commentable.project.owner_id] if self.commentable.project.owner_type == 'User'
recipients.each do |recipient_id|
recipient = User.find(recipient_id)
UserMailer.new_comment_notification(self, recipient).deliver
end
end
end end

View File

@ -5,12 +5,17 @@ class Issue < ActiveRecord::Base
belongs_to :user belongs_to :user
has_many :comments, :as => :commentable has_many :comments, :as => :commentable
has_many :subscribes, :as => :subscribeable
validates :title, :body, :project_id, :user_id, :presence => true validates :title, :body, :project_id, :user_id, :presence => true
#attr_readonly :serial_id #attr_readonly :serial_id
after_create :set_serial_id after_create :set_serial_id
after_create :subscribe_users
after_create :deliver_new_issue_notification
after_create :deliver_issue_assign_notification
after_update :deliver_issue_assign_notification
protected protected
@ -18,4 +23,38 @@ class Issue < ActiveRecord::Base
self.serial_id = self.project.issues.count self.serial_id = self.project.issues.count
self.save! self.save!
end end
def deliver_new_issue_notification
#UserMailer.new_issue_notification(self, self.project.owner).deliver
#self.project.relations.by_role('admin').each do |rel|
# admin = User.find(rel.object_id)
# UserMailer.new_issue_notification(self, admin).deliver
#end
recipients = collect_recipient_ids
recipients.each do |recipient_id|
recipient = User.find(recipient_id)
UserMailer.new_issue_notification(self, recipient).deliver
end
end
def deliver_issue_assign_notification
UserMailer.issue_assign_notification(self, self.user).deliver if self.user_id_was != self.user_id
end
def subscribe_users
recipients = collect_recipient_ids
recipients.each do |recipient_id|
ss = self.subscribes.build(:user_id => recipient_id)
ss.save!
end
end
def collect_recipient_ids
recipients = self.project.relations.by_role('admin').where(:object_type => 'User').map { |rel| rel.read_attribute(:object_id) }
recipients = recipients | [self.user_id]
recipients = recipients | [self.project.owner_id] if self.project.owner_type == 'User'
recipients
end
end end

View File

@ -10,6 +10,7 @@ class Relation < ActiveRecord::Base
scope :by_object, lambda {|obj| {:conditions => ['object_id = ? AND object_type = ?', obj.id, obj.class.to_s]}} scope :by_object, lambda {|obj| {:conditions => ['object_id = ? AND object_type = ?', obj.id, obj.class.to_s]}}
scope :by_target, lambda {|tar| {:conditions => ['target_id = ? AND target_type = ?', tar.id, tar.class.to_s]}} scope :by_target, lambda {|tar| {:conditions => ['target_id = ? AND target_type = ?', tar.id, tar.class.to_s]}}
scope :by_role, lambda {|role| {:conditions => ['role = ?', role]}}
def self.create_with_role(object, target, role) def self.create_with_role(object, target, role)
r = new r = new

4
app/models/subscribe.rb Normal file
View File

@ -0,0 +1,4 @@
class Subscribe < ActiveRecord::Base
belongs_to :subscribeable, :polymorphic => true
belongs_to :user
end

View File

@ -20,6 +20,14 @@
= t('activerecord.attributes.issue.status') = t('activerecord.attributes.issue.status')
\: \:
= @issue.status = @issue.status
%p
%b
= t('layout.issues.subscribe')
\:
- if @issue.subscribes.exists? :user_id => current_user.id
= link_to t('layout.issues.unsubscribe_btn'), unsubscribe_issue(@issue), :method => :post
- else
= link_to t('layout.issues.subscribe_btn'), subscribe_issue(@issue), :method => :delete
%a{ :name => "comments" } %a{ :name => "comments" }
.block .block

View File

@ -0,0 +1,7 @@
%p== Здравствуйте, #{@user.name}.
%p Вам была назначена задача #{ link_to @issue.title, show_issue_path(@issue.project, @issue.serial_id) }
%p== Команда поддержки «ROSA Build System»

View File

@ -0,0 +1,7 @@
%p== Здравствуйте, #{@user.name}.
%p К задаче #{ link_to @comment.commentable.title, show_issue_path(@comment.commentable.project, @comment.commentable.serial_id) } был добавлен новый комментарий.
%p== Команда поддержки «ROSA Build System»

View File

@ -0,0 +1,7 @@
%p== Здравствуйте, #{@user.name}.
%p К проекту #{ link_to @issue.project.name, project_path(@issue.project) } была добавлена задача #{ link_to @issue.title, show_issue_path(@issue.project, @issue.serial_id) }
%p== Команда поддержки «ROSA Build System»

View File

@ -106,6 +106,9 @@ ru:
open: Открытые open: Открытые
closed: Закрытые closed: Закрытые
any: Все any: Все
subscribe: Подписка на уведомления
subscribe_btn: Подписаться
unsubscribe_btn: Отписаться
comments: comments:
confirm_delete: Вы уверены, что хотите удалить комментарий? confirm_delete: Вы уверены, что хотите удалить комментарий?
@ -653,3 +656,9 @@ ru:
distro: Дистрибутив distro: Дистрибутив
platform: Архитектура platform: Архитектура
counter: Закачки counter: Закачки
notifications:
subjects:
new_comment_notification: Новый комментарий к Вашей задаче
new_issue_notification: Новая задача добавлена к проекту
new_user_notification: Регистрация на проекте «%{ project_name }»
issue_assign_notification: Вам назначили задачу

View File

@ -78,6 +78,9 @@ Rosa::Application.routes.draw do
resources :categories, :only => [:index, :show] resources :categories, :only => [:index, :show]
end end
match "issues/:issue_id/subscribe" => 'subscribes#create', :as => :subscribe_issue, :via => :post
match "issues/:issue_id/unsubscribe" => 'subscribes#destroy', :as => :unsubscribe_issue, :via => :delete
match "projects/:project_id/issues/:serial_id" => 'issues#show', :serial_id => /\d+/, :as => :show_issue, :via => :get match "projects/:project_id/issues/:serial_id" => 'issues#show', :serial_id => /\d+/, :as => :show_issue, :via => :get
match "projects/:project_id/issues/:serial_id/edit" => 'issues#edit', :serial_id => /\d+/, :as => :edit_issue, :via => :get match "projects/:project_id/issues/:serial_id/edit" => 'issues#edit', :serial_id => /\d+/, :as => :edit_issue, :via => :get
resources :projects do resources :projects do

View File

@ -0,0 +1,14 @@
class CreateSubscribes < ActiveRecord::Migration
def self.up
create_table :subscribes do |t|
t.integer :subscribeable_id
t.string :subscribeable_type
t.integer :user_id
t.timestamps
end
end
def self.down
drop_table :subscribes
end
end

View File

@ -10,7 +10,7 @@
# #
# It's strongly recommended to check this file into your version control system. # It's strongly recommended to check this file into your version control system.
ActiveRecord::Schema.define(:version => 20111221194422) do ActiveRecord::Schema.define(:version => 20111226141947) do
create_table "arches", :force => true do |t| create_table "arches", :force => true do |t|
t.string "name", :null => false t.string "name", :null => false
@ -245,7 +245,6 @@ ActiveRecord::Schema.define(:version => 20111221194422) do
t.string "object_type" t.string "object_type"
t.integer "target_id" t.integer "target_id"
t.string "target_type" t.string "target_type"
t.integer "role_id"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "role" t.string "role"
@ -272,18 +271,26 @@ ActiveRecord::Schema.define(:version => 20111221194422) do
add_index "rpms", ["project_id", "arch_id"], :name => "index_rpms_on_project_id_and_arch_id" add_index "rpms", ["project_id", "arch_id"], :name => "index_rpms_on_project_id_and_arch_id"
add_index "rpms", ["project_id"], :name => "index_rpms_on_project_id" add_index "rpms", ["project_id"], :name => "index_rpms_on_project_id"
create_table "subscribes", :force => true do |t|
t.integer "subscribeable_id"
t.string "subscribeable_type"
t.integer "user_id"
t.datetime "created_at"
t.datetime "updated_at"
end
create_table "users", :force => true do |t| create_table "users", :force => true do |t|
t.string "name" t.string "name"
t.string "email", :default => "", :null => false t.string "email", :default => "", :null => false
t.string "encrypted_password", :limit => 128, :default => "", :null => false t.string "encrypted_password", :limit => 128, :default => "", :null => false
t.string "password_salt", :default => "", :null => false
t.string "reset_password_token" t.string "reset_password_token"
t.datetime "reset_password_sent_at" t.string "remember_token"
t.datetime "remember_created_at" t.datetime "remember_created_at"
t.datetime "created_at" t.datetime "created_at"
t.datetime "updated_at" t.datetime "updated_at"
t.string "uname"
t.text "ssh_key" t.text "ssh_key"
t.integer "role_id" t.string "uname"
t.string "role" t.string "role"
end end

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe SubscribesController do
end

View File

@ -0,0 +1,6 @@
# Read about factories at http://github.com/thoughtbot/factory_girl
FactoryGirl.define do
factory :subscribe do
end
end

View File

@ -0,0 +1,15 @@
require 'spec_helper'
# Specs in this file have access to a helper object that includes
# the SubscribesHelper. For example:
#
# describe SubscribesHelper do
# describe "string concat" do
# it "concats two strings with spaces" do
# helper.concat_strings("this","that").should == "this that"
# end
# end
# end
describe SubscribesHelper do
pending "add some examples to (or delete) #{__FILE__}"
end

View File

@ -0,0 +1,5 @@
require 'spec_helper'
describe Subscribe do
pending "add some examples to (or delete) #{__FILE__}"
end