active_metadata 0.2.2 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/db/migrate/01_create_test_resources.rb +30 -0
- data/db/migrate/02_active_metadata_migrations.rb +71 -0
- data/db/test.sqlite3 +0 -0
- data/lib/active_metadata/base.rb +73 -16
- data/lib/active_metadata/helpers.rb +9 -0
- data/lib/active_metadata/persistence/active_record/history.rb +4 -4
- data/lib/active_metadata/version.rb +1 -1
- data/spec/concurrency_spec.rb +105 -0
- metadata +25 -38
- data/db/development.sqlite3 +0 -0
- data/db/migrate/001_create_document.rb +0 -12
- data/db/migrate/002_add_surname_to_document.rb +0 -9
- data/db/migrate/003_create_section.rb +0 -13
- data/db/migrate/004_create_user.rb +0 -14
- data/db/migrate/005_create_inboxes.rb +0 -19
- data/db/migrate/006_create_alert_message.rb +0 -37
- data/db/migrate/007_create_notes.rb +0 -22
- data/db/migrate/008_create_history.rb +0 -20
- data/db/migrate/009_create_watcher.rb +0 -21
- data/db/migrate/010_create_attachment.rb +0 -26
- data/db/migrate/011_add_created_by_to_histories.rb +0 -10
- data/lib/model/mongoid/active_meta.rb +0 -6
- data/lib/model/mongoid/attachment.rb +0 -25
- data/lib/model/mongoid/history.rb +0 -9
- data/lib/model/mongoid/label.rb +0 -14
- data/lib/model/mongoid/note.rb +0 -10
- data/lib/model/mongoid/watcher.rb +0 -24
@@ -0,0 +1,30 @@
|
|
1
|
+
class CreateTestResources < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
create_table :documents do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :surname
|
6
|
+
t.boolean :keep_alive
|
7
|
+
t.timestamps
|
8
|
+
end
|
9
|
+
|
10
|
+
create_table :sections do |t|
|
11
|
+
t.string :title
|
12
|
+
t.integer :document_id
|
13
|
+
t.timestamps
|
14
|
+
end
|
15
|
+
|
16
|
+
create_table :users do |t|
|
17
|
+
t.string :email
|
18
|
+
t.string :firstname
|
19
|
+
t.string :lastname
|
20
|
+
t.timestamps
|
21
|
+
end
|
22
|
+
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.down
|
26
|
+
drop_table :documents
|
27
|
+
drop_table :sections
|
28
|
+
drop_table :users
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
class ActiveMetadataMigrations < ActiveRecord::Migration
|
2
|
+
def self.up
|
3
|
+
|
4
|
+
create_table :notes do |t|
|
5
|
+
t.text :note
|
6
|
+
t.string :label
|
7
|
+
t.string :document_class
|
8
|
+
t.integer :document_id
|
9
|
+
t.integer :created_by
|
10
|
+
t.integer :updated_by
|
11
|
+
t.timestamps
|
12
|
+
end
|
13
|
+
|
14
|
+
add_index :notes, :document_id
|
15
|
+
add_index :notes, :label
|
16
|
+
add_index :notes, :updated_at
|
17
|
+
|
18
|
+
create_table :histories do |t|
|
19
|
+
t.text :value
|
20
|
+
t.string :label
|
21
|
+
t.string :document_class
|
22
|
+
t.integer :document_id
|
23
|
+
t.integer :created_by
|
24
|
+
t.timestamps
|
25
|
+
end
|
26
|
+
|
27
|
+
add_index :histories, :document_id
|
28
|
+
add_index :histories, :label
|
29
|
+
add_index :histories, :created_at
|
30
|
+
|
31
|
+
create_table :attachments do |t|
|
32
|
+
t.string :label
|
33
|
+
t.integer :document_id
|
34
|
+
t.string :document_class
|
35
|
+
t.integer :created_by
|
36
|
+
t.integer :updated_by
|
37
|
+
t.integer :counter
|
38
|
+
t.string :attach_file_name
|
39
|
+
t.string :attach_content_type
|
40
|
+
t.integer :attach_file_size
|
41
|
+
t.datetime :attach_updated_at
|
42
|
+
t.timestamps
|
43
|
+
end
|
44
|
+
|
45
|
+
add_index :attachments, :document_id
|
46
|
+
add_index :attachments, :label
|
47
|
+
add_index :attachments, :attach_updated_at
|
48
|
+
|
49
|
+
create_table :watchers do |t|
|
50
|
+
t.integer :owner_id
|
51
|
+
t.string :label
|
52
|
+
t.string :document_class
|
53
|
+
t.integer :document_id
|
54
|
+
t.timestamps
|
55
|
+
end
|
56
|
+
|
57
|
+
add_index :watchers, :document_id
|
58
|
+
add_index :watchers, :label
|
59
|
+
add_index :watchers, :owner_id
|
60
|
+
add_index :watchers, :created_at
|
61
|
+
|
62
|
+
end
|
63
|
+
|
64
|
+
def self.down
|
65
|
+
drop_table :notes
|
66
|
+
drop_table :histories
|
67
|
+
drop_table :attachments
|
68
|
+
drop_table :watchers
|
69
|
+
end
|
70
|
+
|
71
|
+
end
|
data/db/test.sqlite3
CHANGED
Binary file
|
data/lib/active_metadata/base.rb
CHANGED
@@ -2,12 +2,13 @@ module ActiveMetadata
|
|
2
2
|
|
3
3
|
CONFIG = File.exists?('config/active_metadata.yml') ? YAML.load_file('config/active_metadata.yml')[Rails.env] : {}
|
4
4
|
CONFIG['cache_expires_in'] ||= 60
|
5
|
-
|
5
|
+
|
6
6
|
## Define ModelMethods
|
7
7
|
module Base
|
8
|
-
|
8
|
+
|
9
9
|
require 'paperclip'
|
10
10
|
require "active_metadata/persistence/persistence"
|
11
|
+
require "active_metadata/helpers"
|
11
12
|
|
12
13
|
def self.included(klass)
|
13
14
|
klass.class_eval do
|
@@ -19,24 +20,26 @@ module ActiveMetadata
|
|
19
20
|
|
20
21
|
def acts_as_metadata *args
|
21
22
|
after_save :save_history
|
22
|
-
|
23
|
+
|
23
24
|
class_variable_set("@@metadata_id_from", args.empty? ? nil : args[0][:metadata_id_from])
|
24
25
|
|
25
26
|
include ActiveMetadata::Base::InstanceMethods
|
26
|
-
include ActiveMetadata::Persistence
|
27
|
-
|
27
|
+
include ActiveMetadata::Persistence
|
28
|
+
|
28
29
|
end
|
29
30
|
|
30
31
|
end
|
31
32
|
|
32
33
|
module InstanceMethods
|
33
|
-
|
34
|
+
|
35
|
+
include ActiveMetadata::Helpers
|
36
|
+
|
34
37
|
def self.included(klass)
|
35
|
-
[:notes
|
36
|
-
klass.send(:define_method,"#{item.to_s}_cache_key".to_sym) do |field|
|
37
|
-
"#{Rails.env}/active_metadata/#{item.to_s}/#{self.class}/#{metadata_id}/#{field}/"
|
38
|
-
end
|
39
|
-
end
|
38
|
+
[:notes, :attachments, :history].each do |item|
|
39
|
+
klass.send(:define_method, "#{item.to_s}_cache_key".to_sym) do |field|
|
40
|
+
"#{Rails.env}/active_metadata/#{item.to_s}/#{self.class}/#{metadata_id}/#{field}/"
|
41
|
+
end
|
42
|
+
end
|
40
43
|
end
|
41
44
|
|
42
45
|
def metadata_id
|
@@ -48,16 +51,70 @@ module ActiveMetadata
|
|
48
51
|
end
|
49
52
|
receiver.id
|
50
53
|
end
|
51
|
-
|
54
|
+
|
52
55
|
def current_user_id
|
53
56
|
if User.respond_to?(:current) && !User.current.nil?
|
54
|
-
|
57
|
+
User.current.id
|
55
58
|
else
|
56
59
|
nil
|
57
|
-
end
|
58
|
-
end
|
59
|
-
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Resolve concurrency using the passed timestamps and the active_metadata histories
|
64
|
+
# To be called from controller before updating the model. Params that contains a conflict are removed from the params list.
|
65
|
+
# Returns 2 values containing the the deleted params with the related history:
|
66
|
+
# [{:key => [passed_value,history]}]
|
67
|
+
#
|
68
|
+
# first result is the WARNINGS array: conflict appears on a field not touched by the user that submit the value
|
69
|
+
# first result is the FATALS Array : if the conflict appears on a field modified by the user that submit the value
|
70
|
+
# an empty array is returned by default
|
71
|
+
def manage_concurrency(params, timestamp)
|
72
|
+
warnings = []
|
73
|
+
fatals = []
|
74
|
+
|
75
|
+
# scan params
|
76
|
+
params.each do |key, val|
|
77
|
+
# ensure the query order
|
78
|
+
histories = history_for key.to_sym, "created_at DESC"
|
79
|
+
latest_history = histories.first
|
80
|
+
|
81
|
+
# if form timestamp is subsequent the history last change go on
|
82
|
+
# if history does not exists yet go on
|
83
|
+
next if latest_history.nil? || timestamp > latest_history.created_at
|
84
|
+
|
85
|
+
#if the timestamp is previous of the last history change
|
86
|
+
if timestamp < latest_history.created_at
|
87
|
+
#remove the key from the update process
|
88
|
+
params.delete key
|
89
|
+
|
90
|
+
# We have a conflict.
|
91
|
+
# Check if the actual submission has been modified
|
92
|
+
histories.each do |h|
|
93
|
+
# Looking for the value that was loaded by the user. First history with a ts that is younger than the form ts
|
94
|
+
next if timestamp > h.created_at
|
95
|
+
|
96
|
+
# History stores values as strings so any boolean is stored as "0" or "1"
|
97
|
+
# We need to translate the params passed for a safer comparison.
|
98
|
+
if self.column_for_attribute(key).type == :boolean
|
99
|
+
b_val = to_bool(h.value)
|
100
|
+
end
|
101
|
+
|
102
|
+
if [h.value, b_val].include? val
|
103
|
+
warnings << {key => [val, h]}
|
104
|
+
else
|
105
|
+
fatals << {key => [val, h]}
|
106
|
+
end
|
107
|
+
end
|
108
|
+
|
109
|
+
end
|
110
|
+
|
111
|
+
end
|
112
|
+
|
113
|
+
return warnings, fatals
|
114
|
+
end
|
115
|
+
|
60
116
|
end # InstanceMethods
|
117
|
+
|
61
118
|
end
|
62
119
|
|
63
120
|
end
|
@@ -0,0 +1,9 @@
|
|
1
|
+
module ActiveMetadata::Helpers
|
2
|
+
|
3
|
+
def to_bool str
|
4
|
+
return true if str == true || str =~ (/(true|t|yes|y|1)$/i)
|
5
|
+
return false if str == false || str.blank? || str =~ (/(false|f|no|n|0)$/i)
|
6
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{str}\"")
|
7
|
+
end
|
8
|
+
|
9
|
+
end
|
@@ -15,9 +15,9 @@ module ActiveMetadata::Persistence::ActiveRecord::History
|
|
15
15
|
end
|
16
16
|
end
|
17
17
|
|
18
|
-
def history_for field
|
18
|
+
def history_for field, order="created_at DESC"
|
19
19
|
Rails.cache.fetch(history_cache_key(field), :expires_in => ActiveMetadata::CONFIG['cache_expires_in'].minutes) do
|
20
|
-
fetch_histories_for field
|
20
|
+
fetch_histories_for field, order
|
21
21
|
end
|
22
22
|
end
|
23
23
|
|
@@ -27,8 +27,8 @@ module ActiveMetadata::Persistence::ActiveRecord::History
|
|
27
27
|
Rails.cache.delete history_cache_key(field)
|
28
28
|
end
|
29
29
|
|
30
|
-
def fetch_histories_for field
|
31
|
-
History.all(:conditions => {:document_id => metadata_id,:label => field}, :order =>
|
30
|
+
def fetch_histories_for field, order
|
31
|
+
History.all(:conditions => {:document_id => metadata_id,:label => field}, :order => order)
|
32
32
|
end
|
33
33
|
|
34
34
|
|
@@ -0,0 +1,105 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Manage Concurrency" do
|
4
|
+
|
5
|
+
before(:each) do
|
6
|
+
@document = Document.create! { |d| d.name = "John" }
|
7
|
+
@document.reload
|
8
|
+
end
|
9
|
+
|
10
|
+
describe "when a field is modified and the form ts is subsequent of the history ts" do
|
11
|
+
|
12
|
+
it "should save the new value and history must be updated with the latest change" do
|
13
|
+
sleep 0.2.seconds
|
14
|
+
|
15
|
+
params = {:name => "nuovo nome"}
|
16
|
+
warn,fatal = @document.manage_concurrency params,Time.now
|
17
|
+
@document.update_attributes(params)
|
18
|
+
|
19
|
+
warn.should be_empty
|
20
|
+
fatal.should be_empty
|
21
|
+
hs = @document.history_for(:name)
|
22
|
+
hs.count.should eq 2
|
23
|
+
hs.first.value.should eq "nuovo nome"
|
24
|
+
Document.last.name.should eq "nuovo nome"
|
25
|
+
end
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
describe "when a field is modified and the form ts is preceding the history ts" do
|
30
|
+
|
31
|
+
it "should not change the model value and the history if the newest history value is equal to the submitted once, param should be retuned as warning" do
|
32
|
+
form_timestamp = Time.now
|
33
|
+
params = {:name => "nuovo nome"}
|
34
|
+
|
35
|
+
#someone change the field value
|
36
|
+
sleep 0.2.seconds
|
37
|
+
warn,fatal = @document.manage_concurrency params,Time.now
|
38
|
+
@document.update_attributes(params)
|
39
|
+
|
40
|
+
# user submit pushing the same value that was already saved by another user
|
41
|
+
sleep 0.2.seconds
|
42
|
+
warn,fatal = @document.manage_concurrency params,form_timestamp
|
43
|
+
@document.update_attributes(params)
|
44
|
+
|
45
|
+
warn.size.should eq 1
|
46
|
+
warn[0][:name][0].should eq "nuovo nome"
|
47
|
+
fatal.should be_empty
|
48
|
+
hs = @document.history_for(:name)
|
49
|
+
#last change shoudl not be recorded in history
|
50
|
+
hs.count.should eq 2
|
51
|
+
hs.first.value.should eq "nuovo nome"
|
52
|
+
Document.last.name.should eq "nuovo nome"
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
it "should reject the change if the history newest value is different from the submitted once, param should be returned as fatal" do
|
57
|
+
form_timestamp = Time.now
|
58
|
+
params = {:name => "nuovo nome"}
|
59
|
+
|
60
|
+
#someone change the field value
|
61
|
+
sleep 0.2.seconds
|
62
|
+
warn,fatal = @document.manage_concurrency params,Time.now
|
63
|
+
@document.update_attributes(params)
|
64
|
+
|
65
|
+
# user submit a new value
|
66
|
+
sleep 0.2.seconds
|
67
|
+
different_params = {:name => "altro nome"}
|
68
|
+
warn,fatal = @document.manage_concurrency different_params,form_timestamp
|
69
|
+
@document.update_attributes(different_params)
|
70
|
+
|
71
|
+
fatal.size.should eq 1
|
72
|
+
fatal[0][:name][0].should eq "altro nome"
|
73
|
+
warn.should be_empty
|
74
|
+
hs = @document.history_for(:name)
|
75
|
+
#last change shoudl not be recorded in history
|
76
|
+
hs.count.should eq 2
|
77
|
+
hs.first.value.should eq "nuovo nome"
|
78
|
+
Document.last.name.should eq "nuovo nome"
|
79
|
+
|
80
|
+
end
|
81
|
+
|
82
|
+
it "should return both fatals and warnings if required" do
|
83
|
+
form_timestamp = Time.now
|
84
|
+
params = {:name => "nuovo nome", :keep_alive => false}
|
85
|
+
|
86
|
+
#someone change the field value
|
87
|
+
sleep 0.2.seconds
|
88
|
+
warn,fatal = @document.manage_concurrency params,Time.now
|
89
|
+
@document.update_attributes(params)
|
90
|
+
|
91
|
+
# user submit a new value
|
92
|
+
sleep 0.2.seconds
|
93
|
+
different_params = {:name => "altro nome", :keep_alive => false}
|
94
|
+
warn,fatal = @document.manage_concurrency different_params,form_timestamp
|
95
|
+
@document.update_attributes(different_params)
|
96
|
+
|
97
|
+
fatal.size.should eq 1
|
98
|
+
fatal[0][:name][0].should eq "altro nome"
|
99
|
+
warn.size.should eq 1
|
100
|
+
warn[0][:keep_alive][0].should eq false
|
101
|
+
end
|
102
|
+
|
103
|
+
end
|
104
|
+
|
105
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: active_metadata
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.2.
|
4
|
+
version: 0.2.3
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -10,11 +10,11 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2011-10-
|
13
|
+
date: 2011-10-19 00:00:00.000000000Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: rspec-rails
|
17
|
-
requirement: &
|
17
|
+
requirement: &2168675080 !ruby/object:Gem::Requirement
|
18
18
|
none: false
|
19
19
|
requirements:
|
20
20
|
- - ! '>='
|
@@ -22,10 +22,10 @@ dependencies:
|
|
22
22
|
version: '0'
|
23
23
|
type: :development
|
24
24
|
prerelease: false
|
25
|
-
version_requirements: *
|
25
|
+
version_requirements: *2168675080
|
26
26
|
- !ruby/object:Gem::Dependency
|
27
27
|
name: sqlite3
|
28
|
-
requirement: &
|
28
|
+
requirement: &2168674400 !ruby/object:Gem::Requirement
|
29
29
|
none: false
|
30
30
|
requirements:
|
31
31
|
- - ! '>='
|
@@ -33,10 +33,10 @@ dependencies:
|
|
33
33
|
version: '0'
|
34
34
|
type: :development
|
35
35
|
prerelease: false
|
36
|
-
version_requirements: *
|
36
|
+
version_requirements: *2168674400
|
37
37
|
- !ruby/object:Gem::Dependency
|
38
38
|
name: sqlite3-ruby
|
39
|
-
requirement: &
|
39
|
+
requirement: &2168673660 !ruby/object:Gem::Requirement
|
40
40
|
none: false
|
41
41
|
requirements:
|
42
42
|
- - ! '>='
|
@@ -44,10 +44,10 @@ dependencies:
|
|
44
44
|
version: '0'
|
45
45
|
type: :development
|
46
46
|
prerelease: false
|
47
|
-
version_requirements: *
|
47
|
+
version_requirements: *2168673660
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
49
|
name: cucumber
|
50
|
-
requirement: &
|
50
|
+
requirement: &2168672720 !ruby/object:Gem::Requirement
|
51
51
|
none: false
|
52
52
|
requirements:
|
53
53
|
- - ! '>='
|
@@ -55,10 +55,10 @@ dependencies:
|
|
55
55
|
version: '0'
|
56
56
|
type: :development
|
57
57
|
prerelease: false
|
58
|
-
version_requirements: *
|
58
|
+
version_requirements: *2168672720
|
59
59
|
- !ruby/object:Gem::Dependency
|
60
60
|
name: ci_reporter
|
61
|
-
requirement: &
|
61
|
+
requirement: &2168672140 !ruby/object:Gem::Requirement
|
62
62
|
none: false
|
63
63
|
requirements:
|
64
64
|
- - ! '>='
|
@@ -66,10 +66,10 @@ dependencies:
|
|
66
66
|
version: '0'
|
67
67
|
type: :development
|
68
68
|
prerelease: false
|
69
|
-
version_requirements: *
|
69
|
+
version_requirements: *2168672140
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rails
|
72
|
-
requirement: &
|
72
|
+
requirement: &2168671320 !ruby/object:Gem::Requirement
|
73
73
|
none: false
|
74
74
|
requirements:
|
75
75
|
- - =
|
@@ -77,10 +77,10 @@ dependencies:
|
|
77
77
|
version: 3.0.1
|
78
78
|
type: :runtime
|
79
79
|
prerelease: false
|
80
|
-
version_requirements: *
|
80
|
+
version_requirements: *2168671320
|
81
81
|
- !ruby/object:Gem::Dependency
|
82
82
|
name: activerecord
|
83
|
-
requirement: &
|
83
|
+
requirement: &2168670740 !ruby/object:Gem::Requirement
|
84
84
|
none: false
|
85
85
|
requirements:
|
86
86
|
- - =
|
@@ -88,10 +88,10 @@ dependencies:
|
|
88
88
|
version: 3.0.1
|
89
89
|
type: :runtime
|
90
90
|
prerelease: false
|
91
|
-
version_requirements: *
|
91
|
+
version_requirements: *2168670740
|
92
92
|
- !ruby/object:Gem::Dependency
|
93
93
|
name: paperclip
|
94
|
-
requirement: &
|
94
|
+
requirement: &2168670280 !ruby/object:Gem::Requirement
|
95
95
|
none: false
|
96
96
|
requirements:
|
97
97
|
- - ! '>='
|
@@ -99,10 +99,10 @@ dependencies:
|
|
99
99
|
version: '0'
|
100
100
|
type: :runtime
|
101
101
|
prerelease: false
|
102
|
-
version_requirements: *
|
102
|
+
version_requirements: *2168670280
|
103
103
|
- !ruby/object:Gem::Dependency
|
104
104
|
name: to_xls
|
105
|
-
requirement: &
|
105
|
+
requirement: &2168669560 !ruby/object:Gem::Requirement
|
106
106
|
none: false
|
107
107
|
requirements:
|
108
108
|
- - ! '>='
|
@@ -110,7 +110,7 @@ dependencies:
|
|
110
110
|
version: '0'
|
111
111
|
type: :runtime
|
112
112
|
prerelease: false
|
113
|
-
version_requirements: *
|
113
|
+
version_requirements: *2168669560
|
114
114
|
description: First implementation will write metadata on mongodb
|
115
115
|
email:
|
116
116
|
- acampolonghi@gmail.com
|
@@ -120,6 +120,7 @@ extensions: []
|
|
120
120
|
extra_rdoc_files: []
|
121
121
|
files:
|
122
122
|
- lib/active_metadata/base.rb
|
123
|
+
- lib/active_metadata/helpers.rb
|
123
124
|
- lib/active_metadata/persistence/active_record/attachment.rb
|
124
125
|
- lib/active_metadata/persistence/active_record/history.rb
|
125
126
|
- lib/active_metadata/persistence/active_record/note.rb
|
@@ -136,12 +137,6 @@ files:
|
|
136
137
|
- lib/model/active_record/history.rb
|
137
138
|
- lib/model/active_record/note.rb
|
138
139
|
- lib/model/active_record/watcher.rb
|
139
|
-
- lib/model/mongoid/active_meta.rb
|
140
|
-
- lib/model/mongoid/attachment.rb
|
141
|
-
- lib/model/mongoid/history.rb
|
142
|
-
- lib/model/mongoid/label.rb
|
143
|
-
- lib/model/mongoid/note.rb
|
144
|
-
- lib/model/mongoid/watcher.rb
|
145
140
|
- lib/rails/railties/tasks.rake
|
146
141
|
- lib/rake/active_record_tasks.rb
|
147
142
|
- lib/rake/task.rb
|
@@ -169,18 +164,8 @@ files:
|
|
169
164
|
- config/initializers/inflections.rb
|
170
165
|
- config/mongoid.yml
|
171
166
|
- config/routes.rb
|
172
|
-
- db/
|
173
|
-
- db/migrate/
|
174
|
-
- db/migrate/002_add_surname_to_document.rb
|
175
|
-
- db/migrate/003_create_section.rb
|
176
|
-
- db/migrate/004_create_user.rb
|
177
|
-
- db/migrate/005_create_inboxes.rb
|
178
|
-
- db/migrate/006_create_alert_message.rb
|
179
|
-
- db/migrate/007_create_notes.rb
|
180
|
-
- db/migrate/008_create_history.rb
|
181
|
-
- db/migrate/009_create_watcher.rb
|
182
|
-
- db/migrate/010_create_attachment.rb
|
183
|
-
- db/migrate/011_add_created_by_to_histories.rb
|
167
|
+
- db/migrate/01_create_test_resources.rb
|
168
|
+
- db/migrate/02_active_metadata_migrations.rb
|
184
169
|
- db/test.sqlite3
|
185
170
|
- features/step_definitions/add_a_user_to_a_watcher_steps.rb
|
186
171
|
- features/step_definitions/trigger_alert_on_modify_steps.rb
|
@@ -191,6 +176,7 @@ files:
|
|
191
176
|
- features/watchlist/trigger_alert_on_modify.feature
|
192
177
|
- spec/active_metadata_spec.rb
|
193
178
|
- spec/benchmark_spec.rb
|
179
|
+
- spec/concurrency_spec.rb
|
194
180
|
- spec/controllers/metadata_controller_spec.rb
|
195
181
|
- spec/spec_helper.rb
|
196
182
|
- spec/support/document.rb
|
@@ -233,6 +219,7 @@ test_files:
|
|
233
219
|
- features/watchlist/trigger_alert_on_modify.feature
|
234
220
|
- spec/active_metadata_spec.rb
|
235
221
|
- spec/benchmark_spec.rb
|
222
|
+
- spec/concurrency_spec.rb
|
236
223
|
- spec/controllers/metadata_controller_spec.rb
|
237
224
|
- spec/spec_helper.rb
|
238
225
|
- spec/support/document.rb
|
data/db/development.sqlite3
DELETED
Binary file
|
@@ -1,19 +0,0 @@
|
|
1
|
-
class CreateInboxes < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :inboxes do |t|
|
4
|
-
t.string :label
|
5
|
-
t.string :object_class
|
6
|
-
t.integer :object_id
|
7
|
-
t.string :alert_type
|
8
|
-
t.string :old_value
|
9
|
-
t.string :new_value
|
10
|
-
t.text :content
|
11
|
-
t.integer :user_id
|
12
|
-
t.timestamps
|
13
|
-
end
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.down
|
17
|
-
drop_table :inboxes
|
18
|
-
end
|
19
|
-
end
|
@@ -1,37 +0,0 @@
|
|
1
|
-
class CreateAlertMessage < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
drop_table :inboxes
|
4
|
-
|
5
|
-
create_table :inboxes do |t|
|
6
|
-
t.integer :user_id
|
7
|
-
end
|
8
|
-
|
9
|
-
create_table :alert_messages do |t|
|
10
|
-
t.string :label
|
11
|
-
t.string :model_class
|
12
|
-
t.integer :model_id
|
13
|
-
t.string :alert_type
|
14
|
-
t.text :old_value
|
15
|
-
t.text :new_value
|
16
|
-
t.integer :inbox_id
|
17
|
-
t.boolean :read
|
18
|
-
|
19
|
-
t.timestamps
|
20
|
-
end
|
21
|
-
end
|
22
|
-
|
23
|
-
def self.down
|
24
|
-
drop_table :alert_messages
|
25
|
-
create_table :inboxes do |t|
|
26
|
-
t.string :label
|
27
|
-
t.string :object_class
|
28
|
-
t.integer :object_id
|
29
|
-
t.string :alert_type
|
30
|
-
t.string :old_value
|
31
|
-
t.string :new_value
|
32
|
-
t.text :content
|
33
|
-
t.integer :user_id
|
34
|
-
t.timestamps
|
35
|
-
end
|
36
|
-
end
|
37
|
-
end
|
@@ -1,22 +0,0 @@
|
|
1
|
-
class CreateNotes < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :notes do |t|
|
4
|
-
t.text :note
|
5
|
-
t.string :label
|
6
|
-
t.integer :document_id
|
7
|
-
t.integer :created_by
|
8
|
-
t.integer :updated_by
|
9
|
-
t.timestamps
|
10
|
-
end
|
11
|
-
|
12
|
-
add_index :notes, :document_id
|
13
|
-
add_index :notes, :label
|
14
|
-
add_index :notes, :updated_at
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.down
|
19
|
-
drop_table :notes
|
20
|
-
end
|
21
|
-
|
22
|
-
end
|
@@ -1,20 +0,0 @@
|
|
1
|
-
class CreateHistory < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :histories do |t|
|
4
|
-
t.text :value
|
5
|
-
t.string :label
|
6
|
-
t.integer :document_id
|
7
|
-
t.timestamps
|
8
|
-
end
|
9
|
-
|
10
|
-
add_index :histories, :document_id
|
11
|
-
add_index :histories, :label
|
12
|
-
add_index :histories, :created_at
|
13
|
-
|
14
|
-
end
|
15
|
-
|
16
|
-
def self.down
|
17
|
-
drop_table :histories
|
18
|
-
end
|
19
|
-
|
20
|
-
end
|
@@ -1,21 +0,0 @@
|
|
1
|
-
class CreateWatcher < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :watchers do |t|
|
4
|
-
t.integer :owner_id
|
5
|
-
t.string :label
|
6
|
-
t.integer :document_id
|
7
|
-
t.timestamps
|
8
|
-
end
|
9
|
-
|
10
|
-
add_index :watchers, :document_id
|
11
|
-
add_index :watchers, :label
|
12
|
-
add_index :watchers, :owner_id
|
13
|
-
add_index :watchers, :created_at
|
14
|
-
|
15
|
-
end
|
16
|
-
|
17
|
-
def self.down
|
18
|
-
drop_table :watchers
|
19
|
-
end
|
20
|
-
|
21
|
-
end
|
@@ -1,26 +0,0 @@
|
|
1
|
-
class CreateAttachment < ActiveRecord::Migration
|
2
|
-
def self.up
|
3
|
-
create_table :attachments do |t|
|
4
|
-
t.string :label
|
5
|
-
t.integer :document_id
|
6
|
-
t.integer :created_by
|
7
|
-
t.integer :updated_by
|
8
|
-
t.integer :counter
|
9
|
-
t.string :attach_file_name
|
10
|
-
t.string :attach_content_type
|
11
|
-
t.integer :attach_file_size
|
12
|
-
t.datetime :attach_updated_at
|
13
|
-
t.timestamps
|
14
|
-
end
|
15
|
-
|
16
|
-
add_index :attachments, :document_id
|
17
|
-
add_index :attachments, :label
|
18
|
-
add_index :attachments, :attach_updated_at
|
19
|
-
|
20
|
-
end
|
21
|
-
|
22
|
-
def self.down
|
23
|
-
drop_table :attachments
|
24
|
-
end
|
25
|
-
|
26
|
-
end
|
@@ -1,25 +0,0 @@
|
|
1
|
-
class Attachment
|
2
|
-
include Mongoid::Document
|
3
|
-
include Mongoid::Paperclip
|
4
|
-
|
5
|
-
belongs_to :label
|
6
|
-
has_mongoid_attached_file :attach,
|
7
|
-
:path => "#{ActiveMetadata::CONFIG['attachment_base_path']}/:document_id/:label/:counter/:basename.:extension",
|
8
|
-
:url => "#{ActiveMetadata::CONFIG['attachment_base_url']}/:document_id/:label/:counter/:basename.:extension"
|
9
|
-
|
10
|
-
field :created_by, :type => Integer
|
11
|
-
field :counter, :type => Integer
|
12
|
-
|
13
|
-
Paperclip.interpolates :document_id do |attachment,style|
|
14
|
-
attachment.instance.label.active_meta.document_id
|
15
|
-
end
|
16
|
-
|
17
|
-
Paperclip.interpolates :label do |attachment,style|
|
18
|
-
attachment.instance.label.name
|
19
|
-
end
|
20
|
-
|
21
|
-
Paperclip.interpolates :counter do |attachment,style|
|
22
|
-
attachment.instance.counter
|
23
|
-
end
|
24
|
-
|
25
|
-
end
|
data/lib/model/mongoid/label.rb
DELETED
@@ -1,14 +0,0 @@
|
|
1
|
-
class Label
|
2
|
-
include Mongoid::Document
|
3
|
-
field :name
|
4
|
-
|
5
|
-
belongs_to :active_meta, :class_name => "ActiveMeta"
|
6
|
-
|
7
|
-
has_many :notes, :class_name => "Note"
|
8
|
-
has_many :histories, :class_name => "History"
|
9
|
-
has_many :attachments, :class_name => "Attachment"
|
10
|
-
has_many :watchers, :class_name => "Watcher"
|
11
|
-
|
12
|
-
index :name
|
13
|
-
|
14
|
-
end
|
data/lib/model/mongoid/note.rb
DELETED
@@ -1,24 +0,0 @@
|
|
1
|
-
class Watcher
|
2
|
-
include Mongoid::Document
|
3
|
-
|
4
|
-
belongs_to :label
|
5
|
-
|
6
|
-
field :owner_id, :type => Integer
|
7
|
-
|
8
|
-
def notify_changes(matched_label, old_value, new_value, model_class, model_id)
|
9
|
-
create_inbox_alert(User.find(owner_id).inbox, matched_label, old_value, new_value, model_class, model_id)
|
10
|
-
end
|
11
|
-
|
12
|
-
def create_inbox_alert(inbox, label, old_value, new_value, model_class, model_id)
|
13
|
-
Message.create! do |message|
|
14
|
-
message.label = label
|
15
|
-
message.model_class = model_class.to_s
|
16
|
-
message.model_id = model_id
|
17
|
-
message.alert_type = :model_value_changed
|
18
|
-
message.old_value = old_value
|
19
|
-
message.new_value = new_value
|
20
|
-
message.inbox_id = inbox.id
|
21
|
-
message.read = false
|
22
|
-
end
|
23
|
-
end
|
24
|
-
end
|