vestal_versions 0.4.4

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ test/*.db
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Steve Richert
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.rdoc ADDED
@@ -0,0 +1,77 @@
1
+ = vestal_versions
2
+
3
+ Finally, DRY ActiveRecord versioning!
4
+
5
+ <tt>acts_as_versioned</tt>[http://github.com/technoweenie/acts_as_versioned] by technoweenie[http://github.com/technoweenie] was a great start, but it failed to keep up with ActiveRecord's introduction of dirty objects in version 2.1. Additionally, each versioned model needs its own versions table that duplicates most of the original table's columns. The versions table is then populated with records that often duplicate most of the original record's attributes. All in all, not very DRY.
6
+
7
+ <tt>simply_versioned</tt>[http://github.com/mmower/simply_versioned] by mmower[http://github.com/mmower] started to move in the right direction by removing a great deal of the duplication of acts_as_versioned. It requires only one versions table and no changes whatsoever to existing models. Its versions table stores all of the model attributes as a YAML hash in a single text column. But we could be DRYer!
8
+
9
+ <tt>vestal_versions</tt> keeps in the spirit of consolidating to one versions table, polymorphically associated with its parent models. But it goes one step further by storing a serialized hash of only the models' changes. Think modern version control systems. By traversing the record of changes, the models can be reverted to any point in time.
10
+
11
+ And that's just what <tt>vestal_versions</tt> does. Not only can a model be reverted to a previous version number but also to a date or time!
12
+
13
+ == Installation
14
+
15
+ In <tt>environment.rb</tt>:
16
+
17
+ Rails::Initializer.run do |config|
18
+ config.gem 'laserlemon-vestal_versions', :lib => 'vestal_versions', :source => 'http://gems.github.com'
19
+ end
20
+
21
+ At your application root, run:
22
+
23
+ $ sudo rake gems:install
24
+
25
+ Next, generate and run the first and last versioning migration you'll ever need:
26
+
27
+ $ script/generate vestal_versions_migration
28
+ $ rake db:migrate
29
+
30
+ == Example
31
+
32
+ To version an ActiveRecord model, simply add <tt>versioned</tt> to your class like so:
33
+
34
+ class User < ActiveRecord::Base
35
+ versioned
36
+
37
+ validates_presence_of :first_name, :last_name
38
+
39
+ def name
40
+ "#{first_name} #{last_name}"
41
+ end
42
+ end
43
+
44
+ It's that easy! Now watch it in action...
45
+
46
+ >> u = User.create(:first_name => 'Steve', :last_name => 'Richert')
47
+ => #<User first_name: "Steve", last_name: "Richert">
48
+ >> u.version
49
+ => 1
50
+ >> u.update_attribute(:first_name, 'Stephen')
51
+ => true
52
+ >> u.name
53
+ => "Stephen Richert"
54
+ >> u.version
55
+ => 2
56
+ >> u.revert_to(:first)
57
+ => 1
58
+ >> u.name
59
+ => "Steve Richert"
60
+ >> u.version
61
+ => 1
62
+ >> u.save
63
+ => true
64
+ >> u.version
65
+ => 3
66
+ >> u.update_attribute(:last_name, 'Jobs')
67
+ => true
68
+ >> u.name
69
+ => "Steve Jobs"
70
+ >> u.version
71
+ => 4
72
+ >> u.revert_to!(2)
73
+ => true
74
+ >> u.name
75
+ => "Stephen Richert"
76
+ >> u.version
77
+ => 5
data/Rakefile ADDED
@@ -0,0 +1,38 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/testtask'
4
+ require 'rake/rdoctask'
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |g|
9
+ g.name = 'vestal_versions'
10
+ g.summary = %(Keep a DRY history of your ActiveRecord models' changes)
11
+ g.description = %(Keep a DRY history of your ActiveRecord models' changes)
12
+ g.email = 'steve@laserlemon.com'
13
+ g.homepage = 'http://github.com/laserlemon/vestal_versions'
14
+ g.authors = %w(laserlemon)
15
+ g.add_development_dependency 'thoughtbot-shoulda'
16
+ g.rubyforge_project = 'laser-lemon'
17
+ end
18
+ Jeweler::RubyforgeTasks.new do |r|
19
+ r.doc_task = 'rdoc'
20
+ end
21
+ rescue LoadError
22
+ puts 'Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com'
23
+ end
24
+
25
+ Rake::TestTask.new do |t|
26
+ t.libs = %w(test)
27
+ t.pattern = 'test/**/*_test.rb'
28
+ end
29
+
30
+ task :default => :test
31
+
32
+ Rake::RDocTask.new do |r|
33
+ version = File.exist?('VERSION') ? File.read('VERSION') : nil
34
+ r.rdoc_dir = 'rdoc'
35
+ r.title = ['vestal_versions', version].compact.join(' ')
36
+ r.rdoc_files.include('README*')
37
+ r.rdoc_files.include('lib/**/*.rb')
38
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.4.4
@@ -0,0 +1,20 @@
1
+ class CreateVestalVersions < ActiveRecord::Migration
2
+ def self.up
3
+ create_table :versions do |t|
4
+ t.belongs_to :versioned, :polymorphic => true
5
+ t.text :changes
6
+ t.integer :number
7
+ t.datetime :created_at
8
+ end
9
+
10
+ change_table :versions do |t|
11
+ t.index [:versioned_type, :versioned_id]
12
+ t.index :number
13
+ t.index :created_at
14
+ end
15
+ end
16
+
17
+ def self.down
18
+ drop_table :versions
19
+ end
20
+ end
@@ -0,0 +1,11 @@
1
+ class VestalVersionsMigrationGenerator < Rails::Generator::Base
2
+ def manifest
3
+ record do |m|
4
+ m.migration_template 'migration.rb', 'db/migrate'
5
+ end
6
+ end
7
+
8
+ def file_name
9
+ 'create_vestal_versions'
10
+ end
11
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ require 'vestal_versions'
data/lib/version.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Version < ActiveRecord::Base
2
+ include Comparable
3
+
4
+ belongs_to :versioned, :polymorphic => true
5
+
6
+ serialize :changes, Hash
7
+
8
+ alias_attribute :version, :number
9
+
10
+ def <=>(other)
11
+ number <=> other.number
12
+ end
13
+ end
@@ -0,0 +1,127 @@
1
+ require 'version'
2
+
3
+ module LaserLemon
4
+ module VestalVersions
5
+ def self.included(base)
6
+ base.extend ClassMethods
7
+ end
8
+
9
+ module ClassMethods
10
+ def versioned
11
+ has_many :versions, :as => :versioned, :order => 'versions.number ASC', :dependent => :destroy do
12
+ def between(from_value, to_value)
13
+ from, to = number_at(from_value), number_at(to_value)
14
+ return [] if from.nil? || to.nil?
15
+ condition = (from == to) ? to : Range.new(*[from, to].sort)
16
+ all(
17
+ :conditions => {:number => condition},
18
+ :order => "versions.number #{(from > to) ? 'DESC' : 'ASC'}"
19
+ )
20
+ end
21
+
22
+ def at(value)
23
+ case value
24
+ when Version then value
25
+ when Numeric then find_by_number(value.floor)
26
+ when Symbol then respond_to?(value) ? send(value) : nil
27
+ when Date, Time then last(:conditions => ['versions.created_at <= ?', value.to_time])
28
+ end
29
+ end
30
+
31
+ def number_at(value)
32
+ case value
33
+ when Version then value.number
34
+ when Numeric then value.floor
35
+ when Symbol, Date, Time then at(value).try(:number)
36
+ end
37
+ end
38
+ end
39
+
40
+ after_save :create_version, :if => :needs_version?
41
+
42
+ include InstanceMethods
43
+ alias_method_chain :reload, :versions
44
+ end
45
+ end
46
+
47
+ module InstanceMethods
48
+ private
49
+ def needs_version?
50
+ !changed.empty?
51
+ end
52
+
53
+ def reset_version(new_version = nil)
54
+ @last_version = nil if new_version.nil?
55
+ @version = new_version
56
+ end
57
+
58
+ def create_version
59
+ if versions.empty?
60
+ versions.create(:changes => attributes, :number => 1)
61
+ else
62
+ reset_version
63
+ versions.create(:changes => changes, :number => (version.to_i + 1))
64
+ end
65
+
66
+ reset_version
67
+ end
68
+
69
+ public
70
+ def version
71
+ @version ||= last_version
72
+ end
73
+
74
+ def last_version
75
+ @last_version ||= versions.maximum(:number)
76
+ end
77
+
78
+ def reverted?
79
+ version != last_version
80
+ end
81
+
82
+ def reload_with_versions(*args)
83
+ reset_version
84
+ reload_without_versions(*args)
85
+ end
86
+
87
+ def revert_to(value)
88
+ to_value = versions.number_at(value)
89
+ return version if to_value == version
90
+ chain = versions.between(version, to_value)
91
+ return version if chain.empty?
92
+
93
+ new_version = chain.last.number
94
+ backward = chain.first > chain.last
95
+ backward ? chain.pop : chain.shift
96
+
97
+ timestamps = %w(created_at created_on updated_at updated_on)
98
+
99
+ chain.each do |version|
100
+ version.changes.except(*timestamps).each do |attribute, change|
101
+ new_value = backward ? change.first : change.last
102
+ write_attribute(attribute, new_value)
103
+ end
104
+ end
105
+
106
+ reset_version(new_version)
107
+ end
108
+
109
+ def revert_to!(value)
110
+ revert_to(value)
111
+ reset_version if saved = save
112
+ saved
113
+ end
114
+
115
+ def last_changes
116
+ return {} if version.nil? || version == 1
117
+ versions.at(version).changes
118
+ end
119
+
120
+ def last_changed
121
+ last_changes.keys
122
+ end
123
+ end
124
+ end
125
+ end
126
+
127
+ ActiveRecord::Base.send(:include, LaserLemon::VestalVersions)
@@ -0,0 +1,58 @@
1
+ require 'test_helper'
2
+
3
+ class BetweenTest < Test::Unit::TestCase
4
+ context 'The number of versions between' do
5
+ setup do
6
+ @user = User.create(:name => 'Steve Richert')
7
+ @version = @user.version
8
+ @valid = [@version, 0, 1_000_000, :first, :last, 1.day.since(@user.created_at), @user.versions.first]
9
+ @invalid = [nil, :bogus, 'bogus', Date.parse('0001-12-25')]
10
+ end
11
+
12
+ context 'the current version and the current version' do
13
+ should 'equal one' do
14
+ assert_equal 1, @user.versions.between(@version, @version).size
15
+ end
16
+ end
17
+
18
+ context 'the current version and a valid value' do
19
+ should 'not equal zero' do
20
+ @valid.each do |valid|
21
+ assert_not_equal 0, @user.versions.between(@version, valid).size
22
+ assert_not_equal 0, @user.versions.between(valid, @version).size
23
+ end
24
+ end
25
+ end
26
+
27
+ context 'the current version and an invalid value' do
28
+ should 'equal zero' do
29
+ @invalid.each do |invalid|
30
+ assert_equal 0, @user.versions.between(@version, invalid).size
31
+ assert_equal 0, @user.versions.between(invalid, @version).size
32
+ end
33
+ end
34
+ end
35
+
36
+ context 'two invalid values' do
37
+ should 'equal zero' do
38
+ @invalid.each do |first|
39
+ @invalid.each do |second|
40
+ assert_equal 0, @user.versions.between(first, second).size
41
+ assert_equal 0, @user.versions.between(second, first).size
42
+ end
43
+ end
44
+ end
45
+ end
46
+
47
+ context 'a valid value and an invalid value' do
48
+ should 'equal zero' do
49
+ @valid.each do |valid|
50
+ @invalid.each do |invalid|
51
+ assert_equal 0, @user.versions.between(valid, invalid).size
52
+ assert_equal 0, @user.versions.between(invalid, valid).size
53
+ end
54
+ end
55
+ end
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class ChangesTest < Test::Unit::TestCase
4
+ context "A version's changes" do
5
+ setup do
6
+ @user = User.create(:name => 'Steve Richert')
7
+ end
8
+
9
+ should "initially equal its parent's attributes" do
10
+ assert_equal @user.attributes, @user.versions.first.changes
11
+ end
12
+
13
+ should 'contain all changed attributes' do
14
+ @user.name = 'Steve Jobs'
15
+ changes = @user.changes
16
+ @user.save
17
+ assert_equal changes, @user.versions.last.changes.slice(*changes.keys)
18
+ end
19
+
20
+ should 'contain timestamp changes when applicable' do
21
+ timestamp = 'updated_at'
22
+ @user.update_attribute(:name, 'Steve Jobs')
23
+ assert @user.class.content_columns.map(&:name).include?(timestamp)
24
+ assert_contains @user.versions.last.changes.keys, timestamp
25
+ end
26
+
27
+ should 'contain no more than the changed attributes and timestamps' do
28
+ timestamps = %w(created_at created_on updated_at updated_on)
29
+ @user.name = 'Steve Jobs'
30
+ changes = @user.changes
31
+ @user.save
32
+ assert_equal changes, @user.versions.last.changes.except(*timestamps)
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ require 'test_helper'
2
+
3
+ class ComparableTest < Test::Unit::TestCase
4
+ context 'A comparable version' do
5
+ setup do
6
+ @version_1 = Version.new(:number => 1)
7
+ @version_2 = Version.new(:number => 2)
8
+ end
9
+
10
+ should 'equal itself' do
11
+ assert @version_1 == @version_1
12
+ assert @version_2 == @version_2
13
+ end
14
+
15
+ context 'with version number 1' do
16
+ should 'not equal a version with version number 2' do
17
+ assert @version_1 != @version_2
18
+ end
19
+
20
+ should 'be less than a version with version number 2' do
21
+ assert @version_1 < @version_2
22
+ end
23
+ end
24
+
25
+ context 'with version number 2' do
26
+ should 'not equal a version with version number 1' do
27
+ assert @version_2 != @version_1
28
+ end
29
+
30
+ should 'be greater than a version with version number 1' do
31
+ assert @version_2 > @version_1
32
+ end
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,70 @@
1
+ require 'test_helper'
2
+
3
+ class CreationTest < Test::Unit::TestCase
4
+ context 'The number of versions' do
5
+ setup do
6
+ @name = 'Steve Richert'
7
+ @user = User.create(:name => @name)
8
+ @count = @user.versions.count
9
+ end
10
+
11
+ should 'initially equal one' do
12
+ assert_equal 1, @count
13
+ end
14
+
15
+ should 'not increase when no changes are made in an update' do
16
+ @user.update_attribute(:name, @name)
17
+ assert_equal @count, @user.versions.count
18
+ end
19
+
20
+ should 'not increase when no changes are made before a save' do
21
+ @user.save
22
+ assert_equal @count, @user.versions.count
23
+ end
24
+
25
+ should 'not increase when reverting to the current version' do
26
+ @user.revert_to!(@user.version)
27
+ assert_equal @count, @user.versions.count
28
+ end
29
+
30
+ context 'after an update' do
31
+ setup do
32
+ @initial_count = @count
33
+ @name = 'Steve Jobs'
34
+ @user.update_attribute(:name, @name)
35
+ @count = @user.versions.count
36
+ end
37
+
38
+ should 'increase by one' do
39
+ assert_equal @initial_count + 1, @count
40
+ end
41
+
42
+ should 'increase by one when reverted' do
43
+ @user.revert_to!(:first)
44
+ assert_equal @count + 1, @user.versions.count
45
+ end
46
+
47
+ should 'not increase until a revert is saved' do
48
+ @user.revert_to(:first)
49
+ assert_equal @count, @user.versions.count
50
+ @user.save
51
+ assert_not_equal @count, @user.versions.count
52
+ end
53
+ end
54
+
55
+ context 'after multiple updates' do
56
+ setup do
57
+ @initial_count = @count
58
+ @new_name = 'Steve Jobs'
59
+ @user.update_attribute(:name, @new_name)
60
+ @user.update_attribute(:name, @name)
61
+ @count = @user.versions.count
62
+ end
63
+
64
+ should 'not increase when reverting to an identical version' do
65
+ @user.revert_to!(:first)
66
+ assert_equal @count, @user.versions.count
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,47 @@
1
+ require 'test_helper'
2
+
3
+ class LastChangesTest < Test::Unit::TestCase
4
+ context "A created model's last changes" do
5
+ setup do
6
+ @user = User.create(:name => 'Steve Richert')
7
+ end
8
+
9
+ should 'be blank' do
10
+ assert @user.last_changes.blank?
11
+ assert @user.last_changed.blank?
12
+ end
13
+ end
14
+
15
+ context "An updated model's last changes" do
16
+ setup do
17
+ @user = User.create(:name => 'Steve Richert')
18
+ @previous_attributes = @user.attributes
19
+ @user.update_attribute(:name, 'Steve Jobs')
20
+ @current_attributes = @user.attributes
21
+ end
22
+
23
+ should 'have keys matching its last changed attributes' do
24
+ assert_equal @user.last_changes.keys, @user.last_changed
25
+ end
26
+
27
+ should 'values of two-element arrays with unique values' do
28
+ @user.last_changes.values.each do |value|
29
+ assert_kind_of Array, value
30
+ assert_equal 2, value.size
31
+ assert_equal value, value.uniq
32
+ end
33
+ end
34
+
35
+ should 'begin with the previous attribute values' do
36
+ changes = @user.last_changes.inject({}){|h,(k,v)| h.update(k => v.first) }
37
+ previous = @previous_attributes.slice(*@user.last_changed)
38
+ assert_equal previous, changes
39
+ end
40
+
41
+ should 'end with the current attribute values' do
42
+ changes = @user.last_changes.inject({}){|h,(k,v)| h.update(k => v.last) }
43
+ current = @current_attributes.slice(*@user.last_changed)
44
+ assert_equal current, changes
45
+ end
46
+ end
47
+ end
@@ -0,0 +1,80 @@
1
+ require 'test_helper'
2
+
3
+ class RevertTest < Test::Unit::TestCase
4
+ context 'A model reversion' do
5
+ setup do
6
+ @user, @attributes, @times = User.new, {}, {}
7
+ names = ['Steve Richert', 'Stephen Richert', 'Stephen Jobs', 'Steve Jobs']
8
+ time = names.size.hours.ago
9
+ names.each do |name|
10
+ @user.update_attribute(:name, name)
11
+ @attributes[@user.version] = @user.attributes
12
+ time += 1.hour
13
+ @user.versions.last.update_attribute(:created_at, time)
14
+ @times[@user.version] = time
15
+ end
16
+ @user.reload.versions.reload
17
+ @first_version, @last_version = @attributes.keys.min, @attributes.keys.max
18
+ end
19
+
20
+ should 'do nothing for a non-existent version' do
21
+ attributes = @user.attributes
22
+ @user.revert_to!(nil)
23
+ assert_equal attributes, @user.attributes
24
+ end
25
+
26
+ should 'return the new version number' do
27
+ new_version = @user.revert_to(@first_version)
28
+ assert_equal @first_version, new_version
29
+ end
30
+
31
+ should 'change the version number when saved' do
32
+ current_version = @user.version
33
+ @user.revert_to!(@first_version)
34
+ assert_not_equal current_version, @user.version
35
+ end
36
+
37
+ should 'be able to target the first version' do
38
+ @user.revert_to(:first)
39
+ assert_equal @first_version, @user.version
40
+ end
41
+
42
+ should 'be able to target the last version' do
43
+ @user.revert_to(:last)
44
+ assert_equal @last_version, @user.version
45
+ end
46
+
47
+ should 'do nothing for a non-existent method name' do
48
+ current_version = @user.version
49
+ @user.revert_to(:bogus)
50
+ assert_equal current_version, @user.version
51
+ end
52
+
53
+ should 'be able to target a version number' do
54
+ @user.revert_to(1)
55
+ assert 1, @user.version
56
+ end
57
+
58
+ should 'be able to target a date and time' do
59
+ @times.each do |version, time|
60
+ @user.revert_to(time + 1.second)
61
+ assert_equal version, @user.version
62
+ end
63
+ end
64
+
65
+ should 'be able to target a version object' do
66
+ @user.versions.each do |version|
67
+ @user.revert_to(version)
68
+ assert_equal version.number, @user.version
69
+ end
70
+ end
71
+
72
+ should "correctly roll back the model's attributes" do
73
+ timestamps = %w(created_at created_on updated_at updated_on)
74
+ @attributes.each do |version, attributes|
75
+ @user.revert_to!(version)
76
+ assert_equal attributes.except(*timestamps), @user.attributes.except(*timestamps)
77
+ end
78
+ end
79
+ end
80
+ end
data/test/schema.rb ADDED
@@ -0,0 +1,37 @@
1
+ ActiveRecord::Base.establish_connection(
2
+ :adapter => defined?(RUBY_ENGINE) && RUBY_ENGINE == 'jruby' ? 'jdbcsqlite3' : 'sqlite3',
3
+ :database => File.join(File.dirname(__FILE__), 'test.db')
4
+ )
5
+
6
+ class CreateSchema < ActiveRecord::Migration
7
+ def self.up
8
+ create_table :users, :force => true do |t|
9
+ t.string :first_name
10
+ t.string :last_name
11
+ t.timestamps
12
+ end
13
+
14
+ create_table :versions, :force => true do |t|
15
+ t.belongs_to :versioned, :polymorphic => true
16
+ t.text :changes
17
+ t.integer :number
18
+ t.datetime :created_at
19
+ end
20
+ end
21
+ end
22
+
23
+ CreateSchema.suppress_messages do
24
+ CreateSchema.migrate(:up)
25
+ end
26
+
27
+ class User < ActiveRecord::Base
28
+ versioned
29
+
30
+ def name
31
+ [first_name, last_name].compact.join(' ')
32
+ end
33
+
34
+ def name=(names)
35
+ self[:first_name], self[:last_name] = names.split(' ', 2)
36
+ end
37
+ end
@@ -0,0 +1,10 @@
1
+ $: << File.join(File.dirname(__FILE__), '..', 'lib')
2
+ $: << File.dirname(__FILE__)
3
+
4
+ require 'rubygems'
5
+ require 'test/unit'
6
+ require 'activerecord'
7
+ require 'shoulda'
8
+ require 'vestal_versions'
9
+ require 'schema'
10
+ begin; require 'redgreen'; rescue LoadError; end
@@ -0,0 +1,69 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{vestal_versions}
8
+ s.version = "0.4.4"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["laserlemon"]
12
+ s.date = %q{2009-09-03}
13
+ s.description = %q{Keep a DRY history of your ActiveRecord models' changes}
14
+ s.email = %q{steve@laserlemon.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.rdoc"
18
+ ]
19
+ s.files = [
20
+ ".gitignore",
21
+ "LICENSE",
22
+ "README.rdoc",
23
+ "Rakefile",
24
+ "VERSION",
25
+ "generators/vestal_versions_migration/templates/migration.rb",
26
+ "generators/vestal_versions_migration/vestal_versions_migration_generator.rb",
27
+ "init.rb",
28
+ "lib/version.rb",
29
+ "lib/vestal_versions.rb",
30
+ "test/between_test.rb",
31
+ "test/changes_test.rb",
32
+ "test/comparable_test.rb",
33
+ "test/creation_test.rb",
34
+ "test/last_changes_test.rb",
35
+ "test/revert_test.rb",
36
+ "test/schema.rb",
37
+ "test/test_helper.rb",
38
+ "vestal_versions.gemspec"
39
+ ]
40
+ s.homepage = %q{http://github.com/laserlemon/vestal_versions}
41
+ s.rdoc_options = ["--charset=UTF-8"]
42
+ s.require_paths = ["lib"]
43
+ s.rubyforge_project = %q{laser-lemon}
44
+ s.rubygems_version = %q{1.3.5}
45
+ s.summary = %q{Keep a DRY history of your ActiveRecord models' changes}
46
+ s.test_files = [
47
+ "test/between_test.rb",
48
+ "test/changes_test.rb",
49
+ "test/comparable_test.rb",
50
+ "test/creation_test.rb",
51
+ "test/last_changes_test.rb",
52
+ "test/revert_test.rb",
53
+ "test/schema.rb",
54
+ "test/test_helper.rb"
55
+ ]
56
+
57
+ if s.respond_to? :specification_version then
58
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
59
+ s.specification_version = 3
60
+
61
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
62
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
63
+ else
64
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ end
66
+ else
67
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
68
+ end
69
+ end
metadata ADDED
@@ -0,0 +1,90 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: vestal_versions
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.4
5
+ platform: ruby
6
+ authors:
7
+ - laserlemon
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-03 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ description: Keep a DRY history of your ActiveRecord models' changes
26
+ email: steve@laserlemon.com
27
+ executables: []
28
+
29
+ extensions: []
30
+
31
+ extra_rdoc_files:
32
+ - LICENSE
33
+ - README.rdoc
34
+ files:
35
+ - .gitignore
36
+ - LICENSE
37
+ - README.rdoc
38
+ - Rakefile
39
+ - VERSION
40
+ - generators/vestal_versions_migration/templates/migration.rb
41
+ - generators/vestal_versions_migration/vestal_versions_migration_generator.rb
42
+ - init.rb
43
+ - lib/version.rb
44
+ - lib/vestal_versions.rb
45
+ - test/between_test.rb
46
+ - test/changes_test.rb
47
+ - test/comparable_test.rb
48
+ - test/creation_test.rb
49
+ - test/last_changes_test.rb
50
+ - test/revert_test.rb
51
+ - test/schema.rb
52
+ - test/test_helper.rb
53
+ - vestal_versions.gemspec
54
+ has_rdoc: true
55
+ homepage: http://github.com/laserlemon/vestal_versions
56
+ licenses: []
57
+
58
+ post_install_message:
59
+ rdoc_options:
60
+ - --charset=UTF-8
61
+ require_paths:
62
+ - lib
63
+ required_ruby_version: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: "0"
68
+ version:
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ requirements: []
76
+
77
+ rubyforge_project: laser-lemon
78
+ rubygems_version: 1.3.5
79
+ signing_key:
80
+ specification_version: 3
81
+ summary: Keep a DRY history of your ActiveRecord models' changes
82
+ test_files:
83
+ - test/between_test.rb
84
+ - test/changes_test.rb
85
+ - test/comparable_test.rb
86
+ - test/creation_test.rb
87
+ - test/last_changes_test.rb
88
+ - test/revert_test.rb
89
+ - test/schema.rb
90
+ - test/test_helper.rb