memento 0.3.0 → 0.3.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|