copyable 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +38 -32
- data/copyable.gemspec +1 -1
- data/lib/copyable/version.rb +1 -1
- metadata +22 -22
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: df943b2cab1eb85ee8f53faff3a908dbcec38198
|
4
|
+
data.tar.gz: 3229ce6dbef3e246d9327f2bbd2b83377a4b77e0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8de6edeca4d17dceb962f8921581a20e292380ddb3089d34b8473314e8e0ef1eff494f05b5196f1a040ac9b433a78e99278bd5dc763789912171eb96311623c0
|
7
|
+
data.tar.gz: c0371addf28eb0121008e1720bed8ab975bfd7eaaf78f6a313acc3de7076a967d2e65ab27195869aa0f1ca7f157f6d742c345e1256c811a9d9061b5285fb906d
|
data/README.md
CHANGED
@@ -1,5 +1,7 @@
|
|
1
1
|
# Copyable
|
2
2
|
|
3
|
+
[![Code Climate](https://codeclimate.com/github/dmcouncil/copyable/badges/gpa.svg)](https://codeclimate.com/github/dmcouncil/copyable)
|
4
|
+
|
3
5
|
Copyable makes it easy to copy ActiveRecord models.
|
4
6
|
|
5
7
|
# Installation
|
@@ -21,7 +23,7 @@ Or install it yourself as:
|
|
21
23
|
|
22
24
|
## Basic Usage
|
23
25
|
|
24
|
-
Copyable gives you a create_copy
|
26
|
+
Copyable gives you a `create_copy!` method that you can use to copy ActiveRecord models:
|
25
27
|
|
26
28
|
isaiah = Book.create!(title: "Isaiah")
|
27
29
|
copy_of_isaiah = isaiah.create_copy!
|
@@ -32,7 +34,7 @@ Now there are two books called "Isaiah" in the database.
|
|
32
34
|
|
33
35
|
## The Copyable Declaration
|
34
36
|
|
35
|
-
In order for an ActiveRecord model class to have the create_copy
|
37
|
+
In order for an ActiveRecord model class to have the `create_copy!` method defined on it, you need to add a copyable declaration:
|
36
38
|
|
37
39
|
class Book < ActiveRecord::Base
|
38
40
|
|
@@ -60,15 +62,15 @@ The columns declaration specifies how each individual column should be copied:
|
|
60
62
|
...
|
61
63
|
end
|
62
64
|
|
63
|
-
Every column *must* be listed here (with the exception of id
|
65
|
+
Every column *must* be listed here (with the exception of `id`, `created_at`, `created_on`, `updated_at` or `updated_on`).
|
64
66
|
|
65
67
|
After each column name, give advice on how to copy that column. The advice must be one of the following:
|
66
68
|
|
67
|
-
*
|
68
|
-
*
|
69
|
-
* lambda { |orig| ... }
|
69
|
+
* `:copy`
|
70
|
+
* `:do_not_copy`
|
71
|
+
* `lambda { |orig| ... }`
|
70
72
|
|
71
|
-
|
73
|
+
`:copy` copies the value from the original model. `:do_not_copy` simply places `nil` in the column. Using a block lets you calculate the value of the column. The block is passed the original ActiveRecord model object that is being copied.
|
72
74
|
|
73
75
|
Here's another example:
|
74
76
|
|
@@ -100,28 +102,28 @@ The associations declaration specifies whether to copy the associated models:
|
|
100
102
|
|
101
103
|
Every association *must* be listed here, with two exceptions:
|
102
104
|
|
103
|
-
* belongs_to associations must not be listed here. Since belongs_to associations will have a foreign key column, the association will be copied when its column is copied.
|
104
|
-
* has_many :through associations must not be listed here, because they are always associated with a related has_many association that will already have been listed.
|
105
|
+
* `belongs_to` associations must not be listed here. Since `belongs_to` associations will have a foreign key column, the association will be copied when its column is copied.
|
106
|
+
* `has_many :through` associations must not be listed here, because they are always associated with a related `has_many` association that will already have been listed.
|
105
107
|
|
106
108
|
The advice must be one of the following:
|
107
109
|
|
108
|
-
*
|
109
|
-
*
|
110
|
-
*
|
110
|
+
* `:copy`
|
111
|
+
* `:do_not_copy`
|
112
|
+
* `:copy_only_habtm_join_records`
|
111
113
|
|
112
|
-
|
114
|
+
`:copy` will iterate through each model in the association, creating a copy. Note that the associated model class must also have a copyable declaration, so that we know how to copy it!
|
113
115
|
|
114
|
-
|
116
|
+
`:do_not_copy` does nothing.
|
115
117
|
|
116
|
-
|
118
|
+
`:copy_only_habtm_join_records` can only be used on `has_and_belongs_to_many` associations. In fact, you can't use `:copy` on `has_and_belongs_to_many` associations. Models associated via habtm are never actually copied, but their associations in the relevant join table can be.
|
117
119
|
|
118
120
|
|
119
121
|
|
120
122
|
## Callbacks
|
121
123
|
|
122
|
-
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
|
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.
|
123
125
|
|
124
|
-
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
|
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.
|
125
127
|
|
126
128
|
copyable do
|
127
129
|
disable_all_callbacks_and_observers_except_validate
|
@@ -132,7 +134,7 @@ To make it easier to reason about the code, and for the sake of being obvious, e
|
|
132
134
|
|
133
135
|
## The After Copy Declaration
|
134
136
|
|
135
|
-
In case you wanted to make sure a particular callback is run, or in case you had some special custom copying behavior, an after_copy declaration is provided that is called after the model has been copied.
|
137
|
+
In case you wanted to make sure a particular callback is run, or in case you had some special custom copying behavior, an `after_copy` declaration is provided that is called after the model has been copied. It is passed the original model and the newly copied model. Note that all callbacks and observers are disabled during the execution of the `after_copy` block, so you must call them explicitly if you want them to run.
|
136
138
|
|
137
139
|
copyable do
|
138
140
|
...
|
@@ -146,7 +148,7 @@ In case you wanted to make sure a particular callback is run, or in case you had
|
|
146
148
|
|
147
149
|
## Putting It All Together
|
148
150
|
|
149
|
-
Here is an example of all four declarations being used in a copyable declaration. Note that all declarations are required except for after_copy
|
151
|
+
Here is an example of all four declarations being used in a copyable declaration. Note that all declarations are required except for `after_copy`.
|
150
152
|
|
151
153
|
copyable do
|
152
154
|
disable_all_callbacks_and_observers_except_validate
|
@@ -169,17 +171,17 @@ Here is an example of all four declarations being used in a copyable declaration
|
|
169
171
|
|
170
172
|
## create_copy!
|
171
173
|
|
172
|
-
The create_copy
|
174
|
+
The `create_copy!` method allows you to override column values by passing in a hash.
|
173
175
|
|
174
176
|
isaiah = Book.create!(title: "Isaiah")
|
175
177
|
copy_of_isaiah = isaiah.create_copy!
|
176
178
|
copy_of_isaiah2 = isaiah.create_copy!(override: { title: "Foo" })
|
177
179
|
|
178
|
-
copy_of_isaiah.title will be "Copy of Isaiah" (or whatever the advice was given in the columns declaration).
|
180
|
+
`copy_of_isaiah.title` will be "Copy of Isaiah" (or whatever the advice was given in the columns declaration).
|
179
181
|
|
180
|
-
copy_of_isaiah2.title will be "Foo".
|
182
|
+
`copy_of_isaiah2.title` will be "Foo".
|
181
183
|
|
182
|
-
Note that you pass in column names only, so if you want to update a
|
184
|
+
Note that you pass in column names only, so if you want to update a `belongs_to` association, you must pass in the column name, not the association name.
|
183
185
|
|
184
186
|
isaiah.create_copy!(override: { author: "Isaiah" }) # NO, bad programmer
|
185
187
|
isaiah.create_copy!(override: { author_id: 34 }) # YES
|
@@ -202,9 +204,9 @@ Currently copyable only has one configuration setting:
|
|
202
204
|
|
203
205
|
Copyable.config.suppress_schema_errors = false
|
204
206
|
|
205
|
-
This is false by default.
|
207
|
+
This is `false` by default. Set this to true if you don't want Copyable to complain with a ColumnError or AssociationError if your database schema does not match your copyable declarations.
|
206
208
|
|
207
|
-
You can also set an environment variable called SUPPRESS_SCHEMA_ERRORS to true.
|
209
|
+
You can also set an environment variable called `SUPPRESS_SCHEMA_ERRORS` to true.
|
208
210
|
|
209
211
|
|
210
212
|
|
@@ -221,7 +223,7 @@ You can also set an environment variable called SUPPRESS_SCHEMA_ERRORS to true.
|
|
221
223
|
## Strengths
|
222
224
|
|
223
225
|
* handles polymorphic associations
|
224
|
-
* create_copy
|
226
|
+
* `create_copy!` is run in a database transaction
|
225
227
|
* keeps track of which models have already been copied so that it does not re-copy them if it comes across them again (helpful for complex model hierarchies with redundant associations)
|
226
228
|
|
227
229
|
|
@@ -231,15 +233,15 @@ You can also set an environment variable called SUPPRESS_SCHEMA_ERRORS to true.
|
|
231
233
|
* not thread-safe
|
232
234
|
* copying very large data structures may use a lot of memory
|
233
235
|
* not designed with performance (CPU or database) in mind
|
234
|
-
* had to monkey-patch Rails
|
236
|
+
* had to monkey-patch Rails
|
235
237
|
* postponed support for single table inheritance until needed
|
236
|
-
* postponed support for keeping counter_cache correct until needed
|
238
|
+
* postponed support for keeping `counter_cache` correct until needed
|
237
239
|
|
238
240
|
|
239
241
|
|
240
242
|
## Convenience
|
241
243
|
|
242
|
-
A rake task is included that will output a basic copyable declaration given a model name.
|
244
|
+
A rake task is included that will output a basic copyable declaration given a model name. Basically, this saves you some typing.
|
243
245
|
|
244
246
|
$ rake copyable model=User
|
245
247
|
|
@@ -247,11 +249,11 @@ A rake task is included that will output a basic copyable declaration given a mo
|
|
247
249
|
|
248
250
|
## Gotchas
|
249
251
|
|
250
|
-
### Creating Objects in after_copy
|
252
|
+
### Creating Objects in `after_copy`
|
251
253
|
|
252
|
-
copyable keeps track of which models have already been copied so as not to reduplicate models if it comes across the same model through different associations.
|
254
|
+
copyable keeps track of which models have already been copied so as not to reduplicate models if it comes across the same model through different associations. If you are creating new objects in `after_copy!` (such as manually copying an association instead of letting copyable do it), you do not have the benefit of copyable's checking whether the models have already been copied and may end up creating too many copies.
|
253
255
|
|
254
|
-
So the recommended approach is to use after_copy to tweak the columns of the copied record but to avoid creating new records here.
|
256
|
+
So the recommended approach is to use `after_copy` to tweak the columns of the copied record but to avoid creating new records here.
|
255
257
|
|
256
258
|
|
257
259
|
|
@@ -262,3 +264,7 @@ So the recommended approach is to use after_copy to tweak the columns of the cop
|
|
262
264
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
263
265
|
4. Push to the branch (`git push origin my-new-feature`)
|
264
266
|
5. Create a new Pull Request
|
267
|
+
|
268
|
+
## About
|
269
|
+
|
270
|
+
Copyable was developed at [the District Management Council](http://dmcouncil.org).
|
data/copyable.gemspec
CHANGED
@@ -18,7 +18,7 @@ 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", "
|
21
|
+
spec.add_dependency "activerecord", "~>4.1"
|
22
22
|
|
23
23
|
spec.add_development_dependency "database_cleaner", "~> 1.4.0"
|
24
24
|
spec.add_development_dependency "bundler", "~> 1.6"
|
data/lib/copyable/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: copyable
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Wyatt Greene
|
@@ -9,90 +9,90 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-03
|
12
|
+
date: 2016-08-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - "~>"
|
19
19
|
- !ruby/object:Gem::Version
|
20
|
-
version: 4.1
|
20
|
+
version: '4.1'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - "~>"
|
26
26
|
- !ruby/object:Gem::Version
|
27
|
-
version: 4.1
|
27
|
+
version: '4.1'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: database_cleaner
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- - ~>
|
32
|
+
- - "~>"
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: 1.4.0
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- - ~>
|
39
|
+
- - "~>"
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: 1.4.0
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: bundler
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- - ~>
|
46
|
+
- - "~>"
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '1.6'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- - ~>
|
53
|
+
- - "~>"
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '1.6'
|
56
56
|
- !ruby/object:Gem::Dependency
|
57
57
|
name: rake
|
58
58
|
requirement: !ruby/object:Gem::Requirement
|
59
59
|
requirements:
|
60
|
-
- -
|
60
|
+
- - ">="
|
61
61
|
- !ruby/object:Gem::Version
|
62
62
|
version: '0'
|
63
63
|
type: :development
|
64
64
|
prerelease: false
|
65
65
|
version_requirements: !ruby/object:Gem::Requirement
|
66
66
|
requirements:
|
67
|
-
- -
|
67
|
+
- - ">="
|
68
68
|
- !ruby/object:Gem::Version
|
69
69
|
version: '0'
|
70
70
|
- !ruby/object:Gem::Dependency
|
71
71
|
name: rspec
|
72
72
|
requirement: !ruby/object:Gem::Requirement
|
73
73
|
requirements:
|
74
|
-
- -
|
74
|
+
- - ">="
|
75
75
|
- !ruby/object:Gem::Version
|
76
76
|
version: '0'
|
77
77
|
type: :development
|
78
78
|
prerelease: false
|
79
79
|
version_requirements: !ruby/object:Gem::Requirement
|
80
80
|
requirements:
|
81
|
-
- -
|
81
|
+
- - ">="
|
82
82
|
- !ruby/object:Gem::Version
|
83
83
|
version: '0'
|
84
84
|
- !ruby/object:Gem::Dependency
|
85
85
|
name: sqlite3
|
86
86
|
requirement: !ruby/object:Gem::Requirement
|
87
87
|
requirements:
|
88
|
-
- -
|
88
|
+
- - ">="
|
89
89
|
- !ruby/object:Gem::Version
|
90
90
|
version: '0'
|
91
91
|
type: :development
|
92
92
|
prerelease: false
|
93
93
|
version_requirements: !ruby/object:Gem::Requirement
|
94
94
|
requirements:
|
95
|
-
- -
|
95
|
+
- - ">="
|
96
96
|
- !ruby/object:Gem::Version
|
97
97
|
version: '0'
|
98
98
|
description: Copyable makes it easy to copy ActiveRecord models.
|
@@ -102,9 +102,9 @@ executables: []
|
|
102
102
|
extensions: []
|
103
103
|
extra_rdoc_files: []
|
104
104
|
files:
|
105
|
-
- .gitignore
|
106
|
-
- .rspec
|
107
|
-
- .travis.yml
|
105
|
+
- ".gitignore"
|
106
|
+
- ".rspec"
|
107
|
+
- ".travis.yml"
|
108
108
|
- Gemfile
|
109
109
|
- LICENSE.txt
|
110
110
|
- README.md
|
@@ -164,17 +164,17 @@ require_paths:
|
|
164
164
|
- lib
|
165
165
|
required_ruby_version: !ruby/object:Gem::Requirement
|
166
166
|
requirements:
|
167
|
-
- -
|
167
|
+
- - ">="
|
168
168
|
- !ruby/object:Gem::Version
|
169
169
|
version: '0'
|
170
170
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
171
171
|
requirements:
|
172
|
-
- -
|
172
|
+
- - ">="
|
173
173
|
- !ruby/object:Gem::Version
|
174
174
|
version: '0'
|
175
175
|
requirements: []
|
176
176
|
rubyforge_project:
|
177
|
-
rubygems_version: 2.
|
177
|
+
rubygems_version: 2.4.8
|
178
178
|
signing_key:
|
179
179
|
specification_version: 4
|
180
180
|
summary: ActiveRecord copier
|