activerecord-duplicate 0.5.0 → 0.5.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |gem|
2
2
  gem.name = 'activerecord-duplicate'
3
- gem.version = '0.5.0'
3
+ gem.version = '0.5.1'
4
4
  gem.authors = 'Mario Uher'
5
5
  gem.email = 'uher.mario@gmail.com'
6
6
  gem.description = gem.summary = 'Duplicating ActiveRecords is easy again.'
@@ -1,10 +1,11 @@
1
1
  source :rubygems
2
2
 
3
- gem 'activerecord', git: 'git://github.com/rails/rails.git'
3
+ gem 'activerecord', github: 'rails/rails'
4
+ gem 'active_record_deprecated_finders', github: 'rails/active_record_deprecated_finders'
4
5
 
5
6
  group :development do
6
7
  gem 'minitest'
7
8
  gem 'purdytest'
8
- gem 'rails', git: 'git://github.com/rails/rails.git'
9
+ gem 'rails', github: 'rails/rails'
9
10
  gem 'sqlite3'
10
11
  end
@@ -1,4 +1,4 @@
1
- require 'activerecord-duplicate/active_record/duplicate'
1
+ require 'activerecord-duplicate/duplicate'
2
2
  require 'activerecord-duplicate/railtie' if defined?(Rails)
3
3
 
4
4
  module ActiveRecord::Duplicate
@@ -0,0 +1,95 @@
1
+ module ActiveRecord::Duplicate
2
+ extend ActiveSupport::Concern
3
+
4
+ included do
5
+ define_callbacks :duplication, terminator: "result == false", scope: [:kind, :name]
6
+
7
+ class_attribute :_duplicatable_attributes
8
+ attr_accessor :duplication_parent, :duplication_context
9
+ end
10
+
11
+ def duplicate
12
+ self.duplication_context = :original
13
+ self.run_callbacks(:duplication) do
14
+ dup.tap do |duplicate|
15
+ duplicate.duplication_context = :duplicate
16
+ duplicate.run_callbacks(:duplication) do
17
+ attributes.each do |key, value|
18
+ value = case true
19
+
20
+ # Duplicate attribute if whitelisted
21
+ when self.class.attr_duplicatable.include?(key.to_sym)
22
+ value
23
+
24
+ # If not whitelisted, set to default value
25
+ when (column = self.class.columns.detect { |c| c.name == key }).present?
26
+ column.default
27
+
28
+ else
29
+ nil
30
+ end
31
+
32
+ duplicate.send(:"#{key}=", value)
33
+ end
34
+
35
+ self.class.reflect_on_all_associations.each do |association|
36
+ name = association.name
37
+ macro = association.macro
38
+ association = self.association(association.name)
39
+
40
+ case macro
41
+ when :belongs_to
42
+ # Duplicate all belongs_to associations.
43
+ if duplication_parent.is_a?(association.klass)
44
+ duplicate.send(:"#{name}=", duplication_parent)
45
+ duplicate.send(:"#{name}_id=", nil)
46
+ else
47
+ duplicate.send(:"#{name}=", send(name))
48
+ end
49
+
50
+ when :has_many
51
+ # Duplicate all has_many associations.
52
+ duplicate.send(:"#{name}=", send(name).map do |object|
53
+ object.duplication_parent = duplicate
54
+ object = object.duplicate
55
+ next unless object.present?
56
+
57
+ object
58
+ end.compact)
59
+ end
60
+ end
61
+ end
62
+ end
63
+ end
64
+ end
65
+
66
+ module ClassMethods
67
+ def attr_duplicatable(*attributes)
68
+ self._duplicatable_attributes = attributes.map(&:to_sym) if attributes.present?
69
+ self._duplicatable_attributes || []
70
+ end
71
+
72
+ # Duplicated from activemodel/lib/active_model/validations/callbacks.rb
73
+ def before_duplication(*args, &block)
74
+ options = args.last
75
+
76
+ if options.is_a?(Hash) && options[:on]
77
+ options[:if] = Array.wrap(options[:if])
78
+ options[:if].unshift("self.duplication_context == :#{options[:on]}")
79
+ end
80
+
81
+ set_callback(:duplication, :before, *args, &block)
82
+ end
83
+
84
+ def after_duplication(*args, &block)
85
+ options = args.extract_options!
86
+
87
+ options[:prepend] = true
88
+ options[:if] = Array.wrap(options[:if])
89
+ options[:if] << "!halted"
90
+ options[:if].unshift("self.duplication_context == :#{options[:on]}") if options[:on]
91
+
92
+ set_callback(:duplication, :after, *(args << options), &block)
93
+ end
94
+ end
95
+ end
@@ -1,6 +1,6 @@
1
1
  require File.expand_path('../spec_helper', __FILE__)
2
2
 
3
- describe ActiveRecord::Duplicate::Callbacks do
3
+ describe ActiveRecord::Duplicate do
4
4
  let(:klass) { Class.new(ActiveRecord::Base) { self.table_name = 'records' } }
5
5
 
6
6
 
@@ -16,7 +16,7 @@ describe ActiveRecord::Duplicate::Callbacks do
16
16
  mock.expect(:after_duplication, nil, [:original])
17
17
  mock.expect(:before_duplication, nil, [:duplicate])
18
18
  mock.expect(:after_duplication, nil, [:duplicate])
19
-
19
+
20
20
  klass.create.duplicate
21
21
  mock.verify
22
22
  end
@@ -32,23 +32,16 @@ describe 'Integration' do
32
32
  class Post < ActiveRecord::Base
33
33
  # Don't duplicate copyrighted posts
34
34
  before_duplication { !self.is_copyrighted? }
35
- after_duplication(:increase_counter, on: :duplicate)
35
+ after_duplication(on: :duplicate) { self.title = title.match(/\d+$/) ? title.succ : "#{title} 2" }
36
36
 
37
37
  belongs_to :blog
38
38
  has_many :comments
39
39
  has_many :ratings, as: :parent
40
40
 
41
- attr_duplicatable :content
41
+ attr_duplicatable :title, :content
42
42
  class_attribute :counter
43
43
 
44
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
45
  end
53
46
 
54
47
  class Comment < ActiveRecord::Base
@@ -64,7 +57,7 @@ describe 'Integration' do
64
57
  end
65
58
 
66
59
 
67
- let(:blog) { Blog.create }
60
+ let(:blog) { Blog.create! }
68
61
 
69
62
 
70
63
  describe 'duplicating blog' do
@@ -78,15 +71,15 @@ describe 'Integration' do
78
71
 
79
72
 
80
73
  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)
74
+ %w[Sample Blog Post].each do |title|
75
+ post = blog.posts.create!(title: title)
76
+ rating = post.ratings.create!(value: 5)
84
77
  end
85
78
 
86
79
  subject.posts.all?(&:new_record?).must_equal(true)
87
80
  subject.posts.size.must_equal(3)
88
81
 
89
- subject.save
82
+ subject.save!
90
83
 
91
84
  Blog.count.must_equal(2)
92
85
  Post.count.must_equal(6)
@@ -95,28 +88,30 @@ describe 'Integration' do
95
88
 
96
89
 
97
90
  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)
91
+ %w[Sample Blog Post].each do |title|
92
+ post = blog.posts.create!(title: title)
93
+ rating = post.ratings.create!(value: 5)
101
94
  end
102
95
 
103
96
  subject.posts.each do |post|
104
97
  post.blog.must_equal(subject)
105
98
  post.blog_id.must_be_nil
106
99
  end
100
+
101
+ subject.save!
107
102
  end
108
103
 
109
104
 
110
105
  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)
106
+ %w[Sample Blog Post].each do |title|
107
+ post = blog.posts.create!(title: title, is_copyrighted: title == 'Sample')
108
+ rating = post.ratings.create!(value: 5)
114
109
  end
115
110
 
116
111
  subject.posts.all?(&:new_record?).must_equal(true)
117
112
  subject.posts.size.must_equal(2)
118
113
 
119
- subject.save
114
+ subject.save!
120
115
 
121
116
  Blog.count.must_equal(2)
122
117
  Post.count.must_equal(5)
@@ -124,27 +119,29 @@ describe 'Integration' do
124
119
  end
125
120
 
126
121
 
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)
122
+ it 'ignores posts published_at timestamp' do
123
+ post = blog.posts.create!(title: 'Post', content: 'Lorem', published_at: Time.now)
124
+ rating = post.ratings.create!(value: 5)
130
125
 
131
126
  post = subject.posts.first
132
127
  post.wont_be_nil
133
128
  post.content.must_equal('Lorem')
134
129
  post.published_at.must_be_nil
130
+
131
+ subject.save!
135
132
  end
136
133
 
137
134
 
138
135
  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 }
136
+ post = blog.posts.create!(title: 'Post')
137
+ rating = post.ratings.create!(value: 5)
138
+ 3.times { post.comments.create! }
142
139
 
143
140
  post = subject.posts.first
144
141
  post.wont_be_nil
145
142
  post.comments.size.must_equal(0)
146
143
 
147
- subject.save
144
+ subject.save!
148
145
 
149
146
  Blog.count.must_equal(2)
150
147
  Post.count.must_equal(2)
@@ -156,9 +153,10 @@ describe 'Integration' do
156
153
 
157
154
  describe 'duplicating post' do
158
155
  it 'sets blog association' do
159
- post = blog.posts.create
156
+ post = blog.posts.create!(title: 'Post')
160
157
 
161
158
  post = post.duplicate
159
+ post.save!
162
160
 
163
161
  post.blog.must_equal(blog)
164
162
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: activerecord-duplicate
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.5.0
4
+ version: 0.5.1
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,11 +9,11 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2012-04-18 00:00:00.000000000 Z
12
+ date: 2012-04-20 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: activerecord
16
- requirement: &70285775741840 !ruby/object:Gem::Requirement
16
+ requirement: &70282697881420 !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
19
  - - ! '>='
@@ -21,10 +21,10 @@ dependencies:
21
21
  version: '3.1'
22
22
  type: :runtime
23
23
  prerelease: false
24
- version_requirements: *70285775741840
24
+ version_requirements: *70282697881420
25
25
  - !ruby/object:Gem::Dependency
26
26
  name: minitest
27
- requirement: &70285775741440 !ruby/object:Gem::Requirement
27
+ requirement: &70282697880800 !ruby/object:Gem::Requirement
28
28
  none: false
29
29
  requirements:
30
30
  - - ! '>='
@@ -32,10 +32,10 @@ dependencies:
32
32
  version: '0'
33
33
  type: :development
34
34
  prerelease: false
35
- version_requirements: *70285775741440
35
+ version_requirements: *70282697880800
36
36
  - !ruby/object:Gem::Dependency
37
37
  name: purdytest
38
- requirement: &70285775740980 !ruby/object:Gem::Requirement
38
+ requirement: &70282697880060 !ruby/object:Gem::Requirement
39
39
  none: false
40
40
  requirements:
41
41
  - - ! '>='
@@ -43,10 +43,10 @@ dependencies:
43
43
  version: '0'
44
44
  type: :development
45
45
  prerelease: false
46
- version_requirements: *70285775740980
46
+ version_requirements: *70282697880060
47
47
  - !ruby/object:Gem::Dependency
48
48
  name: rails
49
- requirement: &70285775740480 !ruby/object:Gem::Requirement
49
+ requirement: &70282697879480 !ruby/object:Gem::Requirement
50
50
  none: false
51
51
  requirements:
52
52
  - - ! '>='
@@ -54,10 +54,10 @@ dependencies:
54
54
  version: '3.1'
55
55
  type: :development
56
56
  prerelease: false
57
- version_requirements: *70285775740480
57
+ version_requirements: *70282697879480
58
58
  - !ruby/object:Gem::Dependency
59
59
  name: rake
60
- requirement: &70285775740060 !ruby/object:Gem::Requirement
60
+ requirement: &70282697879060 !ruby/object:Gem::Requirement
61
61
  none: false
62
62
  requirements:
63
63
  - - ! '>='
@@ -65,10 +65,10 @@ dependencies:
65
65
  version: '0'
66
66
  type: :development
67
67
  prerelease: false
68
- version_requirements: *70285775740060
68
+ version_requirements: *70282697879060
69
69
  - !ruby/object:Gem::Dependency
70
70
  name: sqlite3
71
- requirement: &70285775739600 !ruby/object:Gem::Requirement
71
+ requirement: &70282697878580 !ruby/object:Gem::Requirement
72
72
  none: false
73
73
  requirements:
74
74
  - - ! '>='
@@ -76,7 +76,7 @@ dependencies:
76
76
  version: '0'
77
77
  type: :development
78
78
  prerelease: false
79
- version_requirements: *70285775739600
79
+ version_requirements: *70282697878580
80
80
  description: Duplicating ActiveRecords is easy again.
81
81
  email: uher.mario@gmail.com
82
82
  executables: []
@@ -92,8 +92,7 @@ files:
92
92
  - gemfiles/Rails_3_2.gemfile
93
93
  - gemfiles/Rails_master.gemfile
94
94
  - lib/activerecord-duplicate.rb
95
- - lib/activerecord-duplicate/active_record/duplicate.rb
96
- - lib/activerecord-duplicate/active_record/duplicate/callbacks.rb
95
+ - lib/activerecord-duplicate/duplicate.rb
97
96
  - lib/activerecord-duplicate/railtie.rb
98
97
  - spec/acts_as_duplicator_spec.rb
99
98
  - spec/callbacks_spec.rb
@@ -1,71 +0,0 @@
1
- require 'activerecord-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
-
10
- attr_accessor :duplication_parent
11
-
12
- include ActiveRecord::Duplicate::Callbacks
13
- end
14
-
15
- def duplicate
16
- dup.tap do |duplicate|
17
- attributes.each do |key, value|
18
- value = case true
19
-
20
- # Duplicate attribute if whitelisted
21
- when self.class.attr_duplicatable.include?(key.to_sym)
22
- value
23
-
24
- # If not whitelisted, set to default value
25
- when (column = self.class.columns.detect { |c| c.name == key }).present?
26
- column.default
27
-
28
- else
29
- nil
30
- end
31
-
32
- duplicate.send(:"#{key}=", value)
33
- end
34
-
35
- self.class.reflect_on_all_associations.each do |association|
36
- name = association.name
37
- macro = association.macro
38
- association = self.association(association.name)
39
-
40
- case macro
41
- when :belongs_to
42
- # Duplicate all belongs_to associations.
43
- if duplication_parent.is_a?(association.klass)
44
- duplicate.send(:"#{name}=", duplication_parent)
45
- duplicate.send(:"#{name}_id=", nil)
46
- else
47
- duplicate.send(:"#{name}=", send(name))
48
- end
49
-
50
- when :has_many
51
- # Duplicate all has_many associations.
52
- duplicate.send(:"#{name}=", send(name).map do |object|
53
- object.duplication_parent = duplicate
54
- object = object.duplicate
55
- next unless object.present?
56
-
57
- object
58
- end.compact)
59
- end
60
- end
61
- end
62
- end
63
-
64
- module ClassMethods
65
- def attr_duplicatable(*attributes)
66
- self._duplicatable_attributes = attributes.map(&:to_sym) if attributes.present?
67
- self._duplicatable_attributes || []
68
- end
69
- end
70
- end
71
- end
@@ -1,49 +0,0 @@
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