copyable 0.1.1 → 0.3.1

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 4e51f2b73f6b3f642d8b9174567c245c2f875b6a
4
- data.tar.gz: c56647390d32496da7fbe0f971d9e86d2299b070
2
+ SHA256:
3
+ metadata.gz: 2a08309e56270ce4847101314203835381cb28e1ece99a477391cc23461e3d78
4
+ data.tar.gz: 440110e69f8828d034ba8b01dcbae7bc56e011aea751a69f202423ffa66859f0
5
5
  SHA512:
6
- metadata.gz: 236d9f5a60f236f49d99b2a8f47586ea2678bbd1c2a97c86d2e0dd7eaabf4dafe90065f8e09b9fd32b6f8c9c75188e4ee27c4977c9e3ffd198a85124ed1c13c5
7
- data.tar.gz: b59f9f190720c3dbc37646795017d52953078f7bf8d7a2726fef9aa891e29c67579e911d021029b9b2def2f9898f4a5f05b163644bbba2e7fcdea506b50bcb6d
6
+ metadata.gz: 65fd03e6dce5bfd47f6aa2f784f4a8cab6d061ad6d3c693609239a848af4867bae34cded904a9c540041631cc456b636c44e70e0b6c6a8ab94fe0e07f2e197a9
7
+ data.tar.gz: '0585f34ccded08588ad09aa76a13834846c17c082a783da6f4f4f96f80d3d96156f54437022edf62c521eda8202e06fa02d5b8f24ddc921b401cf4251d591891'
data/README.md CHANGED
@@ -121,16 +121,9 @@ The advice must be one of the following:
121
121
 
122
122
  ## Callbacks
123
123
 
124
- It depends on the situation as to whether you would want a particular callback to be fired when a model is copied. Since the logic of callbacks is situational, Copyable makes the decision to completely disable all callbacks and observers for the duration of the `create_copy!` method. The only exception are callbacks and observers related to validation.
125
-
126
- To make it easier to reason about the code, and for the sake of being obvious, every copyable declaration *must* include a declaration called `disable_all_callbacks_and_observers_except_validate`. This declaration itself does not do anything; it exists as documentation.
127
-
128
- copyable do
129
- disable_all_callbacks_and_observers_except_validate
130
- ...
131
- end
132
-
133
-
124
+ It depends on the situation as to whether you would want a particular callback to be fired when a model is copied. Since the logic of callbacks is situational, Copyable makes the decision to bypass callbacks
125
+ when saving the copied models by using raw SQL insert statements during the copy. It will check
126
+ validations unless `skip_validations` is passed to `create_copy`.
134
127
 
135
128
  ## The After Copy Declaration
136
129
 
@@ -267,4 +260,4 @@ So the recommended approach is to use `after_copy` to tweak the columns of the c
267
260
 
268
261
  ## About
269
262
 
270
- Copyable was developed at [District Management Group](https://dmgroupK12.com).
263
+ Copyable was developed at [District Management Group](https://dmgroupK12.com).
data/copyable.gemspec CHANGED
@@ -6,8 +6,8 @@ require 'copyable/version'
6
6
  Gem::Specification.new do |spec|
7
7
  spec.name = "copyable"
8
8
  spec.version = Copyable::VERSION
9
- spec.authors = ["Wyatt Greene", "Dennis Chan"]
10
- spec.email = ["dchan@dmcouncil.org"]
9
+ spec.authors = ["Wyatt Greene", "Dennis Chan", "Anne Geiersbach", "Parker Morse"]
10
+ spec.email = ["dchan@dmgroupK12.com", "ageiersbach@dmgroupK12.com", "pmorse@dmgroupK12.com"]
11
11
  spec.summary = %q{ActiveRecord copier}
12
12
  spec.description = %q{Copyable makes it easy to copy ActiveRecord models.}
13
13
  spec.homepage = "https://github.com/dmcouncil/copyable"
@@ -18,11 +18,11 @@ Gem::Specification.new do |spec|
18
18
  spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
19
19
  spec.require_paths = ["lib"]
20
20
 
21
- spec.add_dependency "activerecord", "~>4.1.0"
21
+ spec.add_dependency "activerecord", "5.2.6"
22
22
 
23
- spec.add_development_dependency "database_cleaner", "~> 1.4.0"
24
- spec.add_development_dependency "bundler", "~> 1.6"
23
+ spec.add_development_dependency "database_cleaner", "~> 2"
24
+ spec.add_development_dependency "bundler"
25
25
  spec.add_development_dependency "rake"
26
26
  spec.add_development_dependency "rspec"
27
- spec.add_development_dependency "sqlite3"
27
+ spec.add_development_dependency "sqlite3", "~> 1.3.6"
28
28
  end
@@ -49,6 +49,8 @@ module Copyable
49
49
  # fill in each column of this brand new model according to the
50
50
  # instructions given in the copyable declaration
51
51
  column_overrides = options[:override] || {}
52
+ # merge with global override hash if exists
53
+ column_overrides = column_overrides.merge(options[:global_override]) if options[:global_override]
52
54
  Declarations::Columns.execute(main.column_list, original_model, new_model, column_overrides)
53
55
  # save that sucker!
54
56
  Copyable::Saver.save!(new_model, options[:skip_validations])
@@ -61,7 +63,7 @@ module Copyable
61
63
  # declaration
62
64
 
63
65
  skip_associations = options[:skip_associations] || []
64
- Declarations::Associations.execute(main.association_list, original_model, new_model, options[:skip_validations], skip_associations)
66
+ Declarations::Associations.execute(main.association_list, original_model, new_model, options[:global_override], options[:skip_validations], skip_associations)
65
67
  # run the after_copy block if it exists
66
68
  Declarations::AfterCopy.execute(main.after_copy_block, original_model, new_model)
67
69
  ensure
@@ -6,10 +6,12 @@ module Copyable
6
6
 
7
7
  # this is the algorithm for copying associated records according to the
8
8
  # instructions given in the copyable declaration
9
- def execute(association_list, original_model, new_model, skip_validations, skip_associations)
9
+ def execute(association_list, original_model, new_model, global_override = {}, skip_validations, skip_associations)
10
10
  @skip_validations = skip_validations
11
+ @skip_associations = skip_associations
12
+ @global_override = global_override
11
13
  association_list.each do |assoc_name, advice|
12
- association = original_model.class.reflections[assoc_name.to_sym]
14
+ association = original_model.class.reflections[assoc_name.to_s]
13
15
  check_advice(association, advice, original_model)
14
16
  unless advice == :do_not_copy || skip_associations.include?(assoc_name.to_sym)
15
17
  copy_association(association, original_model, new_model)
@@ -26,14 +28,14 @@ module Copyable
26
28
  message << "has unrecognized advice '#{advice}'."
27
29
  raise AssociationError.new(message)
28
30
  end
29
- if association.macro == :has_and_belongs_to_many && advice == :copy
31
+ if association.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection) && advice == :copy
30
32
  message = "Error in copyable:associations of "
31
33
  message << "#{original_model.class.name}: the association '#{association.name}' "
32
34
  message << "only supports the :copy_only_habtm_join_records advice, not the :copy advice, "
33
35
  message << "because it is a has_and_belongs_to_many association."
34
36
  raise AssociationError.new(message)
35
37
  end
36
- if association.macro != :has_and_belongs_to_many && advice == :copy_only_habtm_join_records
38
+ if !association.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection) && advice == :copy_only_habtm_join_records
37
39
  message = "Error in copyable:associations of "
38
40
  message << "#{original_model.class.name}: the association '#{association.name}' "
39
41
  message << "only supports the :copy advice, not the :copy_only_habtm_join_records advice, "
@@ -43,15 +45,14 @@ module Copyable
43
45
  end
44
46
 
45
47
  def copy_association(association, original_model, new_model)
46
- case association.macro
47
- when :has_many
48
+ if association.is_a?(ActiveRecord::Reflection::HasManyReflection)
48
49
  copy_has_many(association, original_model, new_model)
49
- when :has_one
50
+ elsif association.is_a?(ActiveRecord::Reflection::HasOneReflection)
50
51
  copy_has_one(association, original_model, new_model)
51
- when :has_and_belongs_to_many
52
+ elsif association.is_a?(ActiveRecord::Reflection::HasAndBelongsToManyReflection)
52
53
  copy_habtm(association, original_model, new_model)
53
54
  else
54
- raise "Unsupported association #{association.macro}" # should never happen, since we filter out belongs_to
55
+ raise "Unsupported association #{association.class}" # should never happen, since we filter out belongs_to
55
56
  end
56
57
  end
57
58
 
@@ -78,7 +79,9 @@ module Copyable
78
79
  copied_record = original_record.create_copy!(
79
80
  override: { association.foreign_key => parent_model.id },
80
81
  __called_recursively: true,
81
- skip_validations: @skip_validations)
82
+ global_override: @global_override,
83
+ skip_validations: @skip_validations,
84
+ skip_associations: @skip_associations)
82
85
  else
83
86
  message = "Could not copy #{parent_model.class.name}#id:#{parent_model.id} "
84
87
  message << "because #{original_record.class.name} does not have a copyable declaration."
@@ -16,30 +16,33 @@ module Copyable
16
16
 
17
17
  def self.disable_all_callbacks(klass)
18
18
  klass.class_eval do
19
- # Don't do it if it was already done
20
- return if self.method_defined? :__disabled__run_callbacks
21
-
22
- alias_method :__disabled__run_callbacks, :run_callbacks
23
- # We are violently duck-punching ActiveRecord because ActiveRecord
24
- # gives us no way to turn off callbacks. My apologies to the
25
- # squeamish.
26
- def run_callbacks(kind, *args, &block)
27
- if block_given?
28
- yield
29
- else
30
- true
31
- end
19
+ return if self.method_defined? :old_save! # Don't do this more than once
20
+
21
+ @all_callbacks_disabled = true
22
+ class << self
23
+ attr_reader :all_callbacks_disabled
24
+ end
25
+
26
+ alias_method :old_save!, :save!
27
+
28
+ # Hold my beer while we bypass all the Rails callbacks
29
+ # in favor of some raw SQL
30
+ def save!
31
+ Copyable::Saver.save!(self)
32
32
  end
33
33
  end
34
34
  end
35
35
 
36
36
  def self.reenable_all_callbacks(klass)
37
37
  klass.class_eval do
38
- # Only do it if the disabled callbacks are defined
39
- return unless self.method_defined? :__disabled__run_callbacks
38
+ return unless self.method_defined? :old_save! # Don't do this more than once
39
+ @all_callbacks_disabled = false
40
+ class << self
41
+ attr_reader :all_callbacks_disabled
42
+ end
40
43
 
41
- alias_method :run_callbacks, :__disabled__run_callbacks
42
- remove_method :__disabled__run_callbacks
44
+ alias_method :save!, :old_save!
45
+ remove_method :old_save!
43
46
  end
44
47
  end
45
48
 
@@ -1,7 +1,7 @@
1
1
  module Copyable
2
2
  class OptionChecker
3
3
 
4
- VALID_OPTIONS = [:override, :skip_validations, :skip_associations]
4
+ VALID_OPTIONS = [:override, :global_override, :skip_validations, :skip_associations]
5
5
  VALID_PRIVATE_OPTIONS = [:__called_recursively] # for copyable's internal use only
6
6
 
7
7
  def self.check!(options)
@@ -1,19 +1,27 @@
1
1
  module Copyable
2
2
  class Saver
3
3
 
4
+ def self.direct_sql_insert!(new_model)
5
+ new_model.send(:_create_record) # bypass all callbacks and validations
6
+ end
7
+
8
+ def self.direct_sql_update!(new_model)
9
+ new_model.send(:_update_record) # bypass all callbacks and validations
10
+ end
11
+
4
12
  # this is the algorithm for saving the new record
5
- def self.save!(new_model, skip_validations)
6
- unless skip_validations
7
- ModelHooks.reenable!(new_model.class) # we must re-enable or validation does not work
8
- if !new_model.valid?(:create)
9
- ModelHooks.disable!(new_model.class)
10
- raise(ActiveRecord::RecordInvalid.new(new_model))
11
- else
12
- ModelHooks.disable!(new_model.class)
13
- end
13
+ def self.save!(new_model, skip_validations=false)
14
+ unless skip_validations || new_model.valid?(:create)
15
+ raise(ActiveRecord::RecordInvalid.new(new_model))
14
16
  end
15
- new_model.save!
16
- end
17
17
 
18
+ if new_model.class.all_callbacks_disabled && new_model.id.nil?
19
+ self.direct_sql_insert!(new_model)
20
+ elsif new_model.class.all_callbacks_disabled
21
+ self.direct_sql_update!(new_model)
22
+ else
23
+ new_model.save!
24
+ end
25
+ end
18
26
  end
19
27
  end
@@ -10,7 +10,8 @@ module Copyable
10
10
  def expected_entries
11
11
  all_associations = model_class.reflect_on_all_associations
12
12
  required_associations = all_associations.select do |ass|
13
- (ass.macro != :belongs_to) && ass.options[:through].blank?
13
+ !ass.is_a?(ActiveRecord::Reflection::BelongsToReflection) &&
14
+ !ass.is_a?(ActiveRecord::Reflection::ThroughReflection)
14
15
  end
15
16
  required_associations.map(&:name).map(&:to_s)
16
17
  end
@@ -1,3 +1,3 @@
1
1
  module Copyable
2
- VERSION = "0.1.1"
2
+ VERSION = "0.3.1"
3
3
  end
@@ -39,7 +39,8 @@ task :copyable => :environment do
39
39
 
40
40
  all_associations = model_class.reflect_on_all_associations
41
41
  required_associations = all_associations.select do |ass|
42
- (ass.macro != :belongs_to) && ass.options[:through].blank?
42
+ !ass.is_a?(ActiveRecord::Reflection::BelongsToReflection) &&
43
+ !ass.is_a?(ActiveRecord::Reflection::ThroughReflection)
43
44
  end
44
45
  associations = required_associations.map(&:name).map(&:to_s)
45
46
  max_length = associations.map(&:length).max
@@ -89,6 +89,13 @@ describe 'complex model hierarchies:' do
89
89
  expect(CopyableWarranty.count).to eq(3) # Because the amenities weren't copied either
90
90
  end
91
91
 
92
+ it 'should skip nested branches of the tree when directed' do
93
+ @vehicle2 = @vehicle1.create_copy!(skip_associations: [:copyable_warranty])
94
+ expect(CopyableVehicle.count).to eq(2)
95
+ expect(CopyableAmenity.count).to eq(6)
96
+ expect(CopyableWarranty.count).to eq(3) # No new ones created
97
+ end
98
+
92
99
  it 'should create the expected records if copied multiple times' do
93
100
  # this test makes sure the SingleCopyEnforcer isn't too eager
94
101
  @vehicle1.create_copy!
@@ -122,6 +129,20 @@ describe 'complex model hierarchies:' do
122
129
  expect(CopyableVehicle.count).to eq(2)
123
130
  expect(CopyableAmenity.count).to eq(2)
124
131
  end
132
+
133
+ context 'with a global override, can copy vehicle with new owner' do
134
+ before(:each) do
135
+ @jane = CopyableOwner.create!(name: 'Jane')
136
+ end
137
+
138
+ it 'should copy the records correctly' do
139
+ @copy_of_joes_car = @porsche.create_copy!(global_override: { copyable_owner_id: @jane.id })
140
+ expect(CopyableVehicle.count).to eq(2)
141
+ expect(CopyableAmenity.count).to eq(2)
142
+ expect(@copy_of_joes_car.copyable_owner_id).to eq(@jane.id)
143
+ expect(@copy_of_joes_car.copyable_amenities.map(&:copyable_owner_id).uniq).to eq([@jane.id])
144
+ end
145
+ end
125
146
  end
126
147
 
127
148
  context 'with many models, some having redundant associations' do
@@ -11,14 +11,14 @@ module Copyable
11
11
 
12
12
  create_table :copyable_albums, force: true do |t|
13
13
  t.string :name, null: false
14
- t.timestamps
14
+ t.timestamps null: false
15
15
  end
16
16
 
17
17
  create_table :copyable_amenities, force: true do |t|
18
18
  t.string :name
19
19
  t.integer :copyable_vehicle_id
20
20
  t.integer :copyable_owner_id
21
- t.timestamps
21
+ t.timestamps null: false
22
22
  end
23
23
 
24
24
  create_table :copyable_addresses, force: true do |t|
@@ -27,30 +27,30 @@ module Copyable
27
27
  t.string :city, null: false
28
28
  t.string :state, null: false
29
29
  t.integer :copyable_pet_profile_id, null: false
30
- t.timestamps
30
+ t.timestamps null: false
31
31
  end
32
32
 
33
33
  create_table :copyable_cars, force: true do |t|
34
34
  t.string :make, null: false
35
35
  t.string :model, null: false
36
36
  t.integer :year, null: false
37
- t.timestamps
37
+ t.timestamps null: false
38
38
  end
39
39
 
40
40
  create_table :copyable_coins, force: true do |t|
41
41
  t.string :kind
42
42
  t.integer :year
43
- t.timestamps
43
+ t.timestamps null: false
44
44
  end
45
45
 
46
46
  create_table :copyable_owners, force: true do |t|
47
47
  t.string :name, null: false
48
- t.timestamps
48
+ t.timestamps null: false
49
49
  end
50
50
 
51
51
  create_table :copyable_pet_foods, force: true do |t|
52
52
  t.string :name, null: false
53
- t.timestamps
53
+ t.timestamps null: false
54
54
  end
55
55
 
56
56
  create_table :copyable_pet_foods_pets, force: true, id: false do |t|
@@ -62,31 +62,31 @@ module Copyable
62
62
  t.string :description, null: false
63
63
  t.string :nickname
64
64
  t.integer :copyable_pet_id, null: false
65
- t.timestamps
65
+ t.timestamps null: false
66
66
  end
67
67
 
68
68
  create_table :copyable_pet_sitters, force: true do |t|
69
69
  t.string :name, null: false
70
- t.timestamps
70
+ t.timestamps null: false
71
71
  end
72
72
 
73
73
  create_table :copyable_pet_sitting_patronages, force: true do |t|
74
74
  t.integer :copyable_pet_id, null: false
75
75
  t.integer :copyable_pet_sitter_id, null: false
76
- t.timestamps
76
+ t.timestamps null: false
77
77
  end
78
78
 
79
79
  create_table :copyable_pet_tags, force: true do |t|
80
80
  t.string :registered_name, null: false
81
81
  t.integer :copyable_pet_id, null: false
82
- t.timestamps
82
+ t.timestamps null: false
83
83
  end
84
84
 
85
85
  create_table :copyable_pets, force: true do |t|
86
86
  t.string :name, null: false
87
87
  t.string :kind, null: false
88
88
  t.integer :birth_year
89
- t.timestamps
89
+ t.timestamps null: false
90
90
  end
91
91
 
92
92
  create_table :copyable_pictures, force: true do |t|
@@ -94,36 +94,36 @@ module Copyable
94
94
  t.integer :imageable_id
95
95
  t.string :imageable_type
96
96
  t.integer :picture_album_id
97
- t.timestamps
97
+ t.timestamps null: false
98
98
  end
99
99
 
100
100
  create_table :copyable_products, force: true do |t|
101
101
  t.string :name
102
- t.timestamps
102
+ t.timestamps null: false
103
103
  end
104
104
 
105
105
  create_table :copyable_toys, force: true do |t|
106
106
  t.string :name
107
107
  t.string :kind
108
108
  t.integer :copyable_pet_id
109
- t.timestamps
109
+ t.timestamps null: false
110
110
  end
111
111
 
112
112
  create_table :copyable_trees, force: true do |t|
113
113
  t.string :kind
114
- t.timestamps
114
+ t.timestamps null: false
115
115
  end
116
116
 
117
117
  create_table :copyable_vehicles, force: true do |t|
118
118
  t.string :name
119
119
  t.integer :copyable_owner_id
120
- t.timestamps
120
+ t.timestamps null: false
121
121
  end
122
122
 
123
123
  create_table :copyable_warranties, force: true do |t|
124
124
  t.string :name
125
125
  t.integer :copyable_amenity_id
126
- t.timestamps
126
+ t.timestamps null: false
127
127
  end
128
128
 
129
129
  end
@@ -9,85 +9,31 @@ describe Copyable::ModelHooks do
9
9
  before(:each) do
10
10
  Copyable::ModelHooks.disable!(CopyableTree)
11
11
  end
12
+
12
13
  after(:each) do
13
14
  Copyable::ModelHooks.reenable!(CopyableTree)
14
15
  end
15
- it 'should prevent callbacks from executing' do
16
- expect {
17
- CopyableTree.create!(kind: 'magnolia')
18
- }.to_not raise_error
16
+
17
+ it 'defines an instance variable on the class' do
18
+ expect(CopyableTree.all_callbacks_disabled).to eq(true)
19
19
  end
20
+
20
21
  it 'should not prevent model actions from executing' do
21
22
  expect(CopyableTree.count).to eq(0)
22
- CopyableTree.create!(kind: 'magnolia')
23
- expect(CopyableTree.count).to eq(1)
24
23
  end
25
24
  end
26
25
 
27
26
  describe '.reenable!' do
28
- it 'should allow callbacks to execute again' do
29
- Copyable::ModelHooks.disable!(CopyableTree)
27
+ it 'defines an instance variable on the class' do
30
28
  Copyable::ModelHooks.reenable!(CopyableTree)
31
- expect {
32
- CopyableTree.create!(kind: 'magnolia')
33
- }.to raise_error(RuntimeError, "callback2 called")
29
+ expect(CopyableTree.all_callbacks_disabled).to eq(false)
34
30
  end
35
- end
36
- end
37
-
38
- context 'validations' do
39
31
 
40
- # Note: the relevant model and observer class is defined in helper/test_models.rb
41
-
42
- describe '.disable!' do
43
- before(:each) do
44
- Copyable::ModelHooks.disable!(CopyableCoin)
45
- end
46
- after(:each) do
47
- Copyable::ModelHooks.reenable!(CopyableCoin)
48
- end
49
- it 'should prevent validations from executing' do
50
- expect {
51
- CopyableCoin.create!(year: -10)
52
- }.to_not raise_error
53
- end
54
- it 'should not prevent model actions from executing' do
55
- expect(CopyableCoin.count).to eq(0)
56
- CopyableCoin.create!(year: -10)
57
- expect(CopyableCoin.count).to eq(1)
58
- end
59
- end
60
-
61
- describe '.reenable!' do
62
- it 'should allow validations to execute again' do
63
- Copyable::ModelHooks.disable!(CopyableCoin)
64
- Copyable::ModelHooks.reenable!(CopyableCoin)
32
+ it 'should allow callbacks to execute again' do
65
33
  expect {
66
- CopyableCoin.create!(year: -10)
67
- }.to raise_error(ActiveRecord::RecordInvalid)
34
+ CopyableTree.create!(kind: 'magnolia')
35
+ }.to raise_error(RuntimeError, "callback2 called")
68
36
  end
69
37
  end
70
38
  end
71
-
72
- describe 'nested disables and enables' do
73
- it 'should allow callbacks to execute again' do
74
- Copyable::ModelHooks.disable!(CopyableTree)
75
- expect { CopyableTree.create!(kind: 'magnolia') }.to_not raise_error
76
-
77
- Copyable::ModelHooks.disable!(CopyableCoin)
78
- expect { CopyableCoin.create!(year: -10) }.to_not raise_error
79
-
80
- Copyable::ModelHooks.disable!(CopyableTree)
81
- expect { CopyableTree.create!(kind: 'magnolia') }.to_not raise_error
82
-
83
- Copyable::ModelHooks.reenable!(CopyableCoin)
84
- expect { CopyableCoin.create!(year: -10) }.to raise_error(ActiveRecord::RecordInvalid)
85
-
86
- Copyable::ModelHooks.reenable!(CopyableTree)
87
- expect { CopyableTree.create!(kind: 'magnolia') }.to raise_error(RuntimeError)
88
-
89
- Copyable::ModelHooks.reenable!(CopyableTree)
90
- expect { CopyableTree.create!(kind: 'magnolia') }.to raise_error(RuntimeError)
91
- end
92
- end
93
39
  end
metadata CHANGED
@@ -1,58 +1,60 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: copyable
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Wyatt Greene
8
8
  - Dennis Chan
9
- autorequire:
9
+ - Anne Geiersbach
10
+ - Parker Morse
11
+ autorequire:
10
12
  bindir: bin
11
13
  cert_chain: []
12
- date: 2018-02-08 00:00:00.000000000 Z
14
+ date: 2021-08-18 00:00:00.000000000 Z
13
15
  dependencies:
14
16
  - !ruby/object:Gem::Dependency
15
17
  name: activerecord
16
18
  requirement: !ruby/object:Gem::Requirement
17
19
  requirements:
18
- - - "~>"
20
+ - - '='
19
21
  - !ruby/object:Gem::Version
20
- version: 4.1.0
22
+ version: 5.2.6
21
23
  type: :runtime
22
24
  prerelease: false
23
25
  version_requirements: !ruby/object:Gem::Requirement
24
26
  requirements:
25
- - - "~>"
27
+ - - '='
26
28
  - !ruby/object:Gem::Version
27
- version: 4.1.0
29
+ version: 5.2.6
28
30
  - !ruby/object:Gem::Dependency
29
31
  name: database_cleaner
30
32
  requirement: !ruby/object:Gem::Requirement
31
33
  requirements:
32
34
  - - "~>"
33
35
  - !ruby/object:Gem::Version
34
- version: 1.4.0
36
+ version: '2'
35
37
  type: :development
36
38
  prerelease: false
37
39
  version_requirements: !ruby/object:Gem::Requirement
38
40
  requirements:
39
41
  - - "~>"
40
42
  - !ruby/object:Gem::Version
41
- version: 1.4.0
43
+ version: '2'
42
44
  - !ruby/object:Gem::Dependency
43
45
  name: bundler
44
46
  requirement: !ruby/object:Gem::Requirement
45
47
  requirements:
46
- - - "~>"
48
+ - - ">="
47
49
  - !ruby/object:Gem::Version
48
- version: '1.6'
50
+ version: '0'
49
51
  type: :development
50
52
  prerelease: false
51
53
  version_requirements: !ruby/object:Gem::Requirement
52
54
  requirements:
53
- - - "~>"
55
+ - - ">="
54
56
  - !ruby/object:Gem::Version
55
- version: '1.6'
57
+ version: '0'
56
58
  - !ruby/object:Gem::Dependency
57
59
  name: rake
58
60
  requirement: !ruby/object:Gem::Requirement
@@ -85,19 +87,21 @@ dependencies:
85
87
  name: sqlite3
86
88
  requirement: !ruby/object:Gem::Requirement
87
89
  requirements:
88
- - - ">="
90
+ - - "~>"
89
91
  - !ruby/object:Gem::Version
90
- version: '0'
92
+ version: 1.3.6
91
93
  type: :development
92
94
  prerelease: false
93
95
  version_requirements: !ruby/object:Gem::Requirement
94
96
  requirements:
95
- - - ">="
97
+ - - "~>"
96
98
  - !ruby/object:Gem::Version
97
- version: '0'
99
+ version: 1.3.6
98
100
  description: Copyable makes it easy to copy ActiveRecord models.
99
101
  email:
100
- - dchan@dmcouncil.org
102
+ - dchan@dmgroupK12.com
103
+ - ageiersbach@dmgroupK12.com
104
+ - pmorse@dmgroupK12.com
101
105
  executables: []
102
106
  extensions: []
103
107
  extra_rdoc_files: []
@@ -158,7 +162,7 @@ homepage: https://github.com/dmcouncil/copyable
158
162
  licenses:
159
163
  - MIT
160
164
  metadata: {}
161
- post_install_message:
165
+ post_install_message:
162
166
  rdoc_options: []
163
167
  require_paths:
164
168
  - lib
@@ -173,9 +177,8 @@ required_rubygems_version: !ruby/object:Gem::Requirement
173
177
  - !ruby/object:Gem::Version
174
178
  version: '0'
175
179
  requirements: []
176
- rubyforge_project:
177
- rubygems_version: 2.6.12
178
- signing_key:
180
+ rubygems_version: 3.1.4
181
+ signing_key:
179
182
  specification_version: 4
180
183
  summary: ActiveRecord copier
181
184
  test_files: