activerecord-duplicate 0.4.0

Sign up to get free protection for your applications and to get access to all the features.
data/.travis.yml ADDED
@@ -0,0 +1,21 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - 1.9.2
5
+ - 1.9.3
6
+ - ruby-head
7
+
8
+ gemfile:
9
+ - Gemfile
10
+ - gemfiles/Rails_3_1.gemfile
11
+ - gemfiles/Rails_3_2.gemfile
12
+ - gemfiles/Rails_master.gemfile
13
+
14
+ branches:
15
+ only:
16
+ - master
17
+
18
+ matrix:
19
+ exclude:
20
+ - rvm: 1.9.2
21
+ gemfile: gemfiles/Rails_master.gemfile
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/README.md ADDED
@@ -0,0 +1,83 @@
1
+ ## active_record-duplicate [![Build Status](https://secure.travis-ci.org/haihappen/active_record-duplicate.png)](http://travis-ci.org/haihappen/active_record-duplicate)
2
+
3
+ Duplicating ActiveRecords is easy again. All you have to do:
4
+
5
+ ```ruby
6
+ class Post < ActiveRecord::Base
7
+ attr_duplicatable :title, :content
8
+ end
9
+
10
+ post.duplicate
11
+ ```
12
+
13
+ You want more controll? Check out this example:
14
+
15
+ ```ruby
16
+ class Post < ActiveRecord::Base
17
+ # Don't duplicate if callback (on original object) returns false!
18
+ before_duplication(on: :original) { self.is_copyrighted? }
19
+ after_duplication(on: :original) { self.inform_author_about_duplicate! }
20
+
21
+ after_duplication(on: :duplicate) { self.credit_author_in_content! }
22
+
23
+ has_many :comments
24
+ has_many :tags
25
+
26
+ # These attributes will be duplicated.
27
+ attr_duplicatable :title, :content
28
+ end
29
+
30
+ class Tag < ActiveRecord::Base
31
+ attr_duplicatable :tag
32
+ end
33
+
34
+ class Comment < ActiveRecord::Base
35
+ self.duplicatable = false
36
+ end
37
+
38
+ # Duplicates non-copyrighted posts and tags as well, but ignores comments.
39
+ post.duplicate
40
+ ```
41
+
42
+ ## Installation
43
+
44
+ Tested against Ruby versions `1.9.2`, `1.9.3`, `ruby-head` and Rails versions `3.1.x`, `3.2.x`, `master` (upcoming Rails `4.0.0`).
45
+
46
+ In your `Gemfile`:
47
+
48
+ ```ruby
49
+ gem 'active_record-duplicate'
50
+ ```
51
+
52
+ ## Contributing
53
+
54
+ 1. Fork it
55
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
56
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
57
+ 4. Push to the branch (`git push origin my-new-feature`)
58
+ 5. Create new Pull Request
59
+
60
+ ## License
61
+
62
+ Copyright (c) 2012 Mario Uher
63
+
64
+ MIT License
65
+
66
+ Permission is hereby granted, free of charge, to any person obtaining
67
+ a copy of this software and associated documentation files (the
68
+ "Software"), to deal in the Software without restriction, including
69
+ without limitation the rights to use, copy, modify, merge, publish,
70
+ distribute, sublicense, and/or sell copies of the Software, and to
71
+ permit persons to whom the Software is furnished to do so, subject to
72
+ the following conditions:
73
+
74
+ The above copyright notice and this permission notice shall be
75
+ included in all copies or substantial portions of the Software.
76
+
77
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
78
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
79
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
80
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
81
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
82
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
83
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ t.test_files = Dir.glob('spec/**/*_spec.rb')
6
+ end
7
+
8
+ task(default: :test)
@@ -0,0 +1,19 @@
1
+ Gem::Specification.new do |gem|
2
+ gem.name = 'activerecord-duplicate'
3
+ gem.version = '0.4.0'
4
+ gem.authors = 'Mario Uher'
5
+ gem.email = 'uher.mario@gmail.com'
6
+ gem.description = gem.summary = 'Duplicating ActiveRecords is easy again.'
7
+ gem.homepage = 'https://github.com/haihappen/activerecord-duplicate'
8
+
9
+ gem.files = `git ls-files`.split("\n")
10
+ gem.require_path = 'lib'
11
+
12
+ gem.add_dependency 'activerecord', '>= 3.1'
13
+
14
+ gem.add_development_dependency 'minitest'
15
+ gem.add_development_dependency 'purdytest'
16
+ gem.add_development_dependency 'rails', '>= 3.1'
17
+ gem.add_development_dependency 'rake'
18
+ gem.add_development_dependency 'sqlite3'
19
+ end
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 3.1.0'
@@ -0,0 +1,5 @@
1
+ source :rubygems
2
+
3
+ gemspec path: '../'
4
+
5
+ gem 'rails', '~> 3.2.0'
@@ -0,0 +1,10 @@
1
+ source :rubygems
2
+
3
+ gem 'activerecord', git: 'git://github.com/rails/rails.git'
4
+
5
+ group :development do
6
+ gem 'minitest'
7
+ gem 'purdytest'
8
+ gem 'rails', git: 'git://github.com/rails/rails.git'
9
+ gem 'sqlite3'
10
+ end
@@ -0,0 +1,5 @@
1
+ require 'active_record-duplicate/active_record/duplicate'
2
+ require 'active_record-duplicate/railtie' if defined?(Rails)
3
+
4
+ module ActiveRecord::Duplicate
5
+ end
@@ -0,0 +1,81 @@
1
+ require 'active_record-duplicate/active_record/duplicate/callbacks'
2
+
3
+ module ActiveRecord
4
+ module Duplicate
5
+ extend ActiveSupport::Concern
6
+
7
+ included do
8
+ class_attribute :_duplicatable_attributes
9
+ class_attribute :_duplicatable
10
+
11
+ attr_accessor :duplication_parent
12
+
13
+ include ActiveRecord::Duplicate::Callbacks
14
+ end
15
+
16
+ def duplicate
17
+ return unless self.class.duplicatable
18
+
19
+ dup.tap do |duplicate|
20
+ attributes.each do |key, value|
21
+ value = case true
22
+
23
+ # Duplicate attribute if whitelisted
24
+ when self.class.attr_duplicatable.include?(key.to_sym)
25
+ value
26
+
27
+ # If not whitelisted, set to default value
28
+ when (column = self.class.columns.detect { |c| c.name == key }).present?
29
+ column.default
30
+
31
+ else
32
+ nil
33
+ end
34
+
35
+ duplicate.send(:"#{key}=", value)
36
+ end
37
+
38
+ # Duplicate all belongs_to associations.
39
+ self.class.reflect_on_all_associations(:belongs_to).each do |association|
40
+ association = self.association(association.name)
41
+
42
+ if duplication_parent.is_a?(association.klass)
43
+ duplicate.send(:"#{association.reflection.name}=", duplication_parent)
44
+ duplicate.send(:"#{association.reflection.name}_id=", nil)
45
+ else
46
+ duplicate.send(:"#{association.reflection.name}=", send(association.reflection.name))
47
+ end
48
+ end
49
+
50
+ # Duplicate all has_many associations.
51
+ self.class.reflect_on_all_associations(:has_many).each do |association|
52
+ association = self.association(association.name)
53
+
54
+ duplicate.send(:"#{association.reflection.name}=", send(association.reflection.name).map do |object|
55
+ object.duplication_parent = duplicate
56
+ object = object.duplicate
57
+ next unless object.present?
58
+
59
+ object
60
+ end.compact)
61
+ end
62
+ end
63
+ end
64
+
65
+ module ClassMethods
66
+ def attr_duplicatable(*attributes)
67
+ self._duplicatable_attributes = attributes.map(&:to_sym) if attributes.present?
68
+ self._duplicatable_attributes || []
69
+ end
70
+
71
+ def duplicatable=(duplicatable)
72
+ self._duplicatable = duplicatable unless duplicatable.nil?
73
+ self.duplicatable
74
+ end
75
+
76
+ def duplicatable
77
+ self._duplicatable.nil? ? true : !!self._duplicatable
78
+ end
79
+ end
80
+ end
81
+ end
@@ -0,0 +1,49 @@
1
+ module ActiveRecord
2
+ module Duplicate
3
+ module Callbacks
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ define_callbacks :duplication, terminator: "result == false", scope: [:kind, :name]
8
+ attr_accessor :duplication_context
9
+ end
10
+
11
+ def dup
12
+ super.tap do |duplicate|
13
+ duplicate.duplication_context = :duplicate
14
+ duplicate.run_callbacks(:duplication)
15
+ end
16
+ end
17
+
18
+ def duplicate
19
+ self.duplication_context = :original
20
+ self.run_callbacks(:duplication) { super }
21
+ end
22
+
23
+ module ClassMethods
24
+ # Duplicated from activemodel/lib/active_model/validations/callbacks.rb
25
+ def before_duplication(*args, &block)
26
+ options = args.last
27
+
28
+ if options.is_a?(Hash) && options[:on]
29
+ options[:if] = Array.wrap(options[:if])
30
+ options[:if].unshift("self.duplication_context == :#{options[:on]}")
31
+ end
32
+
33
+ set_callback(:duplication, :before, *args, &block)
34
+ end
35
+
36
+ def after_duplication(*args, &block)
37
+ options = args.extract_options!
38
+
39
+ options[:prepend] = true
40
+ options[:if] = Array.wrap(options[:if])
41
+ options[:if] << "!halted"
42
+ options[:if].unshift("self.duplication_context == :#{options[:on]}") if options[:on]
43
+
44
+ set_callback(:duplication, :after, *(args << options), &block)
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,21 @@
1
+ module ActiveRecord::Duplicate
2
+ if defined?(Rails::Railtie)
3
+ require 'rails'
4
+
5
+ class Railtie < Rails::Railtie
6
+ initializer 'active_record-duplicate.insert_into_active_record' do
7
+ ActiveSupport.on_load(:active_record) do
8
+ ActiveRecord::Duplicate::Railtie.insert
9
+ end
10
+ end
11
+ end
12
+ end
13
+
14
+ class Railtie
15
+ def self.insert
16
+ if defined?(ActiveRecord)
17
+ ActiveRecord::Base.send(:include, ActiveRecord::Duplicate)
18
+ end
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,39 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe ActiveRecord::Duplicate do
4
+ let(:klass) { Class.new(ActiveRecord::Base) { self.table_name = 'records' } }
5
+
6
+
7
+ describe :attr_duplicatable do
8
+ it 'allows you to whitelist attributes' do
9
+ klass.attr_duplicatable(:created_at, :updated_at)
10
+ end
11
+
12
+
13
+ it 'returns whitelisted attributes if called without arguments' do
14
+ klass.attr_duplicatable(:created_at, :updated_at)
15
+
16
+ klass.attr_duplicatable.must_equal([:created_at, :updated_at])
17
+ end
18
+ end
19
+
20
+
21
+ describe :duplicatable do
22
+ it 'marks associations as non-duplicatable' do
23
+ klass.duplicatable = false
24
+
25
+ klass.duplicatable.must_equal(false)
26
+ end
27
+ end
28
+
29
+
30
+ describe :duplicate do
31
+ it 'duplicates records' do
32
+ record = klass.create
33
+ duplicate = record.duplicate
34
+
35
+ duplicate.must_be_instance_of(klass)
36
+ duplicate.wont_equal(record)
37
+ end
38
+ end
39
+ end
@@ -0,0 +1,64 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe ActiveRecord::Duplicate::Callbacks do
4
+ let(:klass) { Class.new(ActiveRecord::Base) { self.table_name = 'records' } }
5
+
6
+
7
+ it 'runs callbacks' do
8
+ mock = MiniTest::Mock.new
9
+
10
+ klass.instance_eval do
11
+ before_duplication { mock.before_duplication(duplication_context) }
12
+ after_duplication { mock.after_duplication(duplication_context) }
13
+ end
14
+
15
+ mock.expect(:before_duplication, nil, [:original])
16
+ mock.expect(:after_duplication, nil, [:original])
17
+ mock.expect(:before_duplication, nil, [:duplicate])
18
+ mock.expect(:after_duplication, nil, [:duplicate])
19
+
20
+ klass.create.duplicate
21
+ mock.verify
22
+ end
23
+
24
+
25
+ it 'runs callbacks on the original object' do
26
+ mock = MiniTest::Mock.new
27
+
28
+ klass.instance_eval do
29
+ before_duplication(on: :original) { mock.before_duplication(duplication_context) }
30
+ after_duplication(on: :original) { mock.after_duplication(duplication_context) }
31
+ end
32
+
33
+ mock.expect(:before_duplication, nil, [:original])
34
+ mock.expect(:after_duplication, nil, [:original])
35
+
36
+ klass.create.duplicate
37
+ mock.verify
38
+ end
39
+
40
+
41
+ it 'runs callbacks on the duplicated object' do
42
+ mock = MiniTest::Mock.new
43
+
44
+ klass.instance_eval do
45
+ before_duplication(on: :duplicate) { mock.before_duplication(duplication_context) }
46
+ after_duplication(on: :duplicate) { mock.after_duplication(duplication_context) }
47
+ end
48
+
49
+ mock.expect(:before_duplication, nil, [:duplicate])
50
+ mock.expect(:after_duplication, nil, [:duplicate])
51
+
52
+ klass.create.duplicate
53
+ mock.verify
54
+ end
55
+
56
+
57
+ it 'wont duplicate records if callbacks return false' do
58
+ klass.instance_eval do
59
+ before_duplication(on: :original) { false }
60
+ end
61
+
62
+ klass.create.duplicate.must_equal(false)
63
+ end
64
+ end
@@ -0,0 +1,166 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe 'Integration' do
4
+ before do
5
+ ActiveRecord::Schema.define do
6
+ create_table :blogs
7
+
8
+ create_table :posts do |t|
9
+ t.belongs_to :blog
10
+ t.string :title
11
+ t.text :content
12
+ t.boolean :is_copyrighted
13
+ t.timestamp :published_at
14
+ end
15
+
16
+ create_table :comments do |t|
17
+ t.belongs_to :post
18
+ t.text :content
19
+ end
20
+
21
+ create_table :ratings do |t|
22
+ t.belongs_to :parent
23
+ t.string :parent_type
24
+ t.integer :value
25
+ end
26
+ end
27
+
28
+ class Blog < ActiveRecord::Base
29
+ has_many :posts, inverse_of: :blog
30
+ end
31
+
32
+ class Post < ActiveRecord::Base
33
+ # Don't duplicate copyrighted posts
34
+ before_duplication { !self.is_copyrighted? }
35
+ after_duplication(:increase_counter, on: :duplicate)
36
+
37
+ belongs_to :blog
38
+ has_many :comments
39
+ has_many :ratings, as: :parent
40
+
41
+ attr_duplicatable :content
42
+ class_attribute :counter
43
+
44
+ validates :title, presence: true, uniqueness: true
45
+
46
+ private
47
+ def increase_counter
48
+ self.class.counter ||= 0
49
+ self.class.counter += 1
50
+ self.title = "Lorem #{self.class.counter}"
51
+ end
52
+ end
53
+
54
+ class Comment < ActiveRecord::Base
55
+ self.duplicatable = false
56
+
57
+ belongs_to :post
58
+ has_many :ratings, as: :parent
59
+ end
60
+
61
+ class Rating < ActiveRecord::Base
62
+ belongs_to :parent, polymorphic: true
63
+ end
64
+ end
65
+
66
+
67
+ let(:blog) { Blog.create }
68
+
69
+
70
+ describe 'duplicating blog' do
71
+ subject { blog.duplicate }
72
+
73
+
74
+ it 'returns duplicate' do
75
+ subject.must_be_instance_of(Blog)
76
+ subject.new_record?.must_equal(true)
77
+ end
78
+
79
+
80
+ it 'duplicates posts too' do
81
+ 3.times do |i|
82
+ post = blog.posts.create(title: "Post #{i}")
83
+ rating = post.ratings.create(value: 5)
84
+ end
85
+
86
+ subject.posts.all?(&:new_record?).must_equal(true)
87
+ subject.posts.size.must_equal(3)
88
+
89
+ subject.save
90
+
91
+ Blog.count.must_equal(2)
92
+ Post.count.must_equal(6)
93
+ Rating.count.must_equal(6)
94
+ end
95
+
96
+
97
+ it 'sets blog association' do
98
+ 3.times do |i|
99
+ post = blog.posts.create(title: "Post #{i}")
100
+ rating = post.ratings.create(value: 5)
101
+ end
102
+
103
+ subject.posts.each do |post|
104
+ post.blog.must_equal(subject)
105
+ post.blog_id.must_be_nil
106
+ end
107
+ end
108
+
109
+
110
+ it 'ignores copyrighted posts' do
111
+ 3.times do |i|
112
+ post = blog.posts.create(title: "Post #{i}", is_copyrighted: i == 0)
113
+ rating = post.ratings.create(value: 5)
114
+ end
115
+
116
+ subject.posts.all?(&:new_record?).must_equal(true)
117
+ subject.posts.size.must_equal(2)
118
+
119
+ subject.save
120
+
121
+ Blog.count.must_equal(2)
122
+ Post.count.must_equal(5)
123
+ Rating.count.must_equal(5)
124
+ end
125
+
126
+
127
+ it 'ignores posts copyright flag' do
128
+ post = blog.posts.create(title: 'Post', content: 'Lorem', published_at: Time.now)
129
+ rating = post.ratings.create(value: 5)
130
+
131
+ post = subject.posts.first
132
+ post.wont_be_nil
133
+ post.content.must_equal('Lorem')
134
+ post.published_at.must_be_nil
135
+ end
136
+
137
+
138
+ it 'wont duplicate comments' do
139
+ post = blog.posts.create(title: 'Post')
140
+ rating = post.ratings.create(value: 5)
141
+ 3.times { post.comments.create }
142
+
143
+ post = subject.posts.first
144
+ post.wont_be_nil
145
+ post.comments.size.must_equal(0)
146
+
147
+ subject.save
148
+
149
+ Blog.count.must_equal(2)
150
+ Post.count.must_equal(2)
151
+ Rating.count.must_equal(2)
152
+ Comment.count.must_equal(3)
153
+ end
154
+ end
155
+
156
+
157
+ describe 'duplicating post' do
158
+ it 'sets blog association' do
159
+ post = blog.posts.create
160
+
161
+ post = post.duplicate
162
+
163
+ post.blog.must_equal(blog)
164
+ end
165
+ end
166
+ end
@@ -0,0 +1,8 @@
1
+ require File.expand_path('../spec_helper', __FILE__)
2
+
3
+ describe ActiveRecord::Duplicate do
4
+ it 'extends ActiveRecord::Base' do
5
+ ActiveRecord::Base.must_include(ActiveRecord::Duplicate)
6
+ ActiveRecord::Base.must_respond_to(:attr_duplicatable)
7
+ end
8
+ end
@@ -0,0 +1,28 @@
1
+ $:.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+
3
+ require 'minitest/autorun'
4
+ require 'minitest/spec'
5
+ require 'purdytest'
6
+ require 'active_record'
7
+ require 'active_record-duplicate'
8
+ require 'active_record-duplicate/railtie'
9
+
10
+ ActiveRecord::Duplicate::Railtie.insert
11
+
12
+ class MiniTest::Spec
13
+ before do
14
+ ActiveRecord::Base.establish_connection(adapter: 'sqlite3', database: ':memory:')
15
+ ActiveRecord::Schema.verbose = false
16
+
17
+ # Anonymous record class
18
+ ActiveRecord::Schema.define do
19
+ create_table :records
20
+ end
21
+ end
22
+
23
+ after do
24
+ ActiveRecord::Base.connection.tables.each do |table|
25
+ ActiveRecord::Base.connection.drop_table(table)
26
+ end
27
+ end
28
+ end
metadata ADDED
@@ -0,0 +1,127 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: activerecord-duplicate
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.4.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Mario Uher
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-18 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: activerecord
16
+ requirement: &70346238966700 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '3.1'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *70346238966700
25
+ - !ruby/object:Gem::Dependency
26
+ name: minitest
27
+ requirement: &70346238966300 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *70346238966300
36
+ - !ruby/object:Gem::Dependency
37
+ name: purdytest
38
+ requirement: &70346238965840 !ruby/object:Gem::Requirement
39
+ none: false
40
+ requirements:
41
+ - - ! '>='
42
+ - !ruby/object:Gem::Version
43
+ version: '0'
44
+ type: :development
45
+ prerelease: false
46
+ version_requirements: *70346238965840
47
+ - !ruby/object:Gem::Dependency
48
+ name: rails
49
+ requirement: &70346238965340 !ruby/object:Gem::Requirement
50
+ none: false
51
+ requirements:
52
+ - - ! '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '3.1'
55
+ type: :development
56
+ prerelease: false
57
+ version_requirements: *70346238965340
58
+ - !ruby/object:Gem::Dependency
59
+ name: rake
60
+ requirement: &70346238964920 !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ type: :development
67
+ prerelease: false
68
+ version_requirements: *70346238964920
69
+ - !ruby/object:Gem::Dependency
70
+ name: sqlite3
71
+ requirement: &70346238964460 !ruby/object:Gem::Requirement
72
+ none: false
73
+ requirements:
74
+ - - ! '>='
75
+ - !ruby/object:Gem::Version
76
+ version: '0'
77
+ type: :development
78
+ prerelease: false
79
+ version_requirements: *70346238964460
80
+ description: Duplicating ActiveRecords is easy again.
81
+ email: uher.mario@gmail.com
82
+ executables: []
83
+ extensions: []
84
+ extra_rdoc_files: []
85
+ files:
86
+ - .travis.yml
87
+ - Gemfile
88
+ - README.md
89
+ - Rakefile
90
+ - activerecord-duplicate.gemspec
91
+ - gemfiles/Rails_3_1.gemfile
92
+ - gemfiles/Rails_3_2.gemfile
93
+ - gemfiles/Rails_master.gemfile
94
+ - lib/active_record-duplicate.rb
95
+ - lib/active_record-duplicate/active_record/duplicate.rb
96
+ - lib/active_record-duplicate/active_record/duplicate/callbacks.rb
97
+ - lib/active_record-duplicate/railtie.rb
98
+ - spec/acts_as_duplicator_spec.rb
99
+ - spec/callbacks_spec.rb
100
+ - spec/integration_spec.rb
101
+ - spec/railtie_spec.rb
102
+ - spec/spec_helper.rb
103
+ homepage: https://github.com/haihappen/activerecord-duplicate
104
+ licenses: []
105
+ post_install_message:
106
+ rdoc_options: []
107
+ require_paths:
108
+ - lib
109
+ required_ruby_version: !ruby/object:Gem::Requirement
110
+ none: false
111
+ requirements:
112
+ - - ! '>='
113
+ - !ruby/object:Gem::Version
114
+ version: '0'
115
+ required_rubygems_version: !ruby/object:Gem::Requirement
116
+ none: false
117
+ requirements:
118
+ - - ! '>='
119
+ - !ruby/object:Gem::Version
120
+ version: '0'
121
+ requirements: []
122
+ rubyforge_project:
123
+ rubygems_version: 1.8.11
124
+ signing_key:
125
+ specification_version: 3
126
+ summary: Duplicating ActiveRecords is easy again.
127
+ test_files: []