memento 0.3.0 → 0.3.1
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.
- data/.gitignore +1 -0
- data/README.rdoc +1 -1
- data/Rakefile +12 -14
- data/VERSION.yml +2 -2
- data/generators/memento_migration/templates/migration.rb +1 -1
- data/{rails/init.rb → init.rb} +0 -0
- data/lib/memento.rb +10 -3
- data/lib/memento/action/update.rb +3 -4
- data/lib/memento/action_controller_methods.rb +1 -2
- data/lib/memento/active_record_methods.rb +10 -6
- data/lib/memento/result.rb +2 -1
- data/lib/memento/session.rb +1 -1
- data/lib/memento/state.rb +1 -1
- data/memento.gemspec +5 -5
- data/spec/memento/action/create_spec.rb +1 -1
- data/spec/memento/action/update_spec.rb +2 -2
- data/spec/memento/action_controller_methods_spec.rb +1 -3
- data/spec/memento/active_record_methods_spec.rb +2 -2
- data/spec/memento/session_spec.rb +1 -1
- data/spec/memento/state_spec.rb +4 -4
- data/spec/spec_helper.rb +6 -10
- metadata +15 -6
data/.gitignore
CHANGED
data/README.rdoc
CHANGED
data/Rakefile
CHANGED
@@ -1,5 +1,17 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
|
+
require "rspec/core/rake_task"
|
4
|
+
|
5
|
+
RSpec::Core::RakeTask.new(:spec) do |spec|
|
6
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
7
|
+
end
|
8
|
+
|
9
|
+
RSpec::Core::RakeTask.new(:rcov) do |spec|
|
10
|
+
spec.pattern = 'spec/**/*_spec.rb'
|
11
|
+
spec.rcov = true
|
12
|
+
end
|
13
|
+
|
14
|
+
task :default => :spec
|
3
15
|
|
4
16
|
begin
|
5
17
|
require 'jeweler'
|
@@ -17,17 +29,3 @@ rescue LoadError
|
|
17
29
|
puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
|
18
30
|
end
|
19
31
|
|
20
|
-
require 'spec/rake/spectask'
|
21
|
-
Spec::Rake::SpecTask.new(:spec) do |spec|
|
22
|
-
spec.libs << 'lib' << 'spec'
|
23
|
-
spec.spec_files = FileList['spec/**/*_spec.rb']
|
24
|
-
end
|
25
|
-
|
26
|
-
Spec::Rake::SpecTask.new(:rcov) do |spec|
|
27
|
-
spec.libs << 'lib' << 'spec'
|
28
|
-
spec.pattern = 'spec/**/*_spec.rb'
|
29
|
-
spec.rcov = true
|
30
|
-
end
|
31
|
-
|
32
|
-
task :default => :spec
|
33
|
-
|
data/VERSION.yml
CHANGED
@@ -8,7 +8,7 @@ class MementoMigration < ActiveRecord::Migration
|
|
8
8
|
|
9
9
|
create_table :memento_states do |t|
|
10
10
|
t.string :action_type
|
11
|
-
t.binary :record_data, :limit =>
|
11
|
+
t.binary :record_data, :limit => 16777215
|
12
12
|
t.references :record, :polymorphic => true
|
13
13
|
t.references :session
|
14
14
|
t.timestamps
|
data/{rails/init.rb → init.rb}
RENAMED
File without changes
|
data/lib/memento.rb
CHANGED
@@ -1,3 +1,5 @@
|
|
1
|
+
require 'active_record'
|
2
|
+
|
1
3
|
class Memento
|
2
4
|
include Singleton
|
3
5
|
|
@@ -12,7 +14,7 @@ class Memento
|
|
12
14
|
end
|
13
15
|
|
14
16
|
def start(user_or_id)
|
15
|
-
user = User.find_by_id(user_or_id)
|
17
|
+
user = user_or_id.is_a?(User) ? user_or_id : User.find_by_id(user_or_id)
|
16
18
|
@session = user ? Memento::Session.new(:user => user) : nil
|
17
19
|
end
|
18
20
|
|
@@ -37,8 +39,13 @@ class Memento
|
|
37
39
|
@ignore = false
|
38
40
|
end
|
39
41
|
|
40
|
-
|
41
|
-
|
42
|
+
def self.serializer=(serializer)
|
43
|
+
@serializer = serializer
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.serializer
|
47
|
+
@serializer ||= YAML
|
48
|
+
end
|
42
49
|
|
43
50
|
private
|
44
51
|
|
@@ -21,7 +21,7 @@ class Memento::Action::Update < Memento::Action::Base
|
|
21
21
|
private
|
22
22
|
|
23
23
|
def update_record
|
24
|
-
|
24
|
+
record.tap do |object|
|
25
25
|
record_data.each do |attribute, values|
|
26
26
|
object.send(:"#{attribute}=", values.first)
|
27
27
|
end
|
@@ -35,20 +35,19 @@ class Memento::Action::Update < Memento::Action::Base
|
|
35
35
|
values = values.map{|v| v.is_a?(Time) ? v.to_s(:db) : v }
|
36
36
|
current_value = record.send(:"#{attribute}")
|
37
37
|
current_value = current_value.utc.to_s(:db) if current_value.is_a?(Time)
|
38
|
-
|
39
38
|
values.include?(current_value)
|
40
39
|
end || record_data.size.zero?
|
41
40
|
end
|
42
41
|
|
43
42
|
def was_destroyed
|
44
43
|
new_object do |object|
|
45
|
-
object.errors
|
44
|
+
object.errors[:memento_undo] << ActiveSupport::StringInquirer.new("was_destroyed")
|
46
45
|
object.id = state.record_id
|
47
46
|
end
|
48
47
|
end
|
49
48
|
|
50
49
|
def was_changed
|
51
|
-
record.errors
|
50
|
+
record.errors[:memento_undo] << ActiveSupport::StringInquirer.new("was_changed")
|
52
51
|
record
|
53
52
|
end
|
54
53
|
|
@@ -1,8 +1,6 @@
|
|
1
1
|
class Memento
|
2
2
|
module ActionControllerMethods
|
3
3
|
|
4
|
-
private
|
5
|
-
|
6
4
|
def memento
|
7
5
|
block_result = nil
|
8
6
|
memento_session = Memento.instance.memento(current_user) do
|
@@ -13,6 +11,7 @@ class Memento
|
|
13
11
|
end
|
14
12
|
block_result
|
15
13
|
end
|
14
|
+
private :memento
|
16
15
|
end
|
17
16
|
end
|
18
17
|
|
@@ -9,6 +9,12 @@ module Memento::ActiveRecordMethods
|
|
9
9
|
module ClassMethods
|
10
10
|
|
11
11
|
def memento_changes(*action_types)
|
12
|
+
if defined?(@memento_initialized) && @memento_initialized
|
13
|
+
raise "Memento initialized twice. Use memento_changes only once per model"
|
14
|
+
end
|
15
|
+
|
16
|
+
@memento_initialized = true
|
17
|
+
|
12
18
|
include InstanceMethods
|
13
19
|
|
14
20
|
self.memento_options = action_types.last.is_a?(Hash) ? action_types.pop : {}
|
@@ -20,10 +26,7 @@ module Memento::ActiveRecordMethods
|
|
20
26
|
end
|
21
27
|
|
22
28
|
action_types.each do |action_type|
|
23
|
-
|
24
|
-
callback.method.to_sym == :"record_#{action_type}"
|
25
|
-
end
|
26
|
-
send :"after_#{action_type}", :"record_#{action_type}" unless callback_exists
|
29
|
+
send :"after_#{action_type}", :"record_#{action_type}"
|
27
30
|
end
|
28
31
|
|
29
32
|
has_many :memento_states, :class_name => "Memento::State", :as => :record
|
@@ -50,22 +53,23 @@ module Memento::ActiveRecordMethods
|
|
50
53
|
filter_attributes_for_memento(changes)
|
51
54
|
end
|
52
55
|
|
53
|
-
private
|
54
|
-
|
55
56
|
def filter_attributes_for_memento(hash)
|
56
57
|
hash.delete_if do |key, value|
|
57
58
|
ignore_attributes_for_memento.include?(key.to_sym)
|
58
59
|
end
|
59
60
|
end
|
61
|
+
private :filter_attributes_for_memento
|
60
62
|
|
61
63
|
def ignore_attributes_for_memento
|
62
64
|
Memento::ActiveRecordMethods::IGNORE_ATTRIBUTES + (self.class.memento_options[:ignore] || [])
|
63
65
|
end
|
66
|
+
private :ignore_attributes_for_memento
|
64
67
|
|
65
68
|
Memento::Action::Base.action_types.each do |action_type|
|
66
69
|
define_method :"record_#{action_type}" do
|
67
70
|
Memento.instance.add_state(action_type, self)
|
68
71
|
end
|
72
|
+
private :"record_#{action_type}"
|
69
73
|
end
|
70
74
|
end
|
71
75
|
|
data/lib/memento/result.rb
CHANGED
data/lib/memento/session.rb
CHANGED
data/lib/memento/state.rb
CHANGED
@@ -27,7 +27,7 @@ class Memento::State < ActiveRecord::Base
|
|
27
27
|
|
28
28
|
def record_data=(data)
|
29
29
|
@record_data = nil
|
30
|
-
write_attribute(:record_data, Memento.serializer.dump(data))
|
30
|
+
write_attribute(:record_data, data.is_a?(String) ? data : Memento.serializer.dump(data))
|
31
31
|
end
|
32
32
|
|
33
33
|
def fetch?
|
data/memento.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{memento}
|
8
|
-
s.version = "0.3.
|
8
|
+
s.version = "0.3.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Yolk Sebastian Munz & Julia Soergel GbR"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-11-14}
|
13
13
|
s.email = %q{sebastian@yo.lk}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -25,6 +25,7 @@ Gem::Specification.new do |s|
|
|
25
25
|
"VERSION.yml",
|
26
26
|
"generators/memento_migration/memento_migration_generator.rb",
|
27
27
|
"generators/memento_migration/templates/migration.rb",
|
28
|
+
"init.rb",
|
28
29
|
"lib/memento.rb",
|
29
30
|
"lib/memento/action.rb",
|
30
31
|
"lib/memento/action/create.rb",
|
@@ -36,7 +37,6 @@ Gem::Specification.new do |s|
|
|
36
37
|
"lib/memento/session.rb",
|
37
38
|
"lib/memento/state.rb",
|
38
39
|
"memento.gemspec",
|
39
|
-
"rails/init.rb",
|
40
40
|
"spec/memento/action/create_spec.rb",
|
41
41
|
"spec/memento/action/destroy_spec.rb",
|
42
42
|
"spec/memento/action/update_spec.rb",
|
@@ -51,7 +51,7 @@ Gem::Specification.new do |s|
|
|
51
51
|
s.homepage = %q{http://github.com/yolk/memento}
|
52
52
|
s.rdoc_options = ["--charset=UTF-8"]
|
53
53
|
s.require_paths = ["lib"]
|
54
|
-
s.rubygems_version = %q{1.3.
|
54
|
+
s.rubygems_version = %q{1.3.7}
|
55
55
|
s.summary = %q{Undo for Rails/ActiveRecord - covers destroy, update and create}
|
56
56
|
s.test_files = [
|
57
57
|
"spec/memento/action/create_spec.rb",
|
@@ -70,7 +70,7 @@ Gem::Specification.new do |s|
|
|
70
70
|
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
71
71
|
s.specification_version = 3
|
72
72
|
|
73
|
-
if Gem::Version.new(Gem::
|
73
|
+
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
74
74
|
else
|
75
75
|
end
|
76
76
|
else
|
@@ -40,7 +40,7 @@ describe Memento::Action::Create, "when object is created" do
|
|
40
40
|
undone = Memento::Session.last.undo
|
41
41
|
Project.count.should eql(1)
|
42
42
|
undone.first.should_not be_success
|
43
|
-
undone.first.error.should be_was_changed
|
43
|
+
undone.first.error.first.should be_was_changed
|
44
44
|
end
|
45
45
|
|
46
46
|
describe "when record was already destroyed" do
|
@@ -58,7 +58,7 @@ describe Memento::Action::Update do
|
|
58
58
|
it "should return fake object with error" do
|
59
59
|
undone = Memento::Session.last.undo.first
|
60
60
|
undone.should_not be_success
|
61
|
-
undone.error.should be_was_destroyed
|
61
|
+
undone.error.first.should be_was_destroyed
|
62
62
|
undone.object.class.should eql(Project)
|
63
63
|
undone.object.id.should eql(1)
|
64
64
|
end
|
@@ -140,7 +140,7 @@ describe Memento::Action::Update do
|
|
140
140
|
end
|
141
141
|
|
142
142
|
it "should set error" do
|
143
|
-
@result.error.should be_was_changed
|
143
|
+
@result.error.first.should be_was_changed
|
144
144
|
end
|
145
145
|
|
146
146
|
it "should return not undone object" do
|
@@ -2,8 +2,6 @@ require File.join(File.dirname(__FILE__), '..', 'spec_helper')
|
|
2
2
|
|
3
3
|
class FooController < ActionController::Base
|
4
4
|
|
5
|
-
private
|
6
|
-
|
7
5
|
end
|
8
6
|
|
9
7
|
describe Memento::ActionControllerMethods do
|
@@ -22,7 +20,7 @@ describe Memento::ActionControllerMethods do
|
|
22
20
|
end
|
23
21
|
|
24
22
|
it "should add memento-method to ActionController::Base" do
|
25
|
-
FooController.private_instance_methods.should include(
|
23
|
+
FooController.private_instance_methods.map(&:to_sym).should include(:memento)
|
26
24
|
end
|
27
25
|
|
28
26
|
it "should call memento#memento with user and block" do
|
@@ -7,8 +7,8 @@ describe Memento::ActiveRecordMethods do
|
|
7
7
|
setup_data
|
8
8
|
end
|
9
9
|
|
10
|
-
it "should declare
|
11
|
-
Project.private_instance_methods.should include(
|
10
|
+
it "should declare protected methods on Project" do
|
11
|
+
Project.private_instance_methods.map(&:to_sym).should include(:record_destroy, :record_update, :record_create)
|
12
12
|
end
|
13
13
|
|
14
14
|
it "should set hook on create to call Memento" do
|
data/spec/memento/state_spec.rb
CHANGED
@@ -13,12 +13,12 @@ describe Memento::State do
|
|
13
13
|
end
|
14
14
|
|
15
15
|
it "should require session" do
|
16
|
-
Memento::State.create.errors[:session].should eql("can't be blank")
|
16
|
+
Memento::State.create.errors[:session].should eql(["can't be blank"])
|
17
17
|
end
|
18
18
|
|
19
19
|
it "should require action_type to be one of Memento::State::RECORD_CAUSES" do
|
20
|
-
Memento::State.create.errors[:action_type].should eql("can't be blank")
|
21
|
-
Memento::State.create(:action_type => "move").errors[:action_type].should eql("is not included in the list")
|
20
|
+
Memento::State.create.errors[:action_type].should eql(["can't be blank"])
|
21
|
+
Memento::State.create(:action_type => "move").errors[:action_type].should eql(["is not included in the list"])
|
22
22
|
end
|
23
23
|
|
24
24
|
it "should belong to polymorphic record" do
|
@@ -27,7 +27,7 @@ describe Memento::State do
|
|
27
27
|
end
|
28
28
|
|
29
29
|
it "should require record" do
|
30
|
-
Memento::State.create.errors[:record].should eql("can't be blank")
|
30
|
+
Memento::State.create.errors[:record].should eql(["can't be blank"])
|
31
31
|
end
|
32
32
|
|
33
33
|
|
data/spec/spec_helper.rb
CHANGED
@@ -2,7 +2,7 @@ require 'rubygems'
|
|
2
2
|
require 'active_support'
|
3
3
|
require 'active_record'
|
4
4
|
require 'action_controller'
|
5
|
-
require '
|
5
|
+
require 'rspec'
|
6
6
|
|
7
7
|
# Initialize time_zones from rails
|
8
8
|
Time.zone_default = Time.__send__(:get_zone, 'Berlin') || raise("Err")
|
@@ -13,10 +13,6 @@ $:.unshift(File.dirname(__FILE__))
|
|
13
13
|
$:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
14
|
require 'memento'
|
15
15
|
|
16
|
-
Spec::Runner.configure do |config|
|
17
|
-
|
18
|
-
end
|
19
|
-
|
20
16
|
ActiveRecord::Base.establish_connection(:adapter => "sqlite3", :database => ":memory:")
|
21
17
|
# catch AR schema statements
|
22
18
|
$stdout = StringIO.new
|
@@ -54,7 +50,7 @@ def setup_db
|
|
54
50
|
|
55
51
|
create_table :memento_states do |t|
|
56
52
|
t.string :action_type
|
57
|
-
t.binary :record_data, :limit =>
|
53
|
+
t.binary :record_data, :limit => 16777215
|
58
54
|
t.references :record, :polymorphic => true
|
59
55
|
t.references :session
|
60
56
|
t.timestamps
|
@@ -74,18 +70,18 @@ def shutdown_db
|
|
74
70
|
end
|
75
71
|
|
76
72
|
class User < ActiveRecord::Base
|
77
|
-
end
|
73
|
+
end unless defined?(User)
|
78
74
|
|
79
75
|
class Customer < ActiveRecord::Base
|
80
76
|
has_many :projects
|
81
|
-
end
|
77
|
+
end unless defined?(Customer)
|
82
78
|
|
83
79
|
class Project < ActiveRecord::Base
|
84
80
|
belongs_to :customer
|
85
81
|
|
86
82
|
memento_changes :ignore => :ignore_this
|
87
|
-
end
|
83
|
+
end unless defined?(Project)
|
88
84
|
|
89
85
|
class TimestamplessObject < ActiveRecord::Base
|
90
86
|
memento_changes
|
91
|
-
end
|
87
|
+
end unless defined?(TimestamplessObject)
|
metadata
CHANGED
@@ -1,7 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: memento
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 3
|
8
|
+
- 1
|
9
|
+
version: 0.3.1
|
5
10
|
platform: ruby
|
6
11
|
authors:
|
7
12
|
- Yolk Sebastian Munz & Julia Soergel GbR
|
@@ -9,7 +14,7 @@ autorequire:
|
|
9
14
|
bindir: bin
|
10
15
|
cert_chain: []
|
11
16
|
|
12
|
-
date: 2010-
|
17
|
+
date: 2010-11-14 00:00:00 +01:00
|
13
18
|
default_executable:
|
14
19
|
dependencies: []
|
15
20
|
|
@@ -32,6 +37,7 @@ files:
|
|
32
37
|
- VERSION.yml
|
33
38
|
- generators/memento_migration/memento_migration_generator.rb
|
34
39
|
- generators/memento_migration/templates/migration.rb
|
40
|
+
- init.rb
|
35
41
|
- lib/memento.rb
|
36
42
|
- lib/memento/action.rb
|
37
43
|
- lib/memento/action/create.rb
|
@@ -43,7 +49,6 @@ files:
|
|
43
49
|
- lib/memento/session.rb
|
44
50
|
- lib/memento/state.rb
|
45
51
|
- memento.gemspec
|
46
|
-
- rails/init.rb
|
47
52
|
- spec/memento/action/create_spec.rb
|
48
53
|
- spec/memento/action/destroy_spec.rb
|
49
54
|
- spec/memento/action/update_spec.rb
|
@@ -64,21 +69,25 @@ rdoc_options:
|
|
64
69
|
require_paths:
|
65
70
|
- lib
|
66
71
|
required_ruby_version: !ruby/object:Gem::Requirement
|
72
|
+
none: false
|
67
73
|
requirements:
|
68
74
|
- - ">="
|
69
75
|
- !ruby/object:Gem::Version
|
76
|
+
segments:
|
77
|
+
- 0
|
70
78
|
version: "0"
|
71
|
-
version:
|
72
79
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
80
|
+
none: false
|
73
81
|
requirements:
|
74
82
|
- - ">="
|
75
83
|
- !ruby/object:Gem::Version
|
84
|
+
segments:
|
85
|
+
- 0
|
76
86
|
version: "0"
|
77
|
-
version:
|
78
87
|
requirements: []
|
79
88
|
|
80
89
|
rubyforge_project:
|
81
|
-
rubygems_version: 1.3.
|
90
|
+
rubygems_version: 1.3.7
|
82
91
|
signing_key:
|
83
92
|
specification_version: 3
|
84
93
|
summary: Undo for Rails/ActiveRecord - covers destroy, update and create
|