protected_record 0.0.4 → 0.0.5

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 2ca5f6df32648cad9acee2ed43774965181ef3b4
4
- data.tar.gz: c9f887c42afc82b5a793b3e9b689102dc1492df6
3
+ metadata.gz: f77ce95c22273bab1bf96d5c3955ec8c0866ea72
4
+ data.tar.gz: cc5c1b24cda6552940a9b86a7fa466f7a56519ee
5
5
  SHA512:
6
- metadata.gz: c9ff4028860f759cb5a5dd2d9212d2d873b4e6e3b400343199ff37a5f93c852b7510410aa843630fbc1dcfce50979e6826c3c66b9014af8d14ecbfa4027b4518
7
- data.tar.gz: 30c2e5c35108ef953ad05c1f5fa676f15f7f74e5fe11c5adeabc1cf5555a70f9a24e7257f422b9700581e84e03c7a7606b5ea7a02d94a26953c3e11d1c1ea1b2
6
+ metadata.gz: c65da5f7063befa647fbd49a7ee8d6e13d582d79dbb74d3d760f264e0ec96c8f4022988f0bfc5709a7ec985443454fcacdddfea1675cd739e2f1d9e10ddfc6dd
7
+ data.tar.gz: 0bc2f938d78f5a4cd364c07082ed77da4a1504f15d361161c4c104ced43e5d1a508949ca2c64b0876f46d68d5b1c61bfdb40ba3bdcc865b9d20e3c2f0894b98e
data/README.md CHANGED
@@ -5,17 +5,17 @@
5
5
  I've created an engine to provide the necessary migrations as well as a (very)
6
6
  basic interface for triaging `ProtectedRecord::ChangeRequest::Record` objects.
7
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).
8
+ [grab these](https://github.com/rthbound/protected_record_manager/tree/master/db/migrate).
9
9
 
10
10
  ### Your models
11
11
 
12
12
  Prepare your models.
13
13
  There's **two types** of models at play here:
14
14
 
15
- 1. User (for now I expect a `User` class and `current\_user` method
15
+ 1. User (for now I expect a `User` class and `current_user` method
16
16
  2. Your records .. these are the models you want to track
17
17
 
18
- So, in your models
18
+ So, in your models add `require "protected_record"`
19
19
 
20
20
  ```ruby
21
21
  # app/models/user.rb
@@ -30,6 +30,22 @@ include ProtectedRecord::ChangeRequest::Changeling
30
30
  include ProtectedRecord::ChangeLog::Changeling
31
31
  ```
32
32
 
33
+ #### Protected Keys
34
+
35
+ You have two options,
36
+
37
+ 1. Inject the `:protected_keys` option when you execute the update (this will always take precedence)
38
+ 2. Include in your record class `ProtectedRecord::DirtyModel` and define them there:
39
+
40
+ ```ruby
41
+ class SomeRecord < ActiveRecord::Base
42
+ include ProtectedRecord::DirtyModel
43
+ protected_keys :do_not_resuscitate, :organ_donor
44
+ end
45
+ ```
46
+
47
+ If you do not specify either option, ProtectedRecord will use an empty array.
48
+
33
49
  ## Usage
34
50
 
35
51
  1. protected_record will prevent changes to attributes you specify as protected.
@@ -0,0 +1,17 @@
1
+ module ProtectedRecord
2
+ module DirtyModel
3
+ def self.included(base)
4
+ base.extend(ClassMethods)
5
+
6
+ def protected_keys
7
+ self.class.send(:protected_keys)
8
+ end
9
+ end
10
+
11
+ module ClassMethods
12
+ def protected_keys(*args)
13
+ @@protected_keys ||= args.to_a
14
+ end
15
+ end
16
+ end
17
+ end
@@ -3,7 +3,8 @@ module ProtectedRecord
3
3
  module ChangeFilter
4
4
  class Create < PayDirt::Base
5
5
  def initialize(options)
6
- load_options(:protected_keys, :protected_record, options)
6
+ load_options(:protected_record, options)
7
+ validate_state
7
8
  end
8
9
 
9
10
  def execute!
@@ -22,6 +23,17 @@ module ProtectedRecord
22
23
  end
23
24
  end
24
25
  end
26
+
27
+ protected
28
+ def validate_state
29
+ if !@protected_keys.kind_of?(Array)
30
+ if @protected_record.respond_to? :protected_keys
31
+ @protected_keys = @protected_record.protected_keys
32
+ else
33
+ @protected_keys = []
34
+ end
35
+ end
36
+ end
25
37
  end
26
38
  end
27
39
  end
@@ -7,7 +7,8 @@ module ProtectedRecord
7
7
  record_class: ::ProtectedRecord::ChangeRequest::Record
8
8
  }.merge!(options) if !options.has_key?(:record_class)
9
9
 
10
- load_options(:protected_keys, :record_class, :user, :protected_record, options)
10
+ load_options(:record_class, :user, :protected_record, options)
11
+ validate_state
11
12
  end
12
13
 
13
14
  def execute!
@@ -45,6 +46,17 @@ module ProtectedRecord
45
46
 
46
47
  raise if @protected_keys.any? { |key| @protected_record.send("#{key}_changed?") }
47
48
  end
49
+
50
+ protected
51
+ def validate_state
52
+ if !@protected_keys.kind_of?(Array)
53
+ if @protected_record.respond_to? :protected_keys
54
+ @protected_keys = @protected_record.protected_keys
55
+ else
56
+ @protected_keys = []
57
+ end
58
+ end
59
+ end
48
60
  end
49
61
  end
50
62
  end
@@ -9,7 +9,7 @@ module ProtectedRecord
9
9
  change_log: UseCase::ChangeLog::Create
10
10
  }.merge!(options)
11
11
 
12
- load_options(:params, :protected_record, :change_request, :change_log, :change_filter, :protected_keys, :user, options)
12
+ load_options(:params, :protected_record, :change_request, :change_log, :change_filter, :user, options)
13
13
  validate_state
14
14
  end
15
15
 
@@ -70,7 +70,11 @@ module ProtectedRecord
70
70
  def validate_state
71
71
  # We expect some keys
72
72
  if !@protected_keys.kind_of?(Array)
73
- raise TypeError.new(':protected_keys not kind of Array')
73
+ if @protected_record.respond_to? :protected_keys
74
+ @protected_keys = @protected_record.protected_keys
75
+ else
76
+ @protected_keys = []
77
+ end
74
78
  end
75
79
 
76
80
  # The keys should respond to to_s
@@ -1,3 +1,3 @@
1
1
  module ProtectedRecord
2
- VERSION = "0.0.4"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -11,3 +11,90 @@ $: << File.dirname(__FILE__) + "/../lib"
11
11
  $: << File.dirname(__FILE__)
12
12
 
13
13
  require "protected_record"
14
+
15
+ class TestCase
16
+ include ActiveModel::Dirty
17
+ include ProtectedRecord::DirtyModel
18
+
19
+ protected_keys :knowledge, :power
20
+
21
+ define_attribute_methods [:knowledge, :power]
22
+
23
+ def knowledge
24
+ @knowledge
25
+ end
26
+
27
+ def attributes=(args)
28
+ end
29
+
30
+ def id_was
31
+ 1
32
+ end
33
+
34
+ def power
35
+ @power
36
+ end
37
+
38
+ def knowledge=(val)
39
+ knowledge_will_change! unless val == @knowledge
40
+ @knowledge = val
41
+ end
42
+
43
+ def power=(val)
44
+ power_will_change! unless val == @power
45
+ @power = val
46
+ end
47
+
48
+ def save
49
+ @previously_changed = changes
50
+ @changed_attributes.clear
51
+ end
52
+
53
+ def initialize(attributes = {})
54
+ attributes.each do |name, value|
55
+ send("#{name}=", value)
56
+ end
57
+ end
58
+ end
59
+
60
+ class UnprotectedTestCase
61
+ include ActiveModel::Dirty
62
+
63
+ define_attribute_methods [:knowledge, :power]
64
+
65
+ def knowledge
66
+ @knowledge
67
+ end
68
+
69
+ def attributes=(args)
70
+ end
71
+
72
+ def id_was
73
+ 1
74
+ end
75
+
76
+ def power
77
+ @power
78
+ end
79
+
80
+ def knowledge=(val)
81
+ knowledge_will_change! unless val == @knowledge
82
+ @knowledge = val
83
+ end
84
+
85
+ def power=(val)
86
+ power_will_change! unless val == @power
87
+ @power = val
88
+ end
89
+
90
+ def save
91
+ @previously_changed = changes
92
+ @changed_attributes.clear
93
+ end
94
+
95
+ def initialize(attributes = {})
96
+ attributes.each do |name, value|
97
+ send("#{name}=", value)
98
+ end
99
+ end
100
+ end
@@ -1,45 +1,8 @@
1
1
  require "minitest_helper"
2
- require "active_record"
3
2
 
4
3
  describe ProtectedRecord::UseCase::ChangeFilter::Create do
5
4
  describe "new" do
6
5
  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
6
  @subject = ProtectedRecord::UseCase::ChangeFilter::Create
44
7
 
45
8
  @protected_record = TestCase.new(knowledge: "power", power: "money")
@@ -129,5 +92,36 @@ describe ProtectedRecord::UseCase::ChangeFilter::Create do
129
92
  ret_obj.knowledge.must_equal "growth"
130
93
  ret_obj.power.must_equal "money"
131
94
  end
95
+
96
+ it "it will read protected_keys from your model" do
97
+ @protected_record.knowledge="growth"
98
+ @protected_record.power="knowledge"
99
+
100
+ result = @subject.new({
101
+ protected_record: @protected_record,
102
+ }).execute!
103
+
104
+ ret_obj = result.data[:change_request_record]
105
+
106
+ ret_obj.knowledge.must_equal "power"
107
+ ret_obj.power.must_equal "money"
108
+ end
109
+
110
+ it "will allow any changes when no protected_keys are provided" do
111
+ @protected_record = UnprotectedTestCase.new(knowledge: "power", power: "money")
112
+ @protected_record.save
113
+
114
+ @protected_record.knowledge="growth"
115
+ @protected_record.power="knowledge"
116
+
117
+ result = @subject.new({
118
+ protected_record: @protected_record,
119
+ }).execute!
120
+
121
+ ret_obj = result.data[:change_request_record]
122
+
123
+ ret_obj.knowledge.must_equal "growth"
124
+ ret_obj.power.must_equal "knowledge"
125
+ end
132
126
  end
133
127
  end
@@ -1,82 +1,45 @@
1
1
  require "minitest_helper"
2
- require "active_record"
3
2
 
4
- describe ProtectedRecord::UseCase::ChangeFilter::Create do
3
+ describe ProtectedRecord::UseCase::ChangeLog::Create do
5
4
  describe "new" do
6
5
  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)
6
+ @subject = ProtectedRecord::UseCase::ChangeLog::Create
7
+ @test_case = TestCase.new({
8
+ knowledge: "power",
9
+ power: "money"
10
+ })
11
+ @test_case.save
12
+
13
+ @change_log_record_class = MiniTest::Mock.new
14
+ @change_log_record = MiniTest::Mock.new
15
+ @user = MiniTest::Mock.new
16
+ @changes = JSON.generate(@test_case.previous_changes)
17
+ @change_log_record_class.expect :new, @change_log_record
18
+ @change_log_record.expect :user=, @user, [@user]
19
+ @change_log_record.expect :recordable=, @test_case, [@test_case]
20
+ @change_log_record.expect :observed_changes=, @changes, [@changes]
21
+ @change_log_record.expect :save, true
57
22
 
58
23
  @dependencies = {
59
- record_class: @mock_change_log_record_class,
60
- user: @mock_user,
61
- changed_object: @protected_record
24
+ user: @user,
25
+ record_class: @change_log_record_class,
26
+ changed_object: @test_case
62
27
  }
63
28
  end
64
29
 
65
30
  it "initializes with required options" do
66
- subject = @subject.new(@dependencies)
67
-
31
+ subject = @subject.new @dependencies
68
32
  subject.must_be_instance_of @subject
69
33
  end
70
34
 
71
35
  it "initializes when options with defaults are omitted" do
72
- subject = @subject.new(@dependencies.reject { |k| k == :record_class })
73
-
36
+ subject = @subject.new @dependencies.reject { |k| k == :record_class }
74
37
  subject.must_be_instance_of @subject
75
38
  end
76
39
 
77
40
  it "fails to initialize without :user" do
78
41
  begin
79
- @subject.new(@dependencies.reject { |k| k == :user })
42
+ @subject.new @dependencies.reject { |k| k == :user }
80
43
  rescue => e
81
44
  e.must_be_kind_of RuntimeError
82
45
  end
@@ -84,7 +47,7 @@ describe ProtectedRecord::UseCase::ChangeFilter::Create do
84
47
 
85
48
  it "fails to initialize without :changed_object" do
86
49
  begin
87
- @subject.new(@dependencies.reject { |k| k == :changed_object })
50
+ @subject.new @dependencies.reject { |k| k == :changed_object }
88
51
  rescue => e
89
52
  e.must_be_kind_of RuntimeError
90
53
  end
@@ -93,7 +56,7 @@ describe ProtectedRecord::UseCase::ChangeFilter::Create do
93
56
  it "returns a result" do
94
57
  result = @subject.new(@dependencies).execute!
95
58
 
96
- @mock_change_log_record.verify
59
+ @change_log_record.verify
97
60
 
98
61
  result.must_be_kind_of(PayDirt::Result)
99
62
  end
@@ -101,18 +64,18 @@ describe ProtectedRecord::UseCase::ChangeFilter::Create do
101
64
  it "does the deed" do
102
65
  result = @subject.new(@dependencies).execute!
103
66
 
104
- @mock_change_log_record.verify
67
+ @change_log_record.verify
105
68
 
106
69
  result.successful?.must_equal true
107
70
  end
108
71
 
109
72
  it "it's not successful if #save fails" do
110
- @mock_change_log_record.save
111
- @mock_change_log_record.expect(:save, false)
73
+ @change_log_record.save
74
+ @change_log_record.expect(:save, false)
112
75
 
113
76
  result = @subject.new(@dependencies).execute!
114
77
 
115
- @mock_change_log_record.verify
78
+ @change_log_record.verify
116
79
 
117
80
  result.successful?.must_equal false
118
81
  end
@@ -1,2 +1,94 @@
1
1
  require "minitest_helper"
2
2
 
3
+ describe ProtectedRecord::UseCase::ChangeRequest::Create do
4
+ describe "new" do
5
+ before do
6
+ @subject = ProtectedRecord::UseCase::ChangeRequest::Create
7
+
8
+ @protected_record = TestCase.new(knowledge: "power", power: "money")
9
+ @protected_record.save
10
+
11
+ @mock_change_request_record_class = MiniTest::Mock.new
12
+ @mock_change_request_record = MiniTest::Mock.new
13
+ @mock_user = MiniTest::Mock.new
14
+ @mock_change_request_record_class.expect(:new, @mock_change_request_record)
15
+ @mock_change_request_record.expect(:user=, @mock_user, [@mock_user])
16
+ @mock_change_request_record.expect(:recordable=, @protected_record, [@protected_record])
17
+ @mock_change_request_record.expect(:save, true)
18
+
19
+ @protected_record.power= "trivial knowledge"
20
+ @changes = JSON.generate(@protected_record.changes)
21
+ @mock_change_request_record.expect(:requested_changes=, @changes, [@changes])
22
+
23
+ @dependencies = {
24
+ protected_keys: %w{ power },
25
+ protected_record: @protected_record,
26
+ record_class: @mock_change_request_record_class,
27
+ user: @mock_user
28
+ }
29
+ end
30
+
31
+ it "initializes with required options" do
32
+ subject = @subject.new(@dependencies)
33
+
34
+ subject.must_be_instance_of @subject
35
+ end
36
+
37
+ it "initializes when options with defaults are omitted" do
38
+ subject = @subject.new(@dependencies.reject { |k| k == :record_class })
39
+
40
+ subject.must_be_instance_of @subject
41
+ end
42
+
43
+ it "fails to initialize without :user" do
44
+ begin
45
+ @subject.new(@dependencies.reject { |k| k == :user })
46
+ rescue => e
47
+ e.must_be_kind_of RuntimeError
48
+ end
49
+ end
50
+
51
+ it "fails to initialize without :changed_object" do
52
+ begin
53
+ @subject.new(@dependencies.reject { |k| k == :protected_record })
54
+ rescue => e
55
+ e.must_be_kind_of RuntimeError
56
+ end
57
+ end
58
+
59
+ it "returns a result" do
60
+ result = @subject.new(@dependencies).execute!
61
+
62
+ result.must_be_kind_of(PayDirt::Result)
63
+ end
64
+ it "does the deed" do
65
+ result = @subject.new(@dependencies).execute!
66
+
67
+ @mock_change_request_record.verify
68
+
69
+ result.successful?.must_equal true
70
+ end
71
+
72
+ it "can read protected_keys from your model" do
73
+ so = @subject.new @dependencies.reject { |k| k.to_s == "protected_keys" }
74
+ result = so.execute!
75
+
76
+
77
+ @mock_change_request_record.verify
78
+
79
+ result.successful?.must_equal true
80
+ end
81
+
82
+ it "it's not successful if #save fails" do
83
+ @mock_change_request_record.save
84
+ @mock_change_request_record.expect(:save, false)
85
+
86
+ result = @subject.new(@dependencies).execute!
87
+
88
+ @mock_change_request_record.verify
89
+
90
+ result.successful?.must_equal false
91
+ end
92
+ end
93
+ end
94
+
@@ -1 +1,44 @@
1
1
  require "minitest_helper"
2
+
3
+ describe ProtectedRecord::UseCase::Update do
4
+ before do
5
+ @subject = ProtectedRecord::UseCase::Update
6
+
7
+ @params = { params: {
8
+ knowledge: "bad",
9
+ power: "money"
10
+ }}
11
+
12
+ @test_case = TestCase.new( knowledge: :power )
13
+
14
+ @dependencies = {
15
+ user: MiniTest::Mock.new,
16
+ protected_record: @test_case,
17
+ protected_keys: [:knowledge],
18
+ }
19
+ @dependencies.merge! @params
20
+ end
21
+
22
+ it "can be initialized" do
23
+ @subject.must_respond_to :new
24
+ end
25
+
26
+ it "fails without required dependencies" do
27
+ %w{ user params protected_record }.each do |dep|
28
+ begin
29
+ @subject.new @dependencies.reject { |k| k.to_s == dep }
30
+ rescue => e
31
+ e.must_be_kind_of RuntimeError
32
+ end
33
+ end
34
+ end
35
+
36
+ it "initializes without :protected_keys" do
37
+ so = @subject.new @dependencies.reject { |k| k.to_s == "protected_keys" }
38
+ so.must_respond_to :execute!
39
+ end
40
+
41
+ it "can be executed" do
42
+ @subject.new(@dependencies).must_respond_to :execute!
43
+ end
44
+ 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
4
+ version: 0.0.5
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-25 00:00:00.000000000 Z
11
+ date: 2013-05-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: pay_dirt
@@ -98,6 +98,7 @@ files:
98
98
  - lib/protected_record.rb
99
99
  - lib/protected_record/change_log.rb
100
100
  - lib/protected_record/change_request.rb
101
+ - lib/protected_record/dirty_model.rb
101
102
  - lib/protected_record/use_case.rb
102
103
  - lib/protected_record/use_case/change_filter/create.rb
103
104
  - lib/protected_record/use_case/change_log/create.rb