genki-dm-has-versions 0.1.1 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
data/Rakefile CHANGED
@@ -5,7 +5,7 @@ require 'merb-core'
5
5
  require 'merb-core/tasks/merb'
6
6
 
7
7
  GEM_NAME = "dm-has-versions"
8
- GEM_VERSION = "0.1.1"
8
+ GEM_VERSION = "0.2.0"
9
9
  AUTHOR = "Genki Takiuchi"
10
10
  EMAIL = "genki@s21g.com"
11
11
  HOMEPAGE = "http://blog.s21g.com/genki"
@@ -4,13 +4,16 @@ module DataMapper
4
4
  class RevertError < StandardError; end
5
5
 
6
6
  def has_versions(options = {})
7
+ original_class = self
8
+ original_name = name.snake_case
9
+ storage_name = Extlib::Inflection.tableize(name + "Version")
10
+
7
11
  ignores = [options[:ignore]].flatten.compact.map do |ignore|
8
12
  properties[ignore.to_s.intern]
9
13
  end
10
14
 
11
15
  class << self; self end.class_eval do
12
16
  define_method :const_missing do |name|
13
- storage_name = Extlib::Inflection.tableize(self.name + "Version")
14
17
  model = DataMapper::Model.new(storage_name)
15
18
 
16
19
  if name == :Version
@@ -20,6 +23,12 @@ module DataMapper
20
23
  end
21
24
  model.belongs_to self.storage_name.singular.intern
22
25
 
26
+ model.class_eval do
27
+ define_method("to_#{original_name}") do
28
+ original_class.new.tap{|object| object.send :copy, self}
29
+ end
30
+ end
31
+
23
32
  self.const_set("Version", model)
24
33
  else
25
34
  super(name)
@@ -27,6 +36,10 @@ module DataMapper
27
36
  end
28
37
  end
29
38
 
39
+ if options[:revision] != false
40
+ ignores << property(:revision, Integer, :unique_index => true)
41
+ end
42
+
30
43
  self.after_class_method :auto_migrate! do
31
44
  self::Version.auto_migrate!
32
45
  end
@@ -66,6 +79,17 @@ module DataMapper
66
79
  end
67
80
 
68
81
  module InstanceMethods
82
+ def self.included(base)
83
+ base.class_eval do
84
+ def revision=(revision)
85
+ if target = versions.get(revision)
86
+ copy(target)
87
+ self.attribute_set :revision, revision
88
+ end
89
+ !!target
90
+ end
91
+ end
92
+ end
69
93
  ##
70
94
  # Returns a hash of original values to be stored in the
71
95
  # versions table when a new version is created. It is
@@ -100,16 +124,16 @@ module DataMapper
100
124
 
101
125
  def version=(version)
102
126
  if target = versions.first(:offset => version)
103
- self.properties.each do |property|
104
- next if property.key?
105
- name = property.name
106
- self.attribute_set(name, target.attribute_get(name))
107
- end
127
+ copy(target)
108
128
  @version = version
109
129
  end
110
130
  !!target
111
131
  end
112
132
 
133
+ def revisions
134
+ versions.all(:order => [:id.asc]).map(&:id)
135
+ end
136
+
113
137
  def revert_to!(version)
114
138
  self.version = version
115
139
  pending_version_attributes.clear
@@ -128,6 +152,15 @@ module DataMapper
128
152
  def revert
129
153
  revert_to(version) or raise RevertError
130
154
  end
155
+
156
+ private
157
+ def copy(target)
158
+ self.properties.each do |property|
159
+ next if property.key?
160
+ name = property.name
161
+ self.attribute_set(name, target.attribute_get(name))
162
+ end
163
+ end
131
164
  end
132
165
  end
133
166
  end
@@ -109,6 +109,49 @@ describe "dm-has-versions" do
109
109
  story.comments.should_not be_empty
110
110
  story.comments.last.body.should == "Hey, maiha!"
111
111
  end
112
+
113
+ it "should have revision methods" do
114
+ @story.should be_respond_to(:revision)
115
+ @story.revision.should be_nil
116
+ end
117
+
118
+ it "should return revision numbers" do
119
+ @story.should be_respond_to(:revisions)
120
+ revisions = @story.revisions
121
+ revisions.should be_a(Array)
122
+ revisions.should_not be_empty
123
+ revisions.first.should be_a(Integer)
124
+ revisions.should == revisions.sort
125
+ end
126
+
127
+ it "should be able to set revision" do
128
+ revisions = @story.revisions
129
+ last_title = @story.title
130
+ proc do
131
+ @story.save.should be_true
132
+ end.should_not change(Story::Version, :count)
133
+ proc do
134
+ @story.title = "foo01"
135
+ @story.save.should be_true
136
+ end.should change(Story::Version, :count)
137
+ @story.should_not be_dirty
138
+ @story.revision = @story.revisions.last
139
+ @story.should be_dirty
140
+ @story.title.should_not == "foo01"
141
+ @story.title.should == last_title
142
+ end
143
+
144
+ it "should be converted from version object" do
145
+ version = @story.versions.last
146
+ version.should be_a(Story::Version)
147
+ version.should be_respond_to(:to_story)
148
+ story = version.to_story
149
+ story.should be_a(Story)
150
+ story.attributes.each do |key, value|
151
+ next if key == :id
152
+ version.attributes[key].should == value
153
+ end
154
+ end
112
155
  end
113
156
  end
114
157
  end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --color
data/spec/spec_helper.rb CHANGED
@@ -16,7 +16,7 @@ Merb.start_environment(
16
16
  :adapter => 'runner',
17
17
  :environment => ENV['MERB_ENV'] || 'test',
18
18
  :merb_root => File.dirname(__FILE__) / 'fixture',
19
- :log_file => File.dirname(__FILE__) / "merb_test.log"
19
+ :log_file => File.dirname(__FILE__) / "../merb_test.log"
20
20
  )
21
21
  DataMapper.setup(:default, "sqlite3::memory:")
22
22
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: genki-dm-has-versions
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Genki Takiuchi
@@ -9,11 +9,12 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2009-01-16 00:00:00 -08:00
12
+ date: 2009-05-15 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: merb
17
+ type: :runtime
17
18
  version_requirement:
18
19
  version_requirements: !ruby/object:Gem::Requirement
19
20
  requirements:
@@ -47,7 +48,7 @@ files:
47
48
  - spec/fixture/app/models
48
49
  - spec/fixture/app/models/comment.rb
49
50
  - spec/fixture/app/models/story.rb
50
- - spec/merb_test.log
51
+ - spec/spec.opts
51
52
  - spec/spec_helper.rb
52
53
  has_rdoc: true
53
54
  homepage: http://blog.s21g.com/genki
@@ -73,7 +74,7 @@ requirements: []
73
74
  rubyforge_project: merb
74
75
  rubygems_version: 1.2.0
75
76
  signing_key:
76
- specification_version: 2
77
+ specification_version: 3
77
78
  summary: Merb plugin that provides version control for DataMapper models.
78
79
  test_files: []
79
80
 
data/spec/merb_test.log DELETED
@@ -1,108 +0,0 @@
1
- Thu, 15 Jan 2009 12:52:48 GMT ~ info ~ Logfile created
2
- ~ Could not load /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:
3
-
4
- uninitialized constant DataMapper::Has::Versioned - (NameError)
5
-
6
- /Users/takiuchi/project/dm-has-versions/spec/../lib/dm-has-versions/has/versions.rb:50:in `has_versions'
7
- /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:8
8
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
9
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
10
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:863:in `load_file'
11
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1018:in `load_classes_with_requirements'
12
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `each'
13
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `load_classes_with_requirements'
14
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:903:in `load_classes'
15
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:641:in `run'
16
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
17
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
18
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:639:in `run'
19
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:99:in `run'
20
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:172:in `bootup'
21
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:42:in `start'
22
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:170:in `start'
23
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:183:in `start_environment'
24
- /Users/takiuchi/project/dm-has-versions/spec/spec_helper.rb:13
25
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
26
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
27
- /Users/takiuchi/project/dm-has-versions/spec/dm-has-versions_spec.rb:1
28
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load'
29
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load_files'
30
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `each'
31
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `load_files'
32
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/options.rb:98:in `run_examples'
33
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/command_line.rb:10:in `run'
34
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/bin/spec:4
35
- /opt/local/bin/spec:19:in `load'
36
- /opt/local/bin/spec:19
37
- ~ Could not load /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:
38
-
39
- uninitialized constant DataMapper::Has::Versioned - (NameError)
40
-
41
- /Users/takiuchi/project/dm-has-versions/spec/../lib/dm-has-versions/has/versions.rb:50:in `has_versions'
42
- /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:8
43
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
44
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
45
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:863:in `load_file'
46
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1018:in `load_classes_with_requirements'
47
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `each'
48
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `load_classes_with_requirements'
49
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:903:in `load_classes'
50
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:641:in `run'
51
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
52
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
53
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:639:in `run'
54
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:99:in `run'
55
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:172:in `bootup'
56
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:42:in `start'
57
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:170:in `start'
58
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:183:in `start_environment'
59
- /Users/takiuchi/project/dm-has-versions/spec/spec_helper.rb:13
60
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
61
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
62
- /Users/takiuchi/project/dm-has-versions/spec/dm-has-versions_spec.rb:1
63
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load'
64
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load_files'
65
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `each'
66
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `load_files'
67
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/options.rb:98:in `run_examples'
68
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/command_line.rb:10:in `run'
69
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/bin/spec:4
70
- /opt/local/bin/spec:19:in `load'
71
- /opt/local/bin/spec:19
72
- ~ Could not load /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:
73
-
74
- undefined local variable or method `n' for #<Class:Story> - (NameError)
75
-
76
- /Users/takiuchi/project/dm-has-versions/spec/../lib/dm-has-versions/has/versions.rb:25:in `has_versions'
77
- /Users/takiuchi/project/dm-has-versions/spec/../lib/dm-has-versions/has/versions.rb:7:in `class_eval'
78
- /Users/takiuchi/project/dm-has-versions/spec/../lib/dm-has-versions/has/versions.rb:7:in `has_versions'
79
- /Users/takiuchi/project/dm-has-versions/spec/fixture/app/models/story.rb:8
80
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
81
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
82
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:863:in `load_file'
83
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1018:in `load_classes_with_requirements'
84
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `each'
85
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:1015:in `load_classes_with_requirements'
86
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:903:in `load_classes'
87
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:641:in `run'
88
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
89
- /opt/local/lib/ruby/gems/1.8/gems/extlib-0.9.9/lib/extlib/dictionary.rb:268:in `each'
90
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:639:in `run'
91
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/bootloader.rb:99:in `run'
92
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:172:in `bootup'
93
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core/server.rb:42:in `start'
94
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:170:in `start'
95
- /opt/local/lib/ruby/gems/1.8/gems/merb-core-1.0.7.1/lib/merb-core.rb:183:in `start_environment'
96
- /Users/takiuchi/project/dm-has-versions/spec/spec_helper.rb:14
97
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `gem_original_require'
98
- /opt/local/lib/ruby/site_ruby/1.8/rubygems/custom_require.rb:31:in `require'
99
- /Users/takiuchi/project/dm-has-versions/spec/dm-has-versions_spec.rb:1
100
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load'
101
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:14:in `load_files'
102
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `each'
103
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/example_group_runner.rb:13:in `load_files'
104
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/options.rb:98:in `run_examples'
105
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/lib/spec/runner/command_line.rb:10:in `run'
106
- /opt/local/lib/ruby/gems/1.8/gems/rspec-1.1.11/bin/spec:4
107
- /opt/local/bin/spec:19:in `load'
108
- /opt/local/bin/spec:19