active_metadata 0.0.2 → 0.1.9
Sign up to get free protection for your applications and to get access to all the features.
- data/app/controllers/active_metadata/attachments_controller.rb +47 -0
- data/app/controllers/active_metadata/histories_controller.rb +16 -0
- data/app/controllers/active_metadata/notes_controller.rb +61 -0
- data/app/controllers/active_metadata/watchers_controller.rb +34 -0
- data/app/helpers/application_helper.rb +2 -0
- data/app/views/active_metadata/attachments/index.html.erb +11 -0
- data/app/views/active_metadata/histories/index.html.erb +5 -0
- data/app/views/active_metadata/notes/_form.html.erb +23 -0
- data/app/views/active_metadata/notes/edit.html.erb +8 -0
- data/app/views/active_metadata/notes/index.html.erb +11 -0
- data/app/views/active_metadata/notes/index.js.erb +1 -0
- data/app/views/active_metadata/notes/show.html.erb +9 -0
- data/app/views/active_metadata/watchers/create.js.erb +1 -0
- data/app/views/active_metadata/watchers/destroy.js.erb +1 -0
- data/app/views/active_metadata/watchers/index.html.erb +5 -0
- data/config/active_metadata.yml +17 -0
- data/config/application.rb +0 -0
- data/config/database.yml +11 -0
- data/config/initializers/inflections.rb +7 -0
- data/config/mongoid.yml +28 -0
- data/config/routes.rb +30 -0
- data/db/development.sqlite3 +0 -0
- data/db/migrate/001_create_document.rb +12 -0
- data/db/migrate/002_add_surname_to_document.rb +9 -0
- data/db/migrate/003_create_section.rb +13 -0
- data/db/migrate/004_create_user.rb +14 -0
- data/db/migrate/005_create_inboxes.rb +19 -0
- data/db/migrate/006_create_alert_message.rb +37 -0
- data/db/migrate/007_create_notes.rb +22 -0
- data/db/migrate/008_create_history.rb +20 -0
- data/db/migrate/009_create_watcher.rb +21 -0
- data/db/migrate/010_create_attachment.rb +26 -0
- data/db/migrate/011_add_created_by_to_histories.rb +10 -0
- data/db/test.sqlite3 +0 -0
- data/features/step_definitions/add_a_user_to_a_watcher_steps.rb +29 -0
- data/features/step_definitions/trigger_alert_on_modify_steps.rb +86 -0
- data/features/supports/file.txt +1 -0
- data/features/supports/initializer.rb +1 -0
- data/features/supports/updated_file.txt +1 -0
- data/features/watchlist/add_a_user_to_a_watcher.feature +19 -0
- data/features/watchlist/trigger_alert_on_modify.feature +90 -0
- data/lib/active_metadata/base.rb +59 -0
- data/lib/active_metadata/persistence/active_record/attachment.rb +42 -0
- data/lib/active_metadata/persistence/active_record/history.rb +22 -0
- data/lib/active_metadata/persistence/active_record/note.rb +45 -0
- data/lib/active_metadata/persistence/active_record/watcher.rb +45 -0
- data/lib/active_metadata/persistence/active_record.rb +26 -0
- data/lib/active_metadata/persistence/mongoid/attachment.rb +45 -0
- data/lib/active_metadata/persistence/mongoid/history.rb +26 -0
- data/lib/active_metadata/persistence/mongoid/note.rb +48 -0
- data/lib/active_metadata/persistence/mongoid/watcher.rb +43 -0
- data/lib/active_metadata/persistence/mongoid.rb +30 -0
- data/lib/active_metadata/persistence/persistence.rb +13 -0
- data/lib/active_metadata/railtie.rb +6 -0
- data/lib/active_metadata/version.rb +1 -1
- data/lib/active_metadata.rb +6 -12
- data/lib/application_controller.rb +28 -0
- data/lib/application_helper.rb +7 -0
- data/lib/engine.rb +29 -0
- data/lib/model/active_record/attachment.rb +18 -0
- data/lib/model/active_record/history.rb +2 -0
- data/lib/model/active_record/note.rb +2 -0
- data/lib/model/active_record/watcher.rb +4 -0
- data/lib/model/mongoid/active_meta.rb +6 -0
- data/lib/model/mongoid/attachment.rb +25 -0
- data/lib/model/mongoid/history.rb +9 -0
- data/lib/model/mongoid/label.rb +14 -0
- data/lib/model/mongoid/note.rb +10 -0
- data/lib/model/mongoid/watcher.rb +24 -0
- data/lib/rails/railties/tasks.rake +8 -0
- data/lib/rake/active_record_tasks.rb +77 -0
- data/lib/rake/task.rb +18 -0
- data/lib/templates/active_metadata.yml +17 -0
- data/lib/templates/active_metadata_migrations +67 -0
- data/lib/templates/mongoid.yml +20 -0
- data/spec/active_metadata_spec.rb +596 -0
- data/spec/benchmark_spec.rb +35 -0
- data/spec/controllers/metadata_controller_spec.rb +14 -0
- data/spec/spec_helper.rb +87 -0
- data/spec/support/document.rb +8 -0
- data/spec/support/pdf_test.pdf +0 -0
- data/spec/support/pdf_test_2.pdf +0 -0
- data/spec/support/section.rb +8 -0
- data/spec/support/user.rb +13 -0
- data/spec/support/watcher_notifier.rb +21 -0
- metadata +201 -19
- data/.gitignore +0 -4
- data/Gemfile +0 -4
- data/Rakefile +0 -1
- data/active_metadata.gemspec +0 -24
@@ -0,0 +1,86 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
|
3
|
+
# Given ##########################################################
|
4
|
+
Given /^an ActiveRecord instance of 'Document' with 'name' equals to "([^"]*)"$/ do |name|
|
5
|
+
raise unless Document.ancestors.include?(::ActiveRecord::Base)
|
6
|
+
@document = Document.create!(:name => name, :surname => 'Garden' )
|
7
|
+
end
|
8
|
+
|
9
|
+
Given /^a User "([^"]*)" instantiated$/ do |email|
|
10
|
+
@current_user = User.create!(:email => email, :firstname => 'John', :lastname => 'smith' )
|
11
|
+
end
|
12
|
+
|
13
|
+
Given /^a watcher on the "([^"]*)" field$/ do |attribute|
|
14
|
+
@attribute = attribute
|
15
|
+
@document.create_watcher_for(@attribute, @current_user)
|
16
|
+
end
|
17
|
+
|
18
|
+
# When ##########################################################
|
19
|
+
When /^saving a new value "([^"]*)" on the "([^"]*)" field$/ do |value, attribute|
|
20
|
+
@document.send("#{attribute}=", value)
|
21
|
+
@document.save!
|
22
|
+
end
|
23
|
+
|
24
|
+
When /^creating a new note on the "([^"]*)" field with content "([^"]*)"$/ do |field, content|
|
25
|
+
@document.create_note_for(field.to_sym, content)
|
26
|
+
end
|
27
|
+
|
28
|
+
When /^afterwards I update the note on the field "([^"]*)" with content "([^"]*)"$/ do |field, content|
|
29
|
+
note = @document.notes_for(field.to_sym).first
|
30
|
+
@document.update_note(note.id, content)
|
31
|
+
end
|
32
|
+
|
33
|
+
When /^afterwards I delete the note on the field "([^"]*)"$/ do |field|
|
34
|
+
note = @document.notes_for(field.to_sym).first
|
35
|
+
@document.delete_note_for(field.to_sym,note.id)
|
36
|
+
end
|
37
|
+
|
38
|
+
When /^creating a new attachment on the "([^"]*)" field with name "([^"]*)"$/ do |field, filename|
|
39
|
+
file = File.expand_path("../../supports/#{filename}", __FILE__)
|
40
|
+
@attachment = Rack::Test::UploadedFile.new(file, "plain/text")
|
41
|
+
@document.save_attachment_for(field.to_sym, @attachment)
|
42
|
+
@document.attachments_for(field.to_sym).should have(1).record
|
43
|
+
end
|
44
|
+
|
45
|
+
When /^deleting the attachment on the "([^"]*)" field with name "([^"]*)"$/ do |field, filename|
|
46
|
+
@attachment = @document.attachments_for(field.to_sym).last
|
47
|
+
@document.delete_attachment_for(field,@attachment.id)
|
48
|
+
end
|
49
|
+
|
50
|
+
When /^updating the attachment on the "([^"]*)" field with name "([^"]*)"$/ do |field, filename|
|
51
|
+
@attachment = @document.attachments_for(field.to_sym).last
|
52
|
+
file = File.expand_path("../../supports/#{filename}", __FILE__)
|
53
|
+
updated_file = Rack::Test::UploadedFile.new(file, "plain/text")
|
54
|
+
|
55
|
+
@document.update_attachment_for(field,@attachment.id, updated_file)
|
56
|
+
end
|
57
|
+
# Then ##########################################################
|
58
|
+
Then /^([^"]*) alert should be found in the inbox of the user$/ do |number|
|
59
|
+
@notifier = @document.notifier
|
60
|
+
# @current_user.inbox.messages.should have(number.to_i).record
|
61
|
+
# @message = @current_user.inbox.messages.last
|
62
|
+
end
|
63
|
+
|
64
|
+
Then /^should regard the "([^"]*)" field$/ do |field|
|
65
|
+
@notifier.matched_label.should == field
|
66
|
+
end
|
67
|
+
|
68
|
+
Then /^should record the "([^"]*)" model class$/ do |model_class|
|
69
|
+
@notifier.model_class.should == model_class
|
70
|
+
end
|
71
|
+
|
72
|
+
Then /^should record the "([^"]*)" in the old_value$/ do |old_value|
|
73
|
+
@notifier.old_value.should == old_value
|
74
|
+
end
|
75
|
+
|
76
|
+
Then /^should record the "([^"]*)" in the new_value$/ do |new_value|
|
77
|
+
@notifier.new_value.should == new_value
|
78
|
+
end
|
79
|
+
|
80
|
+
Then /^should record the "([^"]*)" in the type$/ do |type|
|
81
|
+
@notifier.type.to_s.should == type
|
82
|
+
end
|
83
|
+
|
84
|
+
Then /^should record the current_user_id in the created_by$/ do
|
85
|
+
@notifier.created_by.to_i.should == User.current.id
|
86
|
+
end
|
@@ -0,0 +1 @@
|
|
1
|
+
my test
|
@@ -0,0 +1 @@
|
|
1
|
+
require "#{File.dirname(__FILE__)}/../../spec/spec_helper.rb"
|
@@ -0,0 +1 @@
|
|
1
|
+
my updated test
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
Feature: Add a user to a watcher
|
3
|
+
In order to alert a user of a modified attribute value or metadata
|
4
|
+
of an ActiveRecord object
|
5
|
+
As a user
|
6
|
+
I want add myself to the list of users for that attribute that will
|
7
|
+
be notified when that value or metadata will be changed by someone
|
8
|
+
|
9
|
+
Background:
|
10
|
+
Given an ActiveRecord object instance of 'Document'
|
11
|
+
And an ActiveRecord object instance of 'User'
|
12
|
+
|
13
|
+
Scenario: creates a watcher for an attribute and add a user to its collection
|
14
|
+
Given a User "fg@fractalgarden.com"
|
15
|
+
When adding the user to the watcherslist of an attribute "name"
|
16
|
+
Then it should be created a new watcher for that field
|
17
|
+
And added a user to the list of the watcher
|
18
|
+
|
19
|
+
|
@@ -0,0 +1,90 @@
|
|
1
|
+
# encoding: UTF-8
|
2
|
+
Feature: Trigger alert on modify
|
3
|
+
In order to alert a user of a modified attribute value or metadata
|
4
|
+
of an ActiveRecord object
|
5
|
+
As a user
|
6
|
+
I want to find a new notification in my inbox when a watcher is set
|
7
|
+
on a field and a modification on it occurs
|
8
|
+
|
9
|
+
Background:
|
10
|
+
Given an ActiveRecord instance of 'Document' with 'name' equals to "pippo"
|
11
|
+
And a User "fg@fractalgarden.com" instantiated
|
12
|
+
|
13
|
+
Scenario: receive a new alert in the inbox when a save of a field value occurs
|
14
|
+
Given a watcher on the "name" field
|
15
|
+
When saving a new value "pluto" on the "name" field
|
16
|
+
Then 1 alert should be found in the inbox of the user
|
17
|
+
And should regard the "name" field
|
18
|
+
And should record the "Document" model class
|
19
|
+
And should record the "pluto" in the new_value
|
20
|
+
And should record the "pippo" in the old_value
|
21
|
+
And should record the "history_message" in the type
|
22
|
+
And should record the current_user_id in the created_by
|
23
|
+
|
24
|
+
Scenario: receive a new alert in the inbox when a note of a field is added
|
25
|
+
Given a watcher on the "name" field
|
26
|
+
When creating a new note on the "name" field with content "new note!"
|
27
|
+
Then 1 alert should be found in the inbox of the user
|
28
|
+
And should regard the "name" field
|
29
|
+
And should record the "Document" model class
|
30
|
+
And should record the "new note!" in the new_value
|
31
|
+
And should record the "" in the old_value
|
32
|
+
And should record the "note_message" in the type
|
33
|
+
And should record the current_user_id in the created_by
|
34
|
+
|
35
|
+
Scenario: receive a new alert in the inbox when a note of a field is updated
|
36
|
+
Given a watcher on the "name" field
|
37
|
+
When creating a new note on the "name" field with content "new note!"
|
38
|
+
And afterwards I update the note on the field "name" with content "updated note!"
|
39
|
+
Then 2 alert should be found in the inbox of the user
|
40
|
+
And should regard the "name" field
|
41
|
+
And should record the "Document" model class
|
42
|
+
And should record the "new note!" in the old_value
|
43
|
+
And should record the "updated note!" in the new_value
|
44
|
+
And should record the "note_message" in the type
|
45
|
+
And should record the current_user_id in the created_by
|
46
|
+
|
47
|
+
Scenario: receive a new alert in the inbox when a note of a field is deleted
|
48
|
+
Given a watcher on the "name" field
|
49
|
+
When creating a new note on the "name" field with content "new note!"
|
50
|
+
And afterwards I delete the note on the field "name"
|
51
|
+
Then 2 alert should be found in the inbox of the user
|
52
|
+
And should regard the "name" field
|
53
|
+
And should record the "Document" model class
|
54
|
+
And should record the "new note!" in the old_value
|
55
|
+
And should record the "" in the new_value
|
56
|
+
And should record the "note_message" in the type
|
57
|
+
|
58
|
+
Scenario: receive a new alert in the inbox when a attachment of a field is created
|
59
|
+
Given a watcher on the "name" field
|
60
|
+
When creating a new attachment on the "name" field with name "file.txt"
|
61
|
+
Then 1 alert should be found in the inbox of the user
|
62
|
+
And should regard the "name" field
|
63
|
+
And should record the "Document" model class
|
64
|
+
And should record the "file.txt" in the new_value
|
65
|
+
And should record the "" in the old_value
|
66
|
+
And should record the "attachment_message" in the type
|
67
|
+
And should record the current_user_id in the created_by
|
68
|
+
|
69
|
+
Scenario: receive a new alert in the inbox when a attachment of a field is updated
|
70
|
+
Given a watcher on the "name" field
|
71
|
+
When creating a new attachment on the "name" field with name "file.txt"
|
72
|
+
And updating the attachment on the "name" field with name "updated_file.txt"
|
73
|
+
Then 2 alert should be found in the inbox of the user
|
74
|
+
And should regard the "name" field
|
75
|
+
And should record the "Document" model class
|
76
|
+
And should record the "updated_file.txt" in the new_value
|
77
|
+
And should record the "file.txt" in the old_value
|
78
|
+
And should record the "attachment_message" in the type
|
79
|
+
And should record the current_user_id in the created_by
|
80
|
+
|
81
|
+
Scenario: receive a new alert in the inbox when a attachment of a field is deleted
|
82
|
+
Given a watcher on the "name" field
|
83
|
+
When creating a new attachment on the "name" field with name "file.txt"
|
84
|
+
And deleting the attachment on the "name" field with name "file.txt"
|
85
|
+
Then 2 alert should be found in the inbox of the user
|
86
|
+
And should regard the "name" field
|
87
|
+
And should record the "Document" model class
|
88
|
+
And should record the "" in the new_value
|
89
|
+
And should record the "file.txt" in the old_value
|
90
|
+
And should record the "attachment_message" in the type
|
@@ -0,0 +1,59 @@
|
|
1
|
+
module ActiveMetadata
|
2
|
+
|
3
|
+
CONFIG = File.exists?('config/active_metadata.yml') ? YAML.load_file('config/active_metadata.yml')[Rails.env] : {}
|
4
|
+
|
5
|
+
## Define ModelMethods
|
6
|
+
module Base
|
7
|
+
|
8
|
+
require 'mongoid' if ActiveMetadata::CONFIG['persists_with'] == 'mongoid'
|
9
|
+
require 'mongoid_paperclip' if ActiveMetadata::CONFIG['persists_with'] == 'mongoid'
|
10
|
+
require 'paperclip' if ActiveMetadata::CONFIG['persists_with'] == 'active_record'
|
11
|
+
require "active_metadata/persistence/persistence"
|
12
|
+
|
13
|
+
def self.included(klass)
|
14
|
+
klass.class_eval do
|
15
|
+
extend Config
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
module Config
|
20
|
+
|
21
|
+
def acts_as_metadata *args
|
22
|
+
after_save :save_history
|
23
|
+
|
24
|
+
class_variable_set("@@metadata_id_from", args.empty? ? nil : args[0][:metadata_id_from])
|
25
|
+
|
26
|
+
include ActiveMetadata::Base::InstanceMethods
|
27
|
+
include ActiveMetadata::Persistence
|
28
|
+
|
29
|
+
end
|
30
|
+
|
31
|
+
end
|
32
|
+
|
33
|
+
module InstanceMethods
|
34
|
+
|
35
|
+
def metadata_id
|
36
|
+
metadata_id_from = self.class.class_variable_get("@@metadata_id_from")
|
37
|
+
return self.id if metadata_id_from.nil?
|
38
|
+
receiver = self
|
39
|
+
metadata_id_from.each do |item|
|
40
|
+
receiver = receiver.send item
|
41
|
+
end
|
42
|
+
receiver.id
|
43
|
+
end
|
44
|
+
|
45
|
+
def current_user_id
|
46
|
+
if User.respond_to?(:current) && !User.current.nil?
|
47
|
+
User.current.id
|
48
|
+
else
|
49
|
+
nil
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
end # InstanceMethods
|
54
|
+
end
|
55
|
+
|
56
|
+
end
|
57
|
+
|
58
|
+
::ActiveRecord::Base.send :include, ActiveMetadata::Base
|
59
|
+
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module ActiveMetadata::Persistence::ActiveRecord::Attachment
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def save_attachment_for(field, file)
|
10
|
+
attachment = Attachment.create! :document_id => metadata_id, :label => field, :attach => file, :created_by => current_user_id
|
11
|
+
self.send(:send_notification, field, "", attachment.attach.original_filename, :attachment_message, current_user_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def attachments_for(field)
|
15
|
+
Attachment.all(:conditions => {:document_id => metadata_id,:label => field}, :order => "attach_updated_at DESC")
|
16
|
+
end
|
17
|
+
|
18
|
+
def delete_attachment_for(field,id)
|
19
|
+
a = Attachment.find(id)
|
20
|
+
filename = a.attach.original_filename
|
21
|
+
a.destroy
|
22
|
+
self.send(:send_notification, field, filename, "", :attachment_message)
|
23
|
+
end
|
24
|
+
|
25
|
+
def update_attachment_for(field, id, newfile)
|
26
|
+
a = Attachment.find(id)
|
27
|
+
old_filename = a.attach.original_filename
|
28
|
+
a.attach = newfile
|
29
|
+
a.updated_by = current_user_id
|
30
|
+
a.save
|
31
|
+
new_filename = a.attach.original_filename
|
32
|
+
|
33
|
+
self.send(:send_notification, field, old_filename, new_filename, :attachment_message, current_user_id)
|
34
|
+
end
|
35
|
+
|
36
|
+
def has_attachments_for field
|
37
|
+
Attachment.count(:conditions => {:label => field, :document_id => metadata_id}) == 0 ? false : true
|
38
|
+
end
|
39
|
+
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module ActiveMetadata::Persistence::ActiveRecord::History
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def save_history
|
10
|
+
self.changes.each do |key, value|
|
11
|
+
next if ActiveMetadata::CONFIG['history_skip_fields'].include?(key)
|
12
|
+
History.create! :value => value[1],:document_id => metadata_id,:label => key.to_s, :created_by => current_user_id
|
13
|
+
self.send(:send_notification, key, value[0], value[1], :history_message,current_user_id)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def history_for field
|
18
|
+
History.all(:conditions => {:document_id => metadata_id,:label => field}, :order => "created_at DESC")
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveMetadata::Persistence::ActiveRecord::Note
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def create_note_for(field, note)
|
10
|
+
Note.create! :document_id => metadata_id,:label => field.to_s,:note => note, :created_by => current_user_id
|
11
|
+
self.send(:send_notification, field, "", note, :note_message, current_user_id)
|
12
|
+
end
|
13
|
+
|
14
|
+
def update_note(id, note)
|
15
|
+
n = Note.find(id)
|
16
|
+
old_value = n.note
|
17
|
+
n.update_attributes! :note => note, :updated_by => current_user_id, :updated_at => Time.now.utc
|
18
|
+
|
19
|
+
self.send(:send_notification, n.label, old_value, note, :note_message, current_user_id)
|
20
|
+
end
|
21
|
+
|
22
|
+
def notes_for(field)
|
23
|
+
Note.all(:conditions => {:label => field, :document_id => metadata_id}, :order => "updated_at DESC" )
|
24
|
+
end
|
25
|
+
|
26
|
+
def note_for(field,id)
|
27
|
+
Note.find(id)
|
28
|
+
end
|
29
|
+
|
30
|
+
def create_notes_for(field,notes)
|
31
|
+
notes.each { |note| create_note_for field, note }
|
32
|
+
end
|
33
|
+
|
34
|
+
def delete_note_for(field,id)
|
35
|
+
n = Note.find(id)
|
36
|
+
old_value = n.note
|
37
|
+
n.destroy
|
38
|
+
self.send(:send_notification, field, old_value, "", :note_message)
|
39
|
+
end
|
40
|
+
|
41
|
+
def has_notes_for field
|
42
|
+
Note.count(:conditions => {:label => field, :document_id => metadata_id}) == 0 ? false : true
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveMetadata::Persistence::ActiveRecord::Watcher
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
def create_watcher_for(field, owner)
|
9
|
+
raise RuntimeError, "The object id MUST be valued" unless self.id
|
10
|
+
Watcher.create! :document_id => metadata_id, :label => field, :owner_id => owner.id
|
11
|
+
end
|
12
|
+
|
13
|
+
def watchers_for(field)
|
14
|
+
Watcher.all(:conditions => {:label => field, :document_id => metadata_id})
|
15
|
+
end
|
16
|
+
|
17
|
+
def delete_watcher_for(field, owner)
|
18
|
+
Watcher.where(:document_id => metadata_id, :label => field, :owner_id => owner.id).each do |watcher|
|
19
|
+
watcher.destroy
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def is_watched_by(field,owner)
|
24
|
+
Watcher.where(:document_id => metadata_id, :label => field, :owner_id => owner.id).empty? ? false : true
|
25
|
+
end
|
26
|
+
|
27
|
+
def send_notification(field, old_value, new_value, type=:default_message, created_by=nil)
|
28
|
+
watchers_for(field).each { |watch| notify_changes(field, old_value, new_value, self.class.to_s, self.id, watch.owner_id, type, created_by) }
|
29
|
+
end
|
30
|
+
|
31
|
+
def notifier
|
32
|
+
@notifier
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
def notify_changes(matched_label, old_value, new_value, model_class, model_id, owner_id, type, created_by)
|
37
|
+
raise "A watcher notifier class must be implemented" unless WatcherNotifier
|
38
|
+
|
39
|
+
@notifier = WatcherNotifier.new
|
40
|
+
@notifier.notify(matched_label.to_s, old_value, new_value, model_class, model_id,owner_id,type, created_by)
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveMetadata::Persistence::ActiveRecord
|
2
|
+
|
3
|
+
require "model/active_record/note"
|
4
|
+
require "model/active_record/history"
|
5
|
+
require "model/active_record/watcher"
|
6
|
+
require "model/active_record/attachment"
|
7
|
+
|
8
|
+
require "active_metadata/persistence/active_record/note"
|
9
|
+
require "active_metadata/persistence/active_record/history"
|
10
|
+
require "active_metadata/persistence/active_record/watcher"
|
11
|
+
require "active_metadata/persistence/active_record/attachment"
|
12
|
+
|
13
|
+
def self.included(receiver)
|
14
|
+
receiver.send :include, InstanceMethods
|
15
|
+
end
|
16
|
+
|
17
|
+
module InstanceMethods
|
18
|
+
|
19
|
+
include ActiveMetadata::Persistence::ActiveRecord::Note
|
20
|
+
include ActiveMetadata::Persistence::ActiveRecord::History
|
21
|
+
include ActiveMetadata::Persistence::ActiveRecord::Watcher
|
22
|
+
include ActiveMetadata::Persistence::ActiveRecord::Attachment
|
23
|
+
|
24
|
+
end
|
25
|
+
|
26
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module ActiveMetadata::Persistence::Mongoid::Attachment
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def save_attachment_for(field, file)
|
10
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s)
|
11
|
+
counter = label.attachments.count > 0 ? label.attachments.last.counter : 0
|
12
|
+
attachment = Attachment.new(:attach => file, :counter => (counter + 1))
|
13
|
+
label.attachments << attachment
|
14
|
+
label.save
|
15
|
+
|
16
|
+
self.send(:send_notification, field, "", attachment.attach.original_filename)
|
17
|
+
end
|
18
|
+
|
19
|
+
def attachments_for(field)
|
20
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s)
|
21
|
+
label.attachments.desc(:attach_updated_at).to_a
|
22
|
+
end
|
23
|
+
|
24
|
+
def delete_attachment_for(field,id)
|
25
|
+
a = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s).attachments.find(id)
|
26
|
+
filename = a.attach.original_filename
|
27
|
+
a.destroy
|
28
|
+
|
29
|
+
self.send(:send_notification, field, filename, "")
|
30
|
+
end
|
31
|
+
|
32
|
+
def update_attachment_for(field, id, newfile)
|
33
|
+
a = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s).attachments.find(id)
|
34
|
+
old_filename = a.attach.original_filename
|
35
|
+
a.attach = newfile
|
36
|
+
a.save
|
37
|
+
new_filename = a.attach.original_filename
|
38
|
+
|
39
|
+
self.send(:send_notification, field, old_filename, new_filename)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
43
|
+
|
44
|
+
end
|
45
|
+
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module ActiveMetadata::Persistence::Mongoid::History
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def save_history
|
10
|
+
self.changes.each do |key, value|
|
11
|
+
next if ActiveMetadata::CONFIG['history_skip_fields'].include?(key)
|
12
|
+
|
13
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => key.to_s)
|
14
|
+
label.histories.create!(:value => value[1], :created_at => Time.now.utc)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
def history_for field
|
19
|
+
meta = ActiveMeta.find_or_create_by(:document_id => metadata_id)
|
20
|
+
|
21
|
+
label = meta.labels.find_or_create_by(:name => field.to_s)
|
22
|
+
label.histories.desc(:created_at).to_a
|
23
|
+
end
|
24
|
+
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
module ActiveMetadata::Persistence::Mongoid::Note
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
|
9
|
+
def create_note_for(field, note, created_by=nil)
|
10
|
+
raise RuntimeError, "The object id MUST be valued" unless self.id
|
11
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s)
|
12
|
+
label.notes.create!(:note => note, :created_by => created_by, :created_at => Time.now.utc, :updated_at => Time.now.utc)
|
13
|
+
|
14
|
+
# BEWARE: I'm not checking the send_notification method existence
|
15
|
+
# this notification should be asynch
|
16
|
+
self.send(:send_notification, field, "", note)
|
17
|
+
end
|
18
|
+
|
19
|
+
def update_note(id, note, updated_by=nil)
|
20
|
+
n = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => 'name').notes.find id
|
21
|
+
old_value = n.note
|
22
|
+
n.update_attributes :note => note, :updated_by => updated_by, :updated_at => Time.now.utc
|
23
|
+
|
24
|
+
self.send(:send_notification, n.label, old_value, note)
|
25
|
+
end
|
26
|
+
|
27
|
+
def notes_for(field)
|
28
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s)
|
29
|
+
label.notes.desc(:updated_at).to_a
|
30
|
+
end
|
31
|
+
|
32
|
+
def note_for(field,id)
|
33
|
+
label = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s)
|
34
|
+
label.notes.find(id)
|
35
|
+
end
|
36
|
+
|
37
|
+
def create_notes_for(field,notes)
|
38
|
+
notes.each { |note| create_note_for field, note }
|
39
|
+
end
|
40
|
+
|
41
|
+
def delete_note_for(field,id)
|
42
|
+
n = ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field.to_s).notes.find(id)
|
43
|
+
old_value = n.note
|
44
|
+
n.destroy
|
45
|
+
self.send(:send_notification, field, old_value, "")
|
46
|
+
end
|
47
|
+
end
|
48
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module ActiveMetadata::Persistence::Mongoid::Watcher
|
2
|
+
|
3
|
+
def self.included(receiver)
|
4
|
+
receiver.send :include, InstanceMethods
|
5
|
+
end
|
6
|
+
|
7
|
+
module InstanceMethods
|
8
|
+
def create_watcher_for(field, owner)
|
9
|
+
raise RuntimeError, "The object id MUST be valued" unless self.id
|
10
|
+
|
11
|
+
label_path(field).watchers.create!(:owner_id => owner.id, :created_at => Time.now.utc, :updated_at => Time.now.utc)
|
12
|
+
|
13
|
+
owner.create_inbox unless owner.inbox # ensure that an inbox is present
|
14
|
+
end
|
15
|
+
|
16
|
+
def watchers_for(field)
|
17
|
+
label_path(field).watchers.asc(:created_at).to_a
|
18
|
+
end
|
19
|
+
|
20
|
+
def delete_watcher_for(field, owner)
|
21
|
+
#TODO
|
22
|
+
end
|
23
|
+
|
24
|
+
def is_watched_by(field,owner)
|
25
|
+
#TODO
|
26
|
+
end
|
27
|
+
|
28
|
+
# This is a callback method of the after_save of the ActiveRecord
|
29
|
+
# object.
|
30
|
+
# TODO: It should definetly be decoupled in time from the save of
|
31
|
+
# the alerting system
|
32
|
+
def on_save_watcher_callback
|
33
|
+
self.changes.each do |field, values|
|
34
|
+
send_notification(field, values.first, values.last)
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def send_notification(field, old_value, new_value)
|
39
|
+
watchers_for(field).each { |watch| watch.notify_changes(field, old_value, new_value, self.class, self.id) }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module ActiveMetadata::Persistence::Mongoid
|
2
|
+
|
3
|
+
require "active_metadata/persistence/mongoid/attachment"
|
4
|
+
require "active_metadata/persistence/mongoid/note"
|
5
|
+
require "active_metadata/persistence/mongoid/history"
|
6
|
+
require "active_metadata/persistence/mongoid/watcher"
|
7
|
+
require "model/mongoid/active_meta"
|
8
|
+
require "model/mongoid/label"
|
9
|
+
require "model/mongoid/note"
|
10
|
+
require "model/mongoid/history"
|
11
|
+
require "model/mongoid/attachment"
|
12
|
+
require "model/mongoid/watcher"
|
13
|
+
|
14
|
+
def self.included(receiver)
|
15
|
+
receiver.send :include, InstanceMethods
|
16
|
+
end
|
17
|
+
|
18
|
+
module InstanceMethods
|
19
|
+
|
20
|
+
include ActiveMetadata::Persistence::Mongoid::Note
|
21
|
+
include ActiveMetadata::Persistence::Mongoid::History
|
22
|
+
include ActiveMetadata::Persistence::Mongoid::Attachment
|
23
|
+
include ActiveMetadata::Persistence::Mongoid::Watcher
|
24
|
+
|
25
|
+
def label_path(field_name)
|
26
|
+
ActiveMeta.find_or_create_by(:document_id => metadata_id).labels.find_or_create_by(:name => field_name.to_s)
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module ActiveMetadata::Persistence
|
2
|
+
|
3
|
+
PERSISTS_WITH = ActiveMetadata::CONFIG['persists_with']
|
4
|
+
|
5
|
+
require "active_metadata/persistence/mongoid" if PERSISTS_WITH == 'mongoid'
|
6
|
+
require "active_metadata/persistence/active_record" if PERSISTS_WITH == 'active_record'
|
7
|
+
|
8
|
+
def self.included(receiver)
|
9
|
+
persister = PERSISTS_WITH == 'active_record' ? ActiveMetadata::Persistence::ActiveRecord : ActiveMetadata::Persistence::Mongoid
|
10
|
+
receiver.send :include, persister
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|