activerecord-duplicate 0.4.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/.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: []