undo 0.0.3 → 0.1.0

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: 4a5040011eba1d15fba3685916c6b860e1c27bcb
4
- data.tar.gz: 13ac49e306629143828ceb2c8b9485fc331b6f13
3
+ metadata.gz: 20c52711aa6a7b2718cf79b9ecc238f1a77b53e2
4
+ data.tar.gz: fd06dc16acb71cd5fde5d9bfe4b69c8f00272a1c
5
5
  SHA512:
6
- metadata.gz: 0c7b26509df4c556ff01122e53af31069be2b3ebb5b64bcd3cab7a2cc7f471130a4c11fb1fe850ca317cc1daddfecbdf4d6ed52642ef7b8dd6de34499c72c03f
7
- data.tar.gz: 30eef3cf3133a1515ef46e1ada8baf4e517c92d3155ef8970514075e088bf6817ecf89761edd8ceed6ae9f46051b465ab0244d1d3eca66a5713a8f0eae89bb46
6
+ metadata.gz: 6a94e5461a9937c5141ca1bdd5cdbf3fb9d653de480ecf1a9c508580f0f1774060cb6902dc55bb4e74d4729ed3b5bc0e1b4b8873cca76cbe24ba617daee8cdf9
7
+ data.tar.gz: 11a5d31f76ddced0163edfb1d382ed03a5d7c84dfd7378a0c805f562b34eb0ed5d05659449b56f59cfdb6e119d1115bc4a69d6f233e4f57eaa766ba8a3f5f172
data/README.md CHANGED
@@ -53,14 +53,35 @@ Usage
53
53
 
54
54
  ### Undo operation
55
55
 
56
- Wrap object in Undo decorator:
56
+ ``` ruby
57
+ uuid = Undo.store object
58
+ Undo.restore uuid
59
+ ```
60
+ That is basically it :)
61
+
62
+ Additionally possible to wrap object in Undo decorator:
57
63
 
58
64
  ``` ruby
59
- Undo.wrap object
65
+ decorated_object = Undo.wrap object
66
+ Undo.restore decorated_object.uuid
60
67
  ```
68
+ Use decorated_object as usual afterwards. Undo gem will store object
69
+ state on each hit to `mutator methods`. By default mutator_methods are
70
+ `update`, `delete`, `destroy`. Those methods can be changed either in
71
+ place or using global configuration (see below).
72
+
73
+ To use something more advanced rather plain memory storage and
74
+ path though serializer, configure the Undo:
75
+
76
+ ``` ruby
77
+ Undo.configure do |config|
78
+ config.storage = Undo::Storage::RailsCache
79
+ config.serializer = Undo::Serializer::ActiveModel
80
+ end
81
+ ```
82
+ gem `undo-storage-rails_cache` and gem `undo-serializer-active_model` are required for this.
83
+ There are a bunch of other Rails free adapters. Read about them in configuration chapter below.
61
84
 
62
- And use it as usual afterwards. Undo gem will store object state on each hit to `mutator methods`.
63
- By default mutator_methods are `update`, `delete`, `destroy`.
64
85
  To append custom mutator_methods use
65
86
 
66
87
  ``` ruby
@@ -69,36 +90,47 @@ Undo.configure do |config|
69
90
  end
70
91
  ```
71
92
 
72
- To restore previous version
93
+ To define custom uuid generator use `uuid_generator` option:
73
94
 
74
- ```
75
- Undo.restore uuid
95
+ ``` ruby
96
+ Undo.configure do |config|
97
+ config.uuid_generator = ->(object) { "#{object.class.name}_#{object.id}" }
98
+ end
76
99
  ```
77
100
 
78
- `uuid` is provided by wrapped object:
101
+ ### UUID
79
102
 
80
- ```
81
- Undo.wrap(object).uuid
103
+ By default uuids are generated by `SecureRandom.uuid`.
104
+
105
+ UUID can be provided to both #wrap and #store methods and it will be used instead of generated one:
106
+
107
+ ``` ruby
108
+ uuid = "uniq identifier"
109
+
110
+ Undo.store object, uuid: uuid
111
+ Undo.restore uuid
82
112
  ```
83
113
 
84
- By default it is using `SecureRandom.uuid`.
85
- To define custom uuid generator use `uuid_generator` option:
114
+ If object respond to #uuid method then it value will be used instead:
86
115
 
87
116
  ``` ruby
88
- Undo.configure do |config|
89
- config.uuid_generator = ->(object) { "#{object.class.name}_#{object.id}" }
90
- end
117
+ object = OpenStruct.new uuid: "uniq identifier"
118
+ Undo.store object # => uniq identifier
119
+ Undo.restore "uniq identifier"
91
120
  ```
92
121
 
93
122
  ### Configuration options
123
+
94
124
  `storage` option responsible for putting and fetching object state to or from some storage.
95
125
  Implement `put(uuid, object)` and `fetch(uuid)` methods.
96
126
  Currently available storages:
97
127
  * `Undo::Storage::Memory` simple runtime storage (Hash)
128
+ * `gem "undo-storage-rails_cache"` designed for Rails, but can be used with any ducktype cache store
98
129
  * `gem "undo-storage-redis"` designed to be used with `gem "redis"` from v0.1 to current
99
130
 
100
131
  See also [documentation](http://github.com/AlexParamonov/undo)
101
- on project repository for full list of currently available storage adapters.
132
+ on project repository for full list of currently available storage adapters.
133
+
102
134
  To convert objects to data that can be processed by storage adapters and backward, use `serializers`:
103
135
 
104
136
  ``` ruby
@@ -109,6 +141,7 @@ end
109
141
 
110
142
  Currently available serializers:
111
143
  * `Undo::Serializer::Null` pass though serializer. It do nothing and returns whatever passed to it.
144
+ * `gem undo-serializer-active_model`
112
145
 
113
146
  Check [documentation](http://github.com/AlexParamonov/undo) on project
114
147
  repository for currently available serializers.
@@ -135,6 +168,7 @@ end
135
168
  ```
136
169
 
137
170
  ### In place configuration
171
+
138
172
  Any configuration option from previous chapter can be applied in
139
173
  place for given operation. To restore object from another storage use
140
174
  `storage` option:
@@ -1,24 +1,44 @@
1
1
  require "undo/version"
2
2
  require "undo/config"
3
+ require "undo/wrapper"
3
4
 
4
5
  module Undo
5
- require "undo/model"
6
-
7
6
  def self.configure(&block)
8
7
  block_given? ? block.call(config) : config
9
8
  end
10
9
 
11
- def self.config
12
- @config ||= Undo::Config.new
10
+ def self.store(object, options = {})
11
+ config.with(options) do |config|
12
+ uuid(object, options).tap do |uuid|
13
+ config.storage.put uuid, config.serializer.serialize(object)
14
+ end
15
+ end
13
16
  end
14
17
 
15
- def self.wrap(object, *args)
16
- Model.new object, *args
18
+ def self.restore(uuid, options = {})
19
+ config.with(options) do |config|
20
+ config.serializer.deserialize config.storage.fetch(uuid)
21
+ end
17
22
  end
18
23
 
19
- def self.restore(uuid, options = {})
24
+ def self.wrap(object, options = {})
20
25
  config.with(options) do |config|
21
- config.serializer.deserialize config.storage.fetch uuid
26
+ Wrapper.new(
27
+ object,
28
+ uuid(object, options),
29
+ mutator_methods: config.mutator_methods
30
+ )
22
31
  end
23
32
  end
33
+
34
+ private
35
+ def self.uuid(object, options = {})
36
+ options[:uuid] || config.uuid_generator.call(object)
37
+ end
38
+
39
+ def self.config
40
+ @config ||= Undo::Config.new
41
+ end
42
+
43
+ private_class_method :uuid, :config
24
44
  end
@@ -1,3 +1,3 @@
1
1
  module Undo
2
- VERSION = "0.0.3"
2
+ VERSION = "0.1.0"
3
3
  end
@@ -0,0 +1,29 @@
1
+ require "forwardable"
2
+
3
+ module Undo
4
+ class Wrapper < SimpleDelegator
5
+ extend Forwardable
6
+ def_delegators :object, :class, :kind_of?
7
+ attr_reader :uuid
8
+
9
+ def initialize(object, uuid, options = {})
10
+ @object = object
11
+ @mutator_methods = options.fetch :mutator_methods, []
12
+ @uuid = object.respond_to?(:uuid) ? object.uuid : uuid
13
+
14
+ super object
15
+ end
16
+
17
+ def method_missing(method, *args, &block)
18
+ store if mutator_methods.include? method
19
+ super method, *args, &block
20
+ end
21
+
22
+ private
23
+ attr_reader :object, :mutator_methods
24
+
25
+ def store
26
+ Undo.store object, uuid: uuid
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,31 @@
1
+ require "spec_helper_lite"
2
+
3
+ describe Undo::Wrapper do
4
+ subject { described_class }
5
+ let(:model) { subject.new object, uuid }
6
+ let(:object) { double :object, change: true }
7
+ let(:uuid) { double :uuid }
8
+
9
+ describe "storage" do
10
+ let(:model) { subject.new object, uuid, mutator_methods: mutator_methods }
11
+ let(:mutator_methods) { [:change] }
12
+
13
+ it "stores object when mutator method is called" do
14
+ expect(model).to receive(:store)
15
+ model.change
16
+ end
17
+ end
18
+
19
+ describe "#uuid" do
20
+ it "uses provided uuid" do
21
+ expect(model.uuid).to eq uuid
22
+ end
23
+
24
+ describe "when object respond_to uuid" do
25
+ it "uses object#uuid instead" do
26
+ expect(object).to receive(:uuid) { "123" }
27
+ expect(model.uuid).to eq "123"
28
+ end
29
+ end
30
+ end
31
+ end
@@ -4,6 +4,43 @@ describe Undo do
4
4
  let(:object) { double :object, change: true }
5
5
  subject { described_class }
6
6
 
7
+ it "stores and restores object" do
8
+ uuid = subject.store object
9
+ expect(subject.restore uuid).to eq object
10
+ end
11
+
12
+ it "stores and restores object using provided uuid" do
13
+ uuid = "uniq_identifier"
14
+ subject.store object, uuid: uuid
15
+
16
+ expect(subject.restore uuid).to eq object
17
+ end
18
+
19
+ describe "serializing" do
20
+ let(:storage) { double :storage }
21
+ let(:serializer) { double :serializer }
22
+
23
+ it "serializes data before storing" do
24
+ expect(serializer).to receive(:serialize).with(object).ordered
25
+ expect(storage).to receive(:put).ordered
26
+
27
+ subject.store object,
28
+ storage: storage,
29
+ serializer: serializer
30
+ end
31
+
32
+ it "deserializes data before restoring" do
33
+ uuid = subject.store object
34
+
35
+ expect(storage).to receive(:fetch).and_return(foo: :bar).ordered
36
+ expect(serializer).to receive(:deserialize).with(foo: :bar).ordered
37
+
38
+ subject.restore uuid,
39
+ storage: storage,
40
+ serializer: serializer
41
+ end
42
+ end
43
+
7
44
  describe "#wrap" do
8
45
  before do
9
46
  subject.configure do |config|
@@ -21,26 +58,22 @@ describe Undo do
21
58
  expect(decorator.class).to eq Array
22
59
  expect(decorator).to be_a Array
23
60
  end
24
- end
25
61
 
26
- describe "restores object by uuid" do
27
- it "restores object" do
28
- model = subject.wrap object
29
- model.change
30
- restored_object = subject.restore model.uuid
62
+ describe "restores" do
63
+ specify "using provided uuid" do
64
+ uuid = "uniq_identifier"
65
+ model = subject.wrap object, uuid: uuid
66
+ model.change
31
67
 
32
- expect(restored_object).to eq object
33
- end
34
-
35
- it "restores using provided options" do
36
- serializer = double :serializer
37
- expect(serializer).to receive(:deserialize) { object }
68
+ expect(subject.restore uuid).to eq object
69
+ end
38
70
 
39
- model = subject.wrap object
40
- model.change
41
- restored_object = subject.restore model.uuid, serializer: serializer
71
+ specify "using gerenated uuid" do
72
+ model = subject.wrap object
73
+ model.change
42
74
 
43
- expect(restored_object).to eq object
75
+ expect(subject.restore model.uuid).to eq object
76
+ end
44
77
  end
45
78
  end
46
79
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: undo
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Alexander Paramonov
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-16 00:00:00.000000000 Z
11
+ date: 2014-03-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: virtus
@@ -92,14 +92,14 @@ files:
92
92
  - Rakefile
93
93
  - lib/undo.rb
94
94
  - lib/undo/config.rb
95
- - lib/undo/model.rb
96
95
  - lib/undo/serializer/null.rb
97
96
  - lib/undo/storage/memory.rb
98
97
  - lib/undo/version.rb
98
+ - lib/undo/wrapper.rb
99
99
  - spec/spec_helper_lite.rb
100
- - spec/undo/model_spec.rb
101
100
  - spec/undo/serializer/null_spec.rb
102
101
  - spec/undo/storage/memory_spec.rb
102
+ - spec/undo/wrapper_spec.rb
103
103
  - spec/undo_spec.rb
104
104
  - undo.gemspec
105
105
  homepage: http://github.com/AlexParamonov/undo
@@ -122,14 +122,14 @@ required_rubygems_version: !ruby/object:Gem::Requirement
122
122
  version: '0'
123
123
  requirements: []
124
124
  rubyforge_project:
125
- rubygems_version: 2.2.2
125
+ rubygems_version: 2.1.11
126
126
  signing_key:
127
127
  specification_version: 4
128
128
  summary: Reverts operation made upon object
129
129
  test_files:
130
130
  - spec/spec_helper_lite.rb
131
- - spec/undo/model_spec.rb
132
131
  - spec/undo/serializer/null_spec.rb
133
132
  - spec/undo/storage/memory_spec.rb
133
+ - spec/undo/wrapper_spec.rb
134
134
  - spec/undo_spec.rb
135
135
  has_rdoc:
@@ -1,38 +0,0 @@
1
- require "forwardable"
2
-
3
- module Undo
4
- class Model < SimpleDelegator
5
- extend Forwardable
6
- def_delegators :object, :class, :kind_of?
7
-
8
- def initialize(object, options = {})
9
- @object = object
10
- @config = config.with options
11
- super object
12
- end
13
-
14
- def uuid
15
- @uuid ||= object.respond_to?(:uuid) ? object.uuid : generate_uuid
16
- end
17
-
18
- def method_missing(method, *args, &block)
19
- store if config.mutator_methods.include? method
20
- super method, *args, &block
21
- end
22
-
23
- private
24
- attr_reader :object
25
-
26
- def generate_uuid
27
- config.uuid_generator.call object
28
- end
29
-
30
- def store
31
- config.storage.put uuid, config.serializer.serialize(object)
32
- end
33
-
34
- def config
35
- @config ||= Undo.config
36
- end
37
- end
38
- end
@@ -1,61 +0,0 @@
1
- require "spec_helper_lite"
2
-
3
- describe Undo::Model do
4
- subject { described_class }
5
- let(:model) { subject.new object }
6
- let(:object) { double :object }
7
-
8
- describe "#uuid" do
9
- it "using object#uuid" do
10
- expect(object).to receive(:uuid) { "123" }
11
- expect(model.uuid).to eq "123"
12
- end
13
-
14
- context "object do not respond to #uuid" do
15
- it "using configured uuid gerenator" do
16
- model = subject.new object, uuid_generator: proc { "123" }
17
- expect(model.uuid).to eq "123"
18
- end
19
-
20
- it "using SecureRandom uuid gerenator by default" do
21
- expect(SecureRandom).to receive(:uuid) { "123" }
22
- expect(model.uuid).to eq "123"
23
- end
24
-
25
- it "passes object to custom uuid gerenator" do
26
- uuid_generator = double :uuid_generator
27
- expect(uuid_generator).to receive(:call).with(object)
28
-
29
- model = subject.new object, uuid_generator: uuid_generator
30
- model.uuid
31
- end
32
-
33
- end
34
-
35
- describe "stores object data" do
36
- let(:object) { double :object, change: true }
37
- let(:storage) { double :storage }
38
- let(:serializer) { double :serializer }
39
-
40
- specify "when called mutator method" do
41
- expect(storage).to receive(:put)
42
-
43
- model = subject.new object,
44
- storage: storage,
45
- mutator_methods: [:change]
46
- model.change
47
- end
48
-
49
- it "serializes data before storing" do
50
- expect(serializer).to receive(:serialize).with(object).ordered
51
- expect(storage).to receive(:put).ordered
52
-
53
- model = subject.new object,
54
- storage: storage,
55
- serializer: serializer,
56
- mutator_methods: [:change]
57
- model.change
58
- end
59
- end
60
- end
61
- end