active_metadata 0.0.2 → 0.1.9
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/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
|