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.
Files changed (90) hide show
  1. data/app/controllers/active_metadata/attachments_controller.rb +47 -0
  2. data/app/controllers/active_metadata/histories_controller.rb +16 -0
  3. data/app/controllers/active_metadata/notes_controller.rb +61 -0
  4. data/app/controllers/active_metadata/watchers_controller.rb +34 -0
  5. data/app/helpers/application_helper.rb +2 -0
  6. data/app/views/active_metadata/attachments/index.html.erb +11 -0
  7. data/app/views/active_metadata/histories/index.html.erb +5 -0
  8. data/app/views/active_metadata/notes/_form.html.erb +23 -0
  9. data/app/views/active_metadata/notes/edit.html.erb +8 -0
  10. data/app/views/active_metadata/notes/index.html.erb +11 -0
  11. data/app/views/active_metadata/notes/index.js.erb +1 -0
  12. data/app/views/active_metadata/notes/show.html.erb +9 -0
  13. data/app/views/active_metadata/watchers/create.js.erb +1 -0
  14. data/app/views/active_metadata/watchers/destroy.js.erb +1 -0
  15. data/app/views/active_metadata/watchers/index.html.erb +5 -0
  16. data/config/active_metadata.yml +17 -0
  17. data/config/application.rb +0 -0
  18. data/config/database.yml +11 -0
  19. data/config/initializers/inflections.rb +7 -0
  20. data/config/mongoid.yml +28 -0
  21. data/config/routes.rb +30 -0
  22. data/db/development.sqlite3 +0 -0
  23. data/db/migrate/001_create_document.rb +12 -0
  24. data/db/migrate/002_add_surname_to_document.rb +9 -0
  25. data/db/migrate/003_create_section.rb +13 -0
  26. data/db/migrate/004_create_user.rb +14 -0
  27. data/db/migrate/005_create_inboxes.rb +19 -0
  28. data/db/migrate/006_create_alert_message.rb +37 -0
  29. data/db/migrate/007_create_notes.rb +22 -0
  30. data/db/migrate/008_create_history.rb +20 -0
  31. data/db/migrate/009_create_watcher.rb +21 -0
  32. data/db/migrate/010_create_attachment.rb +26 -0
  33. data/db/migrate/011_add_created_by_to_histories.rb +10 -0
  34. data/db/test.sqlite3 +0 -0
  35. data/features/step_definitions/add_a_user_to_a_watcher_steps.rb +29 -0
  36. data/features/step_definitions/trigger_alert_on_modify_steps.rb +86 -0
  37. data/features/supports/file.txt +1 -0
  38. data/features/supports/initializer.rb +1 -0
  39. data/features/supports/updated_file.txt +1 -0
  40. data/features/watchlist/add_a_user_to_a_watcher.feature +19 -0
  41. data/features/watchlist/trigger_alert_on_modify.feature +90 -0
  42. data/lib/active_metadata/base.rb +59 -0
  43. data/lib/active_metadata/persistence/active_record/attachment.rb +42 -0
  44. data/lib/active_metadata/persistence/active_record/history.rb +22 -0
  45. data/lib/active_metadata/persistence/active_record/note.rb +45 -0
  46. data/lib/active_metadata/persistence/active_record/watcher.rb +45 -0
  47. data/lib/active_metadata/persistence/active_record.rb +26 -0
  48. data/lib/active_metadata/persistence/mongoid/attachment.rb +45 -0
  49. data/lib/active_metadata/persistence/mongoid/history.rb +26 -0
  50. data/lib/active_metadata/persistence/mongoid/note.rb +48 -0
  51. data/lib/active_metadata/persistence/mongoid/watcher.rb +43 -0
  52. data/lib/active_metadata/persistence/mongoid.rb +30 -0
  53. data/lib/active_metadata/persistence/persistence.rb +13 -0
  54. data/lib/active_metadata/railtie.rb +6 -0
  55. data/lib/active_metadata/version.rb +1 -1
  56. data/lib/active_metadata.rb +6 -12
  57. data/lib/application_controller.rb +28 -0
  58. data/lib/application_helper.rb +7 -0
  59. data/lib/engine.rb +29 -0
  60. data/lib/model/active_record/attachment.rb +18 -0
  61. data/lib/model/active_record/history.rb +2 -0
  62. data/lib/model/active_record/note.rb +2 -0
  63. data/lib/model/active_record/watcher.rb +4 -0
  64. data/lib/model/mongoid/active_meta.rb +6 -0
  65. data/lib/model/mongoid/attachment.rb +25 -0
  66. data/lib/model/mongoid/history.rb +9 -0
  67. data/lib/model/mongoid/label.rb +14 -0
  68. data/lib/model/mongoid/note.rb +10 -0
  69. data/lib/model/mongoid/watcher.rb +24 -0
  70. data/lib/rails/railties/tasks.rake +8 -0
  71. data/lib/rake/active_record_tasks.rb +77 -0
  72. data/lib/rake/task.rb +18 -0
  73. data/lib/templates/active_metadata.yml +17 -0
  74. data/lib/templates/active_metadata_migrations +67 -0
  75. data/lib/templates/mongoid.yml +20 -0
  76. data/spec/active_metadata_spec.rb +596 -0
  77. data/spec/benchmark_spec.rb +35 -0
  78. data/spec/controllers/metadata_controller_spec.rb +14 -0
  79. data/spec/spec_helper.rb +87 -0
  80. data/spec/support/document.rb +8 -0
  81. data/spec/support/pdf_test.pdf +0 -0
  82. data/spec/support/pdf_test_2.pdf +0 -0
  83. data/spec/support/section.rb +8 -0
  84. data/spec/support/user.rb +13 -0
  85. data/spec/support/watcher_notifier.rb +21 -0
  86. metadata +201 -19
  87. data/.gitignore +0 -4
  88. data/Gemfile +0 -4
  89. data/Rakefile +0 -1
  90. 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
@@ -0,0 +1,6 @@
1
+ require 'rails'
2
+ class Railtie < Rails::Railtie
3
+ rake_tasks do
4
+ require_relative '../rake/task.rb'
5
+ end
6
+ end