提交 f0adf28e 编写于 作者: D Dmitriy Zaporozhets

Merge branch 'event-create-service' into 'master'

EventCreateService class

The goal is to collect all event creation logic in one place called EventCreateService.
Because now its placed in observers, controllers, services etc
......@@ -47,14 +47,6 @@ class Event < ActiveRecord::Base
scope :in_projects, ->(project_ids) { where(project_id: project_ids).recent }
class << self
def determine_action(record)
if [Issue, MergeRequest].include? record.class
Event::CREATED
elsif record.kind_of? Note
Event::COMMENTED
end
end
def create_ref_event(project, user, ref, action = 'add', prefix = 'refs/heads')
commit = project.repository.commit(ref.target)
......
class ActivityObserver < BaseObserver
observe :issue, :note, :milestone
def after_create(record)
if record.kind_of?(Note)
# Skip system notes, like status changes and cross-references.
return true if record.system?
# Skip wall notes to prevent spamming of dashboard
return true if record.noteable_type.blank?
end
create_event(record, Event.determine_action(record)) if current_user
end
def after_close(record, transition)
create_event(record, Event::CLOSED)
end
def after_reopen(record, transition)
create_event(record, Event::REOPENED)
end
protected
def create_event(record, status)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
action: status,
author_id: current_user.id
)
end
end
......@@ -3,6 +3,10 @@ class BaseObserver < ActiveRecord::Observer
NotificationService.new
end
def event_service
EventCreateService.new
end
def log_info message
Gitlab::AppLogger.info message
end
......
class IssueObserver < BaseObserver
def after_create(issue)
notification.new_issue(issue, current_user)
event_service.open_issue(issue, current_user)
issue.create_cross_references!(issue.project, current_user)
execute_hooks(issue)
end
def after_close(issue, transition)
notification.close_issue(issue, current_user)
event_service.close_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
def after_reopen(issue, transition)
event_service.reopen_issue(issue, current_user)
create_note(issue)
execute_hooks(issue)
end
......
class MergeRequestObserver < ActivityObserver
observe :merge_request
class MergeRequestObserver < BaseObserver
def after_create(merge_request)
if merge_request.author_id
create_event(merge_request, Event.determine_action(merge_request))
end
event_service.open_mr(merge_request, current_user)
notification.new_merge_request(merge_request, current_user)
merge_request.create_cross_references!(merge_request.project, current_user)
execute_hooks(merge_request)
end
def after_close(merge_request, transition)
create_event(merge_request, Event::CLOSED)
event_service.close_mr(merge_request, current_user)
notification.close_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
end
def after_reopen(merge_request, transition)
create_event(merge_request, Event::REOPENED)
event_service.reopen_mr(merge_request, current_user)
create_note(merge_request)
execute_hooks(merge_request)
merge_request.reload_code
......@@ -33,16 +28,6 @@ class MergeRequestObserver < ActivityObserver
execute_hooks(merge_request)
end
def create_event(record, status)
Event.create(
project: record.target_project,
target_id: record.id,
target_type: record.class.name,
action: status,
author_id: current_user.id
)
end
private
# Create merge request note with service comment like 'Status changed to closed'
......
class MilestoneObserver < BaseObserver
def after_create(milestone)
event_service.open_milestone(milestone, current_user)
end
def after_close(milestone, transition)
event_service.close_milestone(milestone, current_user)
end
def after_reopen(milestone, transition)
event_service.reopen_milestone(milestone, current_user)
end
end
......@@ -2,6 +2,12 @@ class NoteObserver < BaseObserver
def after_create(note)
notification.new_note(note)
# Skip system notes, like status changes and cross-references.
# Skip wall notes to prevent spamming of dashboard
if note.noteable_type.present? && !note.system
event_service.leave_note(note, current_user)
end
unless note.system?
# Create a cross-reference note if this Note contains GFM that names an
# issue, merge request, or commit.
......
# EventCreateService class
#
# Used for creating events feed on dashboard after certain user action
#
# Ex.
# EventCreateService.new.new_issue(issue, current_user)
#
class EventCreateService
def open_issue(issue, current_user)
create_event(issue, current_user, Event::CREATED)
end
def close_issue(issue, current_user)
create_event(issue, current_user, Event::CLOSED)
end
def reopen_issue(issue, current_user)
create_event(issue, current_user, Event::REOPENED)
end
def open_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::CREATED)
end
def close_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::CLOSED)
end
def reopen_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::REOPENED)
end
def merge_mr(merge_request, current_user)
create_event(merge_request, current_user, Event::MERGED)
end
def open_milestone(milestone, current_user)
create_event(milestone, current_user, Event::CREATED)
end
def close_milestone(milestone, current_user)
create_event(milestone, current_user, Event::CLOSED)
end
def reopen_milestone(milestone, current_user)
create_event(milestone, current_user, Event::REOPENED)
end
def leave_note(note, current_user)
create_event(note, current_user, Event::COMMENTED)
end
private
def create_event(record, current_user, status)
Event.create(
project: record.project,
target_id: record.id,
target_type: record.class.name,
action: status,
author_id: current_user.id
)
end
end
......@@ -8,13 +8,7 @@ module MergeRequests
end
def create_merge_event(merge_request, current_user)
Event.create(
project: merge_request.target_project,
target_id: merge_request.id,
target_type: merge_request.class.name,
action: Event::MERGED,
author_id: current_user.id
)
EventCreateService.new.merge_mr(merge_request, current_user)
end
def execute_project_hooks(merge_request)
......
......@@ -19,7 +19,7 @@ module Gitlab
# config.plugins = [ :exception_notification, :ssl_requirement, :all ]
# Activate observers that should always be running.
config.active_record.observers = :activity_observer,
config.active_record.observers = :milestone_observer,
:project_activity_cache_observer,
:issue_observer,
:key_observer,
......
require 'spec_helper'
describe ActivityObserver do
let(:project) { create(:project) }
before { Thread.current[:current_user] = create(:user) }
def self.it_should_be_valid_event
it { @event.should_not be_nil }
it { @event.project.should == project }
end
describe "Issue created" do
before do
Issue.observers.enable :activity_observer do
@issue = create(:issue, project: project)
@event = Event.last
end
end
it_should_be_valid_event
it { @event.action.should == Event::CREATED }
it { @event.target.should == @issue }
end
describe "Issue commented" do
before do
Note.observers.enable :activity_observer do
@issue = create(:issue, project: project)
@note = create(:note, noteable: @issue, project: project, author: @issue.author)
@event = Event.last
end
end
it_should_be_valid_event
it { @event.action.should == Event::COMMENTED }
it { @event.target.should == @note }
end
describe "Ignore system notes" do
let(:author) { create(:user) }
let!(:issue) { create(:issue, project: project) }
let!(:other) { create(:issue) }
it "should not create events for status change notes" do
expect do
Note.observers.enable :activity_observer do
Note.create_status_change_note(issue, project, author, 'reopened', nil)
end
end.to_not change { Event.count }
end
it "should not create events for cross-reference notes" do
expect do
Note.observers.enable :activity_observer do
Note.create_cross_reference_note(issue, other, author, issue.project)
end
end.to_not change { Event.count }
end
end
end
......@@ -100,16 +100,4 @@ describe API::API do
response.status.should == 405
end
end
describe "PUT /projects/:id/issues/:issue_id to test observer on close" do
before { enable_observers }
after { disable_observers }
it "should create an activity event when an issue is closed" do
Event.should_receive(:create)
put api("/projects/#{project.id}/issues/#{issue.id}", user),
state_event: "close"
end
end
end
require 'spec_helper'
describe EventCreateService do
let(:service) { EventCreateService.new }
describe 'Issues' do
describe :open_issue do
let(:issue) { create(:issue) }
it { service.open_issue(issue, issue.author).should be_true }
it "should create new event" do
expect { service.open_issue(issue, issue.author) }.to change { Event.count }
end
end
describe :close_issue do
let(:issue) { create(:issue) }
it { service.close_issue(issue, issue.author).should be_true }
it "should create new event" do
expect { service.close_issue(issue, issue.author) }.to change { Event.count }
end
end
describe :reopen_issue do
let(:issue) { create(:issue) }
it { service.reopen_issue(issue, issue.author).should be_true }
it "should create new event" do
expect { service.reopen_issue(issue, issue.author) }.to change { Event.count }
end
end
end
describe 'Merge Requests' do
describe :open_mr do
let(:merge_request) { create(:merge_request) }
it { service.open_mr(merge_request, merge_request.author).should be_true }
it "should create new event" do
expect { service.open_mr(merge_request, merge_request.author) }.to change { Event.count }
end
end
describe :close_mr do
let(:merge_request) { create(:merge_request) }
it { service.close_mr(merge_request, merge_request.author).should be_true }
it "should create new event" do
expect { service.close_mr(merge_request, merge_request.author) }.to change { Event.count }
end
end
describe :merge_mr do
let(:merge_request) { create(:merge_request) }
it { service.merge_mr(merge_request, merge_request.author).should be_true }
it "should create new event" do
expect { service.merge_mr(merge_request, merge_request.author) }.to change { Event.count }
end
end
describe :reopen_mr do
let(:merge_request) { create(:merge_request) }
it { service.reopen_mr(merge_request, merge_request.author).should be_true }
it "should create new event" do
expect { service.reopen_mr(merge_request, merge_request.author) }.to change { Event.count }
end
end
end
describe 'Milestone' do
let(:user) { create :user }
describe :open_milestone do
let(:milestone) { create(:milestone) }
it { service.open_milestone(milestone, user).should be_true }
it "should create new event" do
expect { service.open_milestone(milestone, user) }.to change { Event.count }
end
end
describe :close_mr do
let(:milestone) { create(:milestone) }
it { service.close_milestone(milestone, user).should be_true }
it "should create new event" do
expect { service.close_milestone(milestone, user) }.to change { Event.count }
end
end
end
end
......@@ -90,7 +90,7 @@ module TestEnv
size: 12.45
)
ActivityObserver.any_instance.stub(
BaseObserver.any_instance.stub(
current_user: double("current_user", id: 1)
)
end
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册