versioned_record 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 949068fec057f339188cdb54a297c3237d806a3c
4
+ data.tar.gz: 4408334975f62ef080055cc2f1351a4ef7730595
5
+ SHA512:
6
+ metadata.gz: d8b8c37d7f54b9a978b8166a66908426ea6060f8ce5f799dd1948f318226cc78c349cb4aadce06c7708341a41acc08532eba13114405ebff36b85fe9ff7f060f
7
+ data.tar.gz: ce25740a5627cffd3dcdec8cad7c76518819eaf7b279ba2b6009e1258a8227a5aa1fdf06ec7a6ce58ae4b5dec4e5609680d46f14bec23449f2be2dc02838bb2b
data/.coveralls.yml ADDED
@@ -0,0 +1,2 @@
1
+ service_name: travis-ci
2
+ repo_token: HuSTbhH4GYJ4rGmPkf2Cxbx1vtrYA3INI
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --color
2
+ --format progress
data/.travis.yml ADDED
@@ -0,0 +1,13 @@
1
+ language: ruby
2
+ rvm:
3
+ - "2.1.1"
4
+ script: bundle exec rspec spec
5
+ addons:
6
+ postgresql: "9.3"
7
+ before_script:
8
+ - export VERSIONED_RECORD_ENV=travis
9
+ - psql -c 'create database versioned_record_test;' -U postgres
10
+ notifications:
11
+ hipchat: 83906daf46b0ce558ce21f13353861@246078
12
+ on_success: always
13
+ on_failure: always
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in versioned_record.gemspec
4
+ gemspec
5
+
6
+ gem 'byebug'
data/History.rdoc ADDED
@@ -0,0 +1,4 @@
1
+ == 0.2.0 (2014-04-28)
2
+
3
+ * First stable release (Dan Draper)
4
+ * Uses Rails 4 compatible version of CPK
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Dan Draper
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,94 @@
1
+ # VersionedRecord
2
+
3
+ [![Code Climate](https://codeclimate.com/github/jobready/versioned_record.png)](https://codeclimate.com/github/jobready/versioned_record)
4
+ [![Build Status](https://travis-ci.org/jobready/versioned_record.png?branch=master)](https://travis-ci.org/jobready/versioned_record)
5
+ [![Coverage Status](https://coveralls.io/repos/jobready/versioned_record/badge.png)](https://coveralls.io/r/jobready/versioned_record)
6
+
7
+ [RDocs](http://rdoc.info/github/jobready/versioned_record/master/frames)
8
+
9
+ Versioned Record allows the creation of multiple versions of an active record that share an ID.
10
+ The version and ID columns of a record form a composite primary key and as such this gem relies on the
11
+ composite_primary_keys gem.
12
+
13
+ Why another versioning tool for ActiveRecord? Mainly because this gem does not rely on serializing data or storing of
14
+ multiple attributes in a single column. It uses databases as they were intended which means it is fast, reliable and flexible.
15
+
16
+ ## Installation
17
+
18
+ Add this line to your application's Gemfile:
19
+
20
+ gem 'versioned_record'
21
+
22
+ And then execute:
23
+
24
+ $ bundle
25
+
26
+ Or install it yourself as:
27
+
28
+ $ gem install versioned_record
29
+
30
+ ## Usage
31
+
32
+ ### Setting up your table
33
+
34
+ To create a versioned record, start by adding the `versioned: true` option to your migration and then (re)running.
35
+
36
+ create_table :products, versioned: true do |t|
37
+ t.string :name
38
+ t.decimal :price
39
+ end
40
+
41
+ The versioned option will create the `id`, `version` and `is_current_version` columns and create a composite primary key on the id and version columns.
42
+
43
+ Next, include the VersionedRecord module in your ActiveRecord model
44
+
45
+ class Product < ActiveRecord::Base
46
+ include VersionedRecord
47
+ end
48
+
49
+ ### Creating records and versions
50
+
51
+ Creating a record happens as normal.
52
+
53
+ product = Product.create(name: 'Coffee Cup', price: 4.99)
54
+
55
+ The product will have `version` set to 0 and `is_current_version` set to true
56
+
57
+ product.version => 0
58
+ product.is_current_version? => true
59
+
60
+ To create a version simply call `create_version!` on the record.
61
+
62
+ product_v2 = product.create_version!(price: 5.99)
63
+
64
+ Note that any attributes not specified in the `create_version!` call will be copied from the previous version.
65
+
66
+ product_v2.name => 'Coffee Cup'
67
+
68
+ Also, the `is_current_version` flag is unset for the old version and set for the new one
69
+
70
+ product.is_current_version? => false
71
+ product_v2.is_current_version? => true
72
+
73
+ ## TODO: Associations
74
+
75
+
76
+ ## Database Support
77
+
78
+ Right now, only PostgreSQL has been tested. MySQL may or may not work but if you'd like to test/add support please fork and contribute!
79
+
80
+ ## Limitations
81
+
82
+ Does not currently work with ActiveRecord 4.1+
83
+
84
+ ## Author
85
+
86
+ Dan Draper, dan at codehire dot com, [Codehire](http://www.codehire.com/), [@danieldraper](http://www.twitter.com/danieldraper)
87
+
88
+ ## Contributing
89
+
90
+ 1. Fork it
91
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
92
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
93
+ 4. Push to the branch (`git push origin my-new-feature`)
94
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1 @@
1
+ require "bundler/gem_tasks"
@@ -0,0 +1,25 @@
1
+ module VersionedRecord
2
+ # Builds a set of attributes for a new version of a record
3
+ class AttributeBuilder
4
+
5
+ # New Builder
6
+ # @param [ActiveRecord::Base] record the record we are versioning
7
+ def initialize(record)
8
+ @record = record
9
+ end
10
+
11
+ # Get new attributes hash for the new version
12
+ # Attributes missing in new_attrs will be filled in from
13
+ # the previous version (specified in the constructor)
14
+ #
15
+ # @param [Hash] new_attrs are the attributes we are changing in this version
16
+ def attributes(new_attrs)
17
+ @new_attrs = new_attrs.stringify_keys
18
+ @record.attributes.merge(@new_attrs.merge({
19
+ is_current_version: true,
20
+ id: @record.id,
21
+ version: @record.version + 1
22
+ }))
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,58 @@
1
+ module VersionedRecord
2
+ module ClassMethods
3
+ # Scope to limit records to only the current versions
4
+ def current_versions
5
+ where(is_current_version: true)
6
+ end
7
+
8
+ # Scope to exclude current version from a query
9
+ def exclude_current
10
+ where(is_current_version: false)
11
+ end
12
+
13
+ # Finds a record as per ActiveRecord::Base
14
+ # If only an ID is provided then it returns the current version for that ID
15
+ # Otherwise, both an ID and a version can be provided
16
+ #
17
+ # @see ActiveRecord::Base#find
18
+ # @see #find_current
19
+ #
20
+ # @example Single Argument
21
+ #
22
+ # Model.find(1) => # The latest record
23
+ #
24
+ # @example An ID and a version
25
+ #
26
+ # Model.find(1, 0) => # The first version
27
+ #
28
+ def find(*args)
29
+ if args.length == 1 && !args.first.kind_of?(Array)
30
+ find_current(args.first)
31
+ else
32
+ super
33
+ end
34
+ end
35
+
36
+ # Find the current version of the record with the given ID
37
+ # @param [Integer] id the record's ID
38
+ # @raise [ActiveRecord::RecordNotFound] if no record with the given ID is found
39
+ def find_current(id)
40
+ current_versions.where(id: id).first.tap do |record|
41
+ raise ActiveRecord::RecordNotFound unless record.present?
42
+ end
43
+ end
44
+
45
+ # Scope to exclude the given record from results.
46
+ # This is handy when retrieving all versions of a record except for one
47
+ # Say when we are viewing all other versions to a given record
48
+ #
49
+ # @example
50
+ #
51
+ # person = Person.find(1, 3)
52
+ # other_versions = person.versions.exclude(person)
53
+ #
54
+ def exclude(record)
55
+ where(id: record.id).where('version != ?', record.version)
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class PostgreSQLAdapter
4
+
5
+ # Provide versioned: true to create a versioned table
6
+ # Note that schema.rb cannot be used with versioned tables
7
+ def create_table(table_name, options = {})
8
+ if options[:versioned]
9
+ super(table_name, options.merge(id: false)) do |table|
10
+ table.column :id, :serial
11
+ table.integer :version, default: 0
12
+ table.boolean :is_current_version, default: true
13
+ yield(table)
14
+ end
15
+ add_index(table_name, [:id, :version], unique: true, name: "#{table_name}_versioned_pkey")
16
+ execute("ALTER TABLE #{table_name} ADD PRIMARY KEY USING INDEX #{table_name}_versioned_pkey")
17
+ else
18
+ super
19
+ end
20
+ end
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,3 @@
1
+ module VersionedRecord
2
+ VERSION = "0.2.0"
3
+ end
@@ -0,0 +1,108 @@
1
+
2
+ require 'active_record'
3
+ require 'active_record/connection_adapters/postgresql_adapter'
4
+
5
+ require 'composite_primary_keys'
6
+ require 'versioned_record/attribute_builder'
7
+ require 'versioned_record/class_methods'
8
+ require 'versioned_record/connection_adapters/postgresql'
9
+ require 'versioned_record/version'
10
+
11
+ module VersionedRecord
12
+ def self.included(model_class)
13
+ model_class.extend ClassMethods
14
+ model_class.primary_keys = :id, :version
15
+ model_class.after_save :ensure_version_deprecation!, on: :create
16
+ end
17
+
18
+ # Create a new version of the existing record
19
+ # A new version can only be created once for a given record and subsequent
20
+ # versions must be created by calling create_version! on the latest version
21
+ #
22
+ # Attributes that are not specified here will be copied to the new version from
23
+ # the previous version
24
+ #
25
+ # This method will still fire ActiveRecord callbacks for save/create etc as per
26
+ # normal record creation
27
+ #
28
+ # @example
29
+ #
30
+ # person_v1 = Person.create(name: 'Dan')
31
+ # person_v2 = person_v1.create_version!(name: 'Daniel')
32
+ #
33
+ def create_version!(new_attrs = {})
34
+ create_operation do
35
+ self.class.create!(new_version_attrs(new_attrs))
36
+ end
37
+ end
38
+
39
+ # Same as #create_version! but will not raise if the record is invalid
40
+ # @see VersionedRecord#create_version!
41
+ #
42
+ def create_version(new_attrs = {})
43
+ create_operation do
44
+ self.class.create(new_version_attrs(new_attrs))
45
+ end
46
+ end
47
+
48
+ # Build (but do not save) a new version of the record
49
+ # This allows you to use the object in forms etc
50
+ # After the record is saved, all previous versions will be deprecated
51
+ # and this record will be marked as current
52
+ #
53
+ # @example
54
+ #
55
+ # new_version = first_version.build_version
56
+ # new_version.save
57
+ #
58
+ def build_version(new_attrs = {})
59
+ new_version = self.class.new(new_version_attrs(new_attrs)).tap do |built|
60
+ built.deprecate_old_versions_after_create!
61
+ end
62
+ end
63
+
64
+ # Retrieve all versions of this record
65
+ # Can be chained with other scopes
66
+ #
67
+ # @example Versions ordered by version number
68
+ #
69
+ # person.versions.order(:version)
70
+ #
71
+ def versions
72
+ self.class.where(id: self.id)
73
+ end
74
+
75
+ # Ensure that old versions are deprecated when we save
76
+ # (only applies on create)
77
+ def deprecate_old_versions_after_create!
78
+ @deprecate_old_versions_after_create = true
79
+ end
80
+
81
+ private
82
+ def new_version_attrs(new_attrs)
83
+ attr_builder = AttributeBuilder.new(self)
84
+ attr_builder.attributes(new_attrs)
85
+ end
86
+
87
+ def deprecate_old_versions(current_version)
88
+ versions.exclude(current_version).update_all(is_current_version: false)
89
+ end
90
+
91
+ def create_operation
92
+ self.class.transaction do
93
+ yield.tap do |created|
94
+ deprecate_old_versions(created) if created.persisted?
95
+ end
96
+ end
97
+ end
98
+
99
+ def deprecate_old_versions_after_create?
100
+ @deprecate_old_versions_after_create
101
+ end
102
+
103
+ def ensure_version_deprecation!
104
+ if deprecate_old_versions_after_create?
105
+ deprecate_old_versions(self)
106
+ end
107
+ end
108
+ end
@@ -0,0 +1,23 @@
1
+ require 'coveralls'
2
+ Coveralls.wear!
3
+
4
+ #require 'active_record'
5
+ require 'versioned_record'
6
+ require 'database_cleaner'
7
+
8
+ Dir[("./spec/support/**/*.rb")].each {|f| require f}
9
+
10
+ # See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
11
+ RSpec.configure do |config|
12
+ config.treat_symbols_as_metadata_keys_with_true_values = true
13
+ config.run_all_when_everything_filtered = true
14
+ config.mock_with :rspec
15
+ config.filter_run :focus
16
+ config.order = 'random'
17
+ config.before :each do
18
+ DatabaseCleaner.start
19
+ end
20
+ config.after :each do
21
+ DatabaseCleaner.clean
22
+ end
23
+ end
@@ -0,0 +1,11 @@
1
+ env = ENV['VERSIONED_RECORD_ENV'] || 'development'
2
+ dbconfig = YAML::load_file(File.join(__dir__, 'database.yml'))
3
+ ActiveRecord::Base.establish_connection(dbconfig[env]['postgresql'])
4
+
5
+ ActiveRecord::Schema.define :version => 0 do
6
+
7
+ create_table :versioned_products, versioned: true, force: true do |t|
8
+ t.string :name
9
+ t.decimal :price
10
+ end
11
+ end
@@ -0,0 +1,15 @@
1
+ development:
2
+ postgresql:
3
+ adapter: postgresql
4
+ host: localhost
5
+ username: daniel
6
+ password:
7
+ database: versioned_record_test
8
+ travis:
9
+ postgresql:
10
+ adapter: postgresql
11
+ host: localhost
12
+ username: postgres
13
+ password:
14
+ database: versioned_record_test
15
+
@@ -0,0 +1,5 @@
1
+ class VersionedProduct < ActiveRecord::Base
2
+ include VersionedRecord
3
+ validates :name, presence: true
4
+ validates :name, length: { minimum: 2 }
5
+ end
@@ -0,0 +1,70 @@
1
+ require 'spec_helper'
2
+
3
+ describe VersionedProduct do
4
+ describe '::create' do
5
+ let(:record) { VersionedProduct.create(name: 'Macbook Pro') }
6
+
7
+ specify do
8
+ expect(record).to be_is_current_version
9
+ expect(record.version).to eq(0)
10
+ end
11
+ end
12
+
13
+ describe '::find' do
14
+ context 'a single non-array argument' do
15
+ it 'retrieves the latest version with the given ID' do
16
+ expect(VersionedProduct).to receive(:find_current).with(1)
17
+ VersionedProduct.find(1)
18
+ end
19
+ end
20
+
21
+ context 'a single array argument' do
22
+ it 'retrieves the latest version with the given ID' do
23
+ expect(ActiveRecord::Base).to receive(:find).with([1, 0])
24
+ VersionedProduct.find([1, 0])
25
+ end
26
+ end
27
+
28
+ context 'multiple arguments' do
29
+ it 'retrieves the latest version with the given ID' do
30
+ expect(ActiveRecord::Base).to receive(:find).with(1, 0)
31
+ VersionedProduct.find(1, 0)
32
+ end
33
+ end
34
+ end
35
+
36
+ describe 'scopes' do
37
+ let!(:first_version) { VersionedProduct.create(name: 'Macbook Pro') }
38
+ let!(:second_version) { first_version.create_version!(name: 'Macbook Retina') }
39
+
40
+ describe '::find_current' do
41
+ it 'finds the latest version' do
42
+ expect(VersionedProduct.find_current(first_version.id)).to eq(second_version)
43
+ end
44
+
45
+ context 'where no matching record exists' do
46
+ it 'finds the latest version' do
47
+ expect { VersionedProduct.find_current(0) }.to raise_error(ActiveRecord::RecordNotFound)
48
+ end
49
+ end
50
+ end
51
+
52
+ describe '::current_versions' do
53
+ it 'returns only the current version' do
54
+ expect(VersionedProduct.current_versions).to eq([second_version])
55
+ end
56
+ end
57
+
58
+ describe '::exclude_current' do
59
+ it 'returns only the current version' do
60
+ expect(VersionedProduct.exclude_current).to eq([first_version])
61
+ end
62
+ end
63
+
64
+ describe '::exclude' do
65
+ it 'returns everything but the excluded record' do
66
+ expect(VersionedProduct.exclude(first_version)).to eq([second_version])
67
+ end
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,144 @@
1
+ require 'spec_helper'
2
+
3
+ describe VersionedProduct do
4
+ let!(:first_version) { VersionedProduct.create(name: 'iPad', price: 100) }
5
+
6
+ shared_examples 'successful version creation' do
7
+ it 'creates a new version' do
8
+ expect { perform }.to change { VersionedProduct.count }.by(1)
9
+ end
10
+
11
+ it 'unsets current version on first version' do
12
+ perform
13
+ expect(first_version.reload).to_not be_is_current_version
14
+ end
15
+
16
+ describe 'the new version' do
17
+ subject { perform.reload }
18
+ specify { expect(subject).to be_is_current_version }
19
+ specify { expect(subject.version).to eq(1) }
20
+ specify { expect(subject.name).to eq('iPad 2') }
21
+ specify { expect(subject.price).to eq(100) }
22
+ specify { expect(subject).to be_valid }
23
+ specify { expect(subject).to be_persisted }
24
+ end
25
+ end
26
+
27
+ describe '#create_version!' do
28
+ def perform
29
+ first_version.create_version!(name: 'iPad 2')
30
+ end
31
+
32
+ include_examples 'successful version creation'
33
+
34
+ context 'when created record is invalid' do
35
+ it 'raises an error' do
36
+ expect { first_version.create_version!(name: nil) }.to raise_error(ActiveRecord::RecordInvalid)
37
+ end
38
+
39
+ it 'does not change the current version flag on first version' do
40
+ begin
41
+ first_version.create_version!(name: nil)
42
+ rescue
43
+ expect(first_version.reload).to be_is_current_version
44
+ end
45
+ end
46
+ end
47
+ end
48
+
49
+ describe '#create_version' do
50
+ def perform
51
+ first_version.create_version(name: 'iPad 2')
52
+ end
53
+
54
+ include_examples 'successful version creation'
55
+
56
+ context 'when created record is invalid' do
57
+ it 'does not create a new version' do
58
+ expect { first_version.create_version(name: 'f') }.to_not change { VersionedProduct.count }
59
+ end
60
+
61
+ describe 'create result' do
62
+ subject { first_version.create_version(name: 'f') }
63
+
64
+ specify { expect(subject).to_not be_valid }
65
+ specify { expect(subject).to_not be_persisted }
66
+ end
67
+ end
68
+ end
69
+
70
+ describe '#build_version' do
71
+ context 'with attributes provided directly' do
72
+ def perform
73
+ first_version.build_version(name: 'iPad 2').tap do |new_version|
74
+ new_version.save!
75
+ end
76
+ end
77
+
78
+ include_examples 'successful version creation'
79
+
80
+ context 'when created record is invalid' do
81
+ it 'does not create a new version' do
82
+ expect {
83
+ new_version = first_version.build_version(name: 'f')
84
+ new_version.save
85
+ }.to_not change { VersionedProduct.count }
86
+ end
87
+
88
+ describe 'create result' do
89
+ subject do
90
+ first_version.build_version(name: 'f').tap do |new_version|
91
+ new_version.save
92
+ end
93
+ end
94
+
95
+ specify { expect(subject).to_not be_valid }
96
+ specify { expect(subject).to_not be_persisted }
97
+ end
98
+ end
99
+ end
100
+
101
+ context 'with attributes provided after initialization' do
102
+ def perform
103
+ first_version.build_version.tap do |new_version|
104
+ new_version.name = 'iPad 2'
105
+ new_version.save!
106
+ end
107
+ end
108
+
109
+ include_examples 'successful version creation'
110
+
111
+ context 'when created record is invalid' do
112
+ it 'does not create a new version' do
113
+ expect {
114
+ new_version = first_version.build_version
115
+ new_version.name = 'f'
116
+ new_version.save
117
+ }.to_not change { VersionedProduct.count }
118
+ end
119
+
120
+ describe 'create result' do
121
+ subject do
122
+ first_version.build_version.tap do |new_version|
123
+ new_version.name = 'f'
124
+ new_version.save
125
+ end
126
+ end
127
+
128
+ specify { expect(subject).to_not be_valid }
129
+ specify { expect(subject).to_not be_persisted }
130
+ end
131
+ end
132
+ end
133
+ end
134
+
135
+ describe '#versions' do
136
+ subject(:first_version) { VersionedProduct.create(name: 'iPad') }
137
+ specify { expect(subject).to have(1).versions }
138
+
139
+ context 'after creating a version' do
140
+ before { first_version.create_version!(name: 'iPad 2') }
141
+ specify { expect(subject).to have(2).versions }
142
+ end
143
+ end
144
+ end
@@ -0,0 +1,33 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'versioned_record/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "versioned_record"
8
+ spec.version = VersionedRecord::VERSION
9
+ spec.authors = ["Dan Draper"]
10
+ spec.email = ["daniel@codehire.com"]
11
+ spec.description = %q{Version ActiveRecord models using composite primary keys}
12
+ spec.summary = %q{Version ActiveRecord models using composite primary keys}
13
+ spec.homepage = ""
14
+ spec.license = "MIT"
15
+
16
+ spec.files = `git ls-files`.split($/)
17
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
18
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
+ spec.require_paths = ["lib"]
20
+
21
+ spec.required_ruby_version = '>= 2.0.0'
22
+
23
+ spec.add_runtime_dependency "activerecord", "~> 4.0.0"
24
+ spec.add_runtime_dependency 'composite_primary_keys', '>= 6.0.3'
25
+
26
+ spec.add_development_dependency "bundler", "~> 1.3"
27
+ spec.add_development_dependency "rake"
28
+ spec.add_development_dependency "rspec", "~> 2.14"
29
+ spec.add_development_dependency "pg"
30
+ spec.add_development_dependency "database_cleaner"
31
+ spec.add_development_dependency "yard"
32
+ spec.add_development_dependency "coveralls"
33
+ end
metadata ADDED
@@ -0,0 +1,198 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: versioned_record
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - Dan Draper
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-04-28 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: 4.0.0
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: 4.0.0
27
+ - !ruby/object:Gem::Dependency
28
+ name: composite_primary_keys
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 6.0.3
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: 6.0.3
41
+ - !ruby/object:Gem::Dependency
42
+ name: bundler
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '1.3'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '1.3'
55
+ - !ruby/object:Gem::Dependency
56
+ name: rake
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - ">="
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: rspec
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '2.14'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '2.14'
83
+ - !ruby/object:Gem::Dependency
84
+ name: pg
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - ">="
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ - !ruby/object:Gem::Dependency
98
+ name: database_cleaner
99
+ requirement: !ruby/object:Gem::Requirement
100
+ requirements:
101
+ - - ">="
102
+ - !ruby/object:Gem::Version
103
+ version: '0'
104
+ type: :development
105
+ prerelease: false
106
+ version_requirements: !ruby/object:Gem::Requirement
107
+ requirements:
108
+ - - ">="
109
+ - !ruby/object:Gem::Version
110
+ version: '0'
111
+ - !ruby/object:Gem::Dependency
112
+ name: yard
113
+ requirement: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ requirements:
122
+ - - ">="
123
+ - !ruby/object:Gem::Version
124
+ version: '0'
125
+ - !ruby/object:Gem::Dependency
126
+ name: coveralls
127
+ requirement: !ruby/object:Gem::Requirement
128
+ requirements:
129
+ - - ">="
130
+ - !ruby/object:Gem::Version
131
+ version: '0'
132
+ type: :development
133
+ prerelease: false
134
+ version_requirements: !ruby/object:Gem::Requirement
135
+ requirements:
136
+ - - ">="
137
+ - !ruby/object:Gem::Version
138
+ version: '0'
139
+ description: Version ActiveRecord models using composite primary keys
140
+ email:
141
+ - daniel@codehire.com
142
+ executables: []
143
+ extensions: []
144
+ extra_rdoc_files: []
145
+ files:
146
+ - ".coveralls.yml"
147
+ - ".gitignore"
148
+ - ".rspec"
149
+ - ".travis.yml"
150
+ - Gemfile
151
+ - History.rdoc
152
+ - LICENSE.txt
153
+ - README.md
154
+ - Rakefile
155
+ - lib/versioned_record.rb
156
+ - lib/versioned_record/attribute_builder.rb
157
+ - lib/versioned_record/class_methods.rb
158
+ - lib/versioned_record/connection_adapters/postgresql.rb
159
+ - lib/versioned_record/version.rb
160
+ - spec/spec_helper.rb
161
+ - spec/support/database.rb
162
+ - spec/support/database.yml
163
+ - spec/support/versioned_product.rb
164
+ - spec/version_class_methods_spec.rb
165
+ - spec/versions_spec.rb
166
+ - versioned_record.gemspec
167
+ homepage: ''
168
+ licenses:
169
+ - MIT
170
+ metadata: {}
171
+ post_install_message:
172
+ rdoc_options: []
173
+ require_paths:
174
+ - lib
175
+ required_ruby_version: !ruby/object:Gem::Requirement
176
+ requirements:
177
+ - - ">="
178
+ - !ruby/object:Gem::Version
179
+ version: 2.0.0
180
+ required_rubygems_version: !ruby/object:Gem::Requirement
181
+ requirements:
182
+ - - ">="
183
+ - !ruby/object:Gem::Version
184
+ version: '0'
185
+ requirements: []
186
+ rubyforge_project:
187
+ rubygems_version: 2.2.2
188
+ signing_key:
189
+ specification_version: 4
190
+ summary: Version ActiveRecord models using composite primary keys
191
+ test_files:
192
+ - spec/spec_helper.rb
193
+ - spec/support/database.rb
194
+ - spec/support/database.yml
195
+ - spec/support/versioned_product.rb
196
+ - spec/version_class_methods_spec.rb
197
+ - spec/versions_spec.rb
198
+ has_rdoc: