protected_record 0.0.3 → 0.0.4
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.
- checksums.yaml +4 -4
- data/README.md +53 -37
- data/lib/protected_record/use_case/change_log/create.rb +3 -1
- data/lib/protected_record/version.rb +1 -1
- data/test/minitest_helper.rb +1 -0
- data/test/protected_record/change_log/create_test.rb +118 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2ca5f6df32648cad9acee2ed43774965181ef3b4
|
4
|
+
data.tar.gz: c9f887c42afc82b5a793b3e9b689102dc1492df6
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c9ff4028860f759cb5a5dd2d9212d2d873b4e6e3b400343199ff37a5f93c852b7510410aa843630fbc1dcfce50979e6826c3c66b9014af8d14ecbfa4027b4518
|
7
|
+
data.tar.gz: 30c2e5c35108ef953ad05c1f5fa676f15f7f74e5fe11c5adeabc1cf5555a70f9a24e7257f422b9700581e84e03c7a7606b5ea7a02d94a26953c3e11d1c1ea1b2
|
data/README.md
CHANGED
@@ -1,67 +1,83 @@
|
|
1
1
|
# protected_record
|
2
|
+
|
2
3
|
## Setup for rails applications
|
3
|
-
I've created an engine to provide the necessary migrations as well as a basic interface for traiging change requests. You are free to use this gem without the engine, but you'll need to visit [protected_record_manager](https://github.com/rthbound/protected_record_manager/tree/master/db/migrate) and copy the migrations into your app manually.
|
4
4
|
|
5
|
-
|
5
|
+
I've created an engine to provide the necessary migrations as well as a (very)
|
6
|
+
basic interface for triaging `ProtectedRecord::ChangeRequest::Record` objects.
|
7
|
+
You are free to use this gem without the engine, but you'll need to
|
8
|
+
[grab these](//github.com/rthbound/protected_record_manager/tree/master/db/migrate).
|
6
9
|
|
7
|
-
|
8
|
-
|
9
|
-
And to your Rails application's `routes.rb`:
|
10
|
-
```ruby
|
11
|
-
mount ProtectedRecordManager::Engine, :at => "/protected_record_manager", as: "protected_record_manager"
|
12
|
-
```
|
13
|
-
Which will provide a user interface for triaging change requests at:
|
14
|
-
```
|
15
|
-
http://localhost:3000/protected_record_manager/change_requests
|
16
|
-
```
|
17
|
-
**Important:** Only users with `@user.protected_record_manager == true` will be able to access these resources.
|
10
|
+
### Your models
|
18
11
|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
Lastly, you'll need to prepare your models. There's two types of models at play here:
|
12
|
+
Prepare your models.
|
13
|
+
There's **two types** of models at play here:
|
14
|
+
|
15
|
+
1. User (for now I expect a `User` class and `current\_user` method
|
16
|
+
2. Your records .. these are the models you want to track
|
25
17
|
|
26
|
-
|
27
|
-
2. records .. these are the models you want to track
|
18
|
+
So, in your models
|
28
19
|
|
29
|
-
So in `user.rb`
|
30
20
|
```ruby
|
21
|
+
# app/models/user.rb
|
31
22
|
include ProtectedRecord::ChangeRequest::Changer
|
32
23
|
include ProtectedRecord::ChangeLog::Changer
|
33
24
|
```
|
34
25
|
|
35
|
-
And in any model where you want to use protection:
|
36
26
|
```ruby
|
27
|
+
# app/models/any.rb
|
28
|
+
|
37
29
|
include ProtectedRecord::ChangeRequest::Changeling
|
38
30
|
include ProtectedRecord::ChangeLog::Changeling
|
39
31
|
```
|
32
|
+
|
40
33
|
## Usage
|
34
|
+
|
41
35
|
1. protected_record will prevent changes to attributes you specify as protected.
|
42
|
-
2. Any attempted change will be logged as a
|
43
|
-
|
44
|
-
|
36
|
+
2. Any attempted change will be logged as a
|
37
|
+
`ProtectedRecord::ChangeRequest::Record`.
|
38
|
+
3. If any changes are allowed through the filter, protected_record
|
39
|
+
will create a `ProtectedRecord::ChangeLog::Record` to log who changed what,
|
40
|
+
and for which record.
|
41
|
+
4. **Important**: ProtectedRecord is opt-in only. It does not change the
|
42
|
+
behavior of any AR methods, nor does it place any callbacks in your models.
|
43
|
+
In order to update with protection, use the following:
|
44
|
+
|
45
|
+
This user can change anything but `:do_not_resuscitate`and `:organ_donor`.
|
46
|
+
Rejected changes will create `ProtectedRecord::ChangeRequest::Record` objects.
|
47
|
+
Permitted changes will create `ProtectedRecord::ChangeLog::Record` objects.
|
45
48
|
|
46
49
|
```ruby
|
47
|
-
|
48
|
-
|
50
|
+
ready = ProtectedRecord::UseCase::Update.new({
|
51
|
+
user: current_user,
|
52
|
+
params: record_params,
|
49
53
|
protected_record: @record,
|
50
|
-
|
51
|
-
|
52
|
-
}).execute!
|
54
|
+
protected_keys: %w{ do_not_resuscitate organ_donor }
|
55
|
+
})
|
53
56
|
|
54
|
-
|
55
|
-
# creating a "change request" rather than applying changes
|
57
|
+
result = ready.execute!
|
56
58
|
|
57
|
-
|
58
|
-
# creating a "change log" entry for the observed changes
|
59
|
-
update_result.successful? #=> true
|
59
|
+
result.successful? #=> true
|
60
60
|
```
|
61
|
-
|
61
|
+
|
62
|
+
and
|
63
|
+
|
62
64
|
```ruby
|
65
|
+
# Who changed what, and when
|
63
66
|
@user.change_log_records
|
67
|
+
|
68
|
+
# Who attempted to change what, and when
|
64
69
|
@user.change_request_records
|
70
|
+
|
71
|
+
# What changed, and when
|
65
72
|
@record.change_log_records
|
73
|
+
|
74
|
+
# What changes were attempted, and when
|
66
75
|
@record.change_request_records
|
67
76
|
```
|
77
|
+
|
78
|
+
## Contributing
|
79
|
+
|
80
|
+
Please do. There's plenty that could be done to round out both the interface
|
81
|
+
and the the feature set.
|
82
|
+
|
83
|
+
Issues and pull requests would be most appreciated.
|
@@ -1,3 +1,5 @@
|
|
1
|
+
require "json"
|
2
|
+
|
1
3
|
module ProtectedRecord
|
2
4
|
module UseCase
|
3
5
|
module ChangeLog
|
@@ -28,7 +30,7 @@ module ProtectedRecord
|
|
28
30
|
@record = @record_class.new
|
29
31
|
@record.user = @user
|
30
32
|
@record.recordable = @changed_object
|
31
|
-
@record.observed_changes =
|
33
|
+
@record.observed_changes = JSON.generate(@changed_object.previous_changes)
|
32
34
|
end
|
33
35
|
end
|
34
36
|
end
|
data/test/minitest_helper.rb
CHANGED
@@ -1,2 +1,120 @@
|
|
1
1
|
require "minitest_helper"
|
2
|
+
require "active_record"
|
2
3
|
|
4
|
+
describe ProtectedRecord::UseCase::ChangeFilter::Create do
|
5
|
+
describe "new" do
|
6
|
+
before do
|
7
|
+
class TestCase
|
8
|
+
include ActiveModel::Dirty
|
9
|
+
|
10
|
+
define_attribute_methods [:knowledge, :power]
|
11
|
+
|
12
|
+
def knowledge
|
13
|
+
@knowledge
|
14
|
+
end
|
15
|
+
|
16
|
+
def power
|
17
|
+
@power
|
18
|
+
end
|
19
|
+
|
20
|
+
def knowledge=(val)
|
21
|
+
knowledge_will_change! unless val == @knowledge
|
22
|
+
@knowledge = val
|
23
|
+
end
|
24
|
+
|
25
|
+
def power=(val)
|
26
|
+
power_will_change! unless val == @power
|
27
|
+
@power = val
|
28
|
+
end
|
29
|
+
|
30
|
+
def save
|
31
|
+
@previously_changed = changes
|
32
|
+
@changed_attributes.clear
|
33
|
+
end
|
34
|
+
|
35
|
+
def initialize(attributes = {})
|
36
|
+
attributes.each do |name, value|
|
37
|
+
send("#{name}=", value)
|
38
|
+
end
|
39
|
+
end
|
40
|
+
#####
|
41
|
+
end
|
42
|
+
|
43
|
+
@subject = ProtectedRecord::UseCase::ChangeLog::Create
|
44
|
+
|
45
|
+
@protected_record = TestCase.new(knowledge: "power", power: "money")
|
46
|
+
@protected_record.save
|
47
|
+
|
48
|
+
@mock_change_log_record_class = MiniTest::Mock.new
|
49
|
+
@mock_change_log_record = MiniTest::Mock.new
|
50
|
+
@mock_user = MiniTest::Mock.new
|
51
|
+
@changes = JSON.generate(@protected_record.previous_changes)
|
52
|
+
@mock_change_log_record_class.expect(:new, @mock_change_log_record)
|
53
|
+
@mock_change_log_record.expect(:user=, @mock_user, [@mock_user])
|
54
|
+
@mock_change_log_record.expect(:recordable=, @protected_record, [@protected_record])
|
55
|
+
@mock_change_log_record.expect(:observed_changes=, @changes, [@changes])
|
56
|
+
@mock_change_log_record.expect(:save, true)
|
57
|
+
|
58
|
+
@dependencies = {
|
59
|
+
record_class: @mock_change_log_record_class,
|
60
|
+
user: @mock_user,
|
61
|
+
changed_object: @protected_record
|
62
|
+
}
|
63
|
+
end
|
64
|
+
|
65
|
+
it "initializes with required options" do
|
66
|
+
subject = @subject.new(@dependencies)
|
67
|
+
|
68
|
+
subject.must_be_instance_of @subject
|
69
|
+
end
|
70
|
+
|
71
|
+
it "initializes when options with defaults are omitted" do
|
72
|
+
subject = @subject.new(@dependencies.reject { |k| k == :record_class })
|
73
|
+
|
74
|
+
subject.must_be_instance_of @subject
|
75
|
+
end
|
76
|
+
|
77
|
+
it "fails to initialize without :user" do
|
78
|
+
begin
|
79
|
+
@subject.new(@dependencies.reject { |k| k == :user })
|
80
|
+
rescue => e
|
81
|
+
e.must_be_kind_of RuntimeError
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
it "fails to initialize without :changed_object" do
|
86
|
+
begin
|
87
|
+
@subject.new(@dependencies.reject { |k| k == :changed_object })
|
88
|
+
rescue => e
|
89
|
+
e.must_be_kind_of RuntimeError
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns a result" do
|
94
|
+
result = @subject.new(@dependencies).execute!
|
95
|
+
|
96
|
+
@mock_change_log_record.verify
|
97
|
+
|
98
|
+
result.must_be_kind_of(PayDirt::Result)
|
99
|
+
end
|
100
|
+
|
101
|
+
it "does the deed" do
|
102
|
+
result = @subject.new(@dependencies).execute!
|
103
|
+
|
104
|
+
@mock_change_log_record.verify
|
105
|
+
|
106
|
+
result.successful?.must_equal true
|
107
|
+
end
|
108
|
+
|
109
|
+
it "it's not successful if #save fails" do
|
110
|
+
@mock_change_log_record.save
|
111
|
+
@mock_change_log_record.expect(:save, false)
|
112
|
+
|
113
|
+
result = @subject.new(@dependencies).execute!
|
114
|
+
|
115
|
+
@mock_change_log_record.verify
|
116
|
+
|
117
|
+
result.successful?.must_equal false
|
118
|
+
end
|
119
|
+
end
|
120
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: protected_record
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Tad Hosford
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-04-
|
11
|
+
date: 2013-04-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: pay_dirt
|