genki-dm-has-versions 0.1.1 → 0.2.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.
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