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.
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