rails_core_extensions 0.0.1 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +1 -0
- data/CHANGELOG.md +8 -0
- data/gemfiles/rails3.gemfile +0 -7
- data/gemfiles/rails4.gemfile +0 -8
- data/gemfiles/rails5.gemfile +6 -0
- data/lib/rails_core_extensions.rb +1 -0
- data/lib/rails_core_extensions/active_record_cloning.rb +27 -39
- data/lib/rails_core_extensions/active_record_extensions.rb +5 -39
- data/lib/rails_core_extensions/transfer_records.rb +21 -0
- data/lib/rails_core_extensions/version.rb +1 -1
- data/rails_core_extensions.gemspec +2 -2
- data/spec/action_controller_sortable_spec.rb +19 -12
- data/spec/active_record_cloning_spec.rb +91 -0
- data/spec/active_record_extensions_spec.rb +73 -61
- data/spec/breadcrumb_spec.rb +1 -0
- data/spec/position_initializer_spec.rb +7 -3
- data/spec/spec_helper.rb +2 -0
- data/spec/support/coverage_loader.rb +1 -1
- data/spec/transfer_records_spec.rb +36 -0
- metadata +9 -14
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 75e544c0a483d1b86ad8520255bb606a5f933aa1
|
4
|
+
data.tar.gz: 77c1fc668e12ea84ec69ede1991f5a339513b90f
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 3ffbf789ea526bf8a86705daa487a620a9ed3210f4a2d7f7ac6b2e19348dd3c4c23541f055b5e088f8e4b2d96e24e50e9ac31c9a6f6abcf899d6660dd0ddde66
|
7
|
+
data.tar.gz: 9c747e644c79d6ea9db7c427afd4b98fd44dccc7f75f937667f6437f545f055b326093561243596229c955f496921e7d5d93afd3c7e7aeb530e62a74c411b9e8
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
data/gemfiles/rails3.gemfile
CHANGED
@@ -2,12 +2,5 @@ source :rubygems
|
|
2
2
|
gemspec :path => '../'
|
3
3
|
|
4
4
|
group :development, :test do
|
5
|
-
gem 'rake', '~> 0.9.2'
|
6
|
-
gem 'rdoc', '~> 3.12'
|
7
|
-
gem 'rspec'
|
8
|
-
gem 'simplecov'
|
9
|
-
gem 'simplecov-rcov'
|
10
|
-
gem 'sqlite3'
|
11
|
-
gem 'activesupport', '~> 3.2.0'
|
12
5
|
gem 'activerecord', '~> 3.2.0'
|
13
6
|
end
|
data/gemfiles/rails4.gemfile
CHANGED
@@ -2,13 +2,5 @@ source :rubygems
|
|
2
2
|
gemspec :path => '../'
|
3
3
|
|
4
4
|
group :development, :test do
|
5
|
-
gem 'rake', '~> 0.9.2'
|
6
|
-
gem 'rdoc', '~> 3.12'
|
7
|
-
gem 'rspec'
|
8
|
-
gem 'simplecov'
|
9
|
-
gem 'simplecov-rcov'
|
10
|
-
gem 'sqlite3'
|
11
|
-
gem 'activesupport', '~> 4.0'
|
12
5
|
gem 'activerecord', '~> 4.0'
|
13
6
|
end
|
14
|
-
|
@@ -6,6 +6,7 @@ module RailsCoreExtensions
|
|
6
6
|
require 'rails_core_extensions/breadcrumb'
|
7
7
|
require 'rails_core_extensions/position_initializer'
|
8
8
|
require 'rails_core_extensions/time_with_zone'
|
9
|
+
require 'rails_core_extensions/transfer_records'
|
9
10
|
require 'rails_core_extensions/active_support_concern'
|
10
11
|
require 'rails_core_extensions/concurrency'
|
11
12
|
|
@@ -1,5 +1,4 @@
|
|
1
1
|
module ActiveRecordCloning
|
2
|
-
|
3
2
|
def self.included(base)
|
4
3
|
base.extend(ClassMethods)
|
5
4
|
end
|
@@ -27,6 +26,26 @@ module ActiveRecordCloning
|
|
27
26
|
cloned_attributes_hash[:exclude] = attributes.map(&:to_sym)
|
28
27
|
end
|
29
28
|
|
29
|
+
def clones_attributes_reset
|
30
|
+
@cloned_attributes = nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def exclude_attributes(cloned, excludes)
|
34
|
+
excluded_attributes(excludes).each do |attr|
|
35
|
+
cloned.send("#{attr}=", nil)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def excluded_attributes(excludes)
|
40
|
+
all_attributes = attribute_names.map(&:to_sym)
|
41
|
+
included_attributes = if attributes_included_in_cloning.empty?
|
42
|
+
all_attributes
|
43
|
+
else
|
44
|
+
all_attributes & attributes_included_in_cloning
|
45
|
+
end
|
46
|
+
all_attributes - included_attributes + attributes_excluded_from_cloning + excludes
|
47
|
+
end
|
48
|
+
|
30
49
|
protected
|
31
50
|
|
32
51
|
def cloned_attributes_hash
|
@@ -39,43 +58,12 @@ module ActiveRecordCloning
|
|
39
58
|
|
40
59
|
end
|
41
60
|
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
base_clone_attributes(reader_method, attributes).delete_if { |k,v| !allowed.include?(k.to_sym) }
|
50
|
-
end
|
51
|
-
}
|
52
|
-
end
|
53
|
-
|
54
|
-
def clone_excluding(excludes=[])
|
55
|
-
method = ActiveRecord::Base.instance_methods(false).include?(:clone) ? :clone : :dup
|
56
|
-
cloned = send(method)
|
57
|
-
|
58
|
-
excludes ||= []
|
59
|
-
excludes = [excludes] unless excludes.is_a?(Enumerable)
|
60
|
-
|
61
|
-
excludes.each do |excluded_attr|
|
62
|
-
attr_writer = (excluded_attr.to_s + '=').to_sym
|
63
|
-
cloned.send attr_writer, nil
|
64
|
-
end
|
65
|
-
|
66
|
-
cloned
|
67
|
-
end
|
68
|
-
|
69
|
-
private
|
70
|
-
|
71
|
-
def cloned_attributes
|
72
|
-
included_attributes = if self.class.attributes_included_in_cloning.empty?
|
73
|
-
attribute_names.map(&:to_sym)
|
74
|
-
else
|
75
|
-
attribute_names.map(&:to_sym) & self.class.attributes_included_in_cloning
|
76
|
-
end
|
77
|
-
included_attributes - self.class.attributes_excluded_from_cloning
|
78
|
-
end
|
61
|
+
def clone_excluding(excludes=[])
|
62
|
+
method = ActiveRecord::Base.instance_methods(false).include?(:clone) ? :clone : :dup
|
63
|
+
cloned = send(method)
|
64
|
+
excludes ||= []
|
65
|
+
excludes = [excludes] unless excludes.is_a?(Enumerable)
|
66
|
+
self.class.exclude_attributes(cloned, excludes)
|
67
|
+
cloned
|
79
68
|
end
|
80
|
-
|
81
69
|
end
|
@@ -2,7 +2,7 @@ module ActiveRecordExtensions
|
|
2
2
|
def self.included(base)
|
3
3
|
base.extend ClassMethods
|
4
4
|
end
|
5
|
-
|
5
|
+
|
6
6
|
module ClassMethods
|
7
7
|
# Like establish_connection but postfixes the key with the rails environment
|
8
8
|
# e.g. database('hello') in development will look for the database
|
@@ -41,15 +41,11 @@ module ActiveRecordExtensions
|
|
41
41
|
rec
|
42
42
|
end
|
43
43
|
end
|
44
|
-
|
45
|
-
def
|
44
|
+
|
45
|
+
def enum_int(field, values, options = {})
|
46
46
|
const_set("#{field.to_s.upcase}_OPTIONS", values)
|
47
|
-
|
48
|
-
select_options =
|
49
|
-
values.map.with_index{|v, i| [v.to_s.humanize, i]}
|
50
|
-
elsif values.is_a?(Hash)
|
51
|
-
values.values.map.with_index{|v, i| [v, i]}
|
52
|
-
end
|
47
|
+
|
48
|
+
select_options = values.map.with_index{|v, i| [v.to_s.humanize, i]}
|
53
49
|
const_set("#{field.to_s.upcase}_SELECT_OPTIONS", select_options)
|
54
50
|
|
55
51
|
values.each.with_index do |value, i|
|
@@ -90,7 +86,6 @@ module ActiveRecordExtensions
|
|
90
86
|
end
|
91
87
|
end
|
92
88
|
|
93
|
-
|
94
89
|
def position_helpers_for(*collections)
|
95
90
|
collections.each do |collection|
|
96
91
|
class_eval <<-EVAL
|
@@ -114,7 +109,6 @@ module ActiveRecordExtensions
|
|
114
109
|
end
|
115
110
|
end
|
116
111
|
|
117
|
-
|
118
112
|
# Validates presence of -- but works on parent within accepts_nested_attributes
|
119
113
|
#
|
120
114
|
def validates_presence_of_parent(foreign_key)
|
@@ -126,7 +120,6 @@ module ActiveRecordExtensions
|
|
126
120
|
end
|
127
121
|
end
|
128
122
|
|
129
|
-
|
130
123
|
# Run a block, being respectful of connection pools
|
131
124
|
#
|
132
125
|
# Useful for when you're not in the standard rails request process,
|
@@ -150,27 +143,20 @@ module ActiveRecordExtensions
|
|
150
143
|
# and also returns connections to the pool cached by threads that are no
|
151
144
|
# longer alive.
|
152
145
|
ActiveRecord::Base.clear_active_connections!
|
153
|
-
|
154
146
|
end
|
155
147
|
|
156
|
-
|
157
148
|
def translate(key, options = {})
|
158
149
|
klass = self
|
159
150
|
klass = klass.superclass while klass.superclass != ActiveRecord::Base
|
160
151
|
I18n.translate key, options.merge(:scope => klass.name.tableize.singularize)
|
161
152
|
end
|
162
153
|
|
163
|
-
|
164
154
|
def t(key, options = {})
|
165
155
|
self.translate(key, options)
|
166
156
|
end
|
167
|
-
|
168
157
|
end
|
169
158
|
|
170
|
-
|
171
159
|
module InstanceMethods
|
172
|
-
|
173
|
-
|
174
160
|
def all_errors
|
175
161
|
errors_hash = {}
|
176
162
|
self.errors.each do |attr, msg|
|
@@ -183,46 +169,26 @@ module ActiveRecordExtensions
|
|
183
169
|
errors_hash
|
184
170
|
end
|
185
171
|
|
186
|
-
|
187
172
|
def to_drop
|
188
173
|
@drop_class ||= (self.class.name+'Drop').constantize
|
189
174
|
@drop_class.new(self)
|
190
175
|
end
|
191
176
|
alias_method :to_liquid, :to_drop
|
192
177
|
|
193
|
-
|
194
178
|
# A unique id - even if you are unsaved!
|
195
179
|
def unique_id
|
196
180
|
id || @generated_dom_id || (@generated_dom_id = Time.now.to_f.to_s.gsub('.', '_'))
|
197
181
|
end
|
198
182
|
|
199
|
-
|
200
183
|
#getting audits
|
201
184
|
def audit_log
|
202
185
|
return (self.methods.include?('audits') ? self.audits : [])
|
203
186
|
end
|
204
187
|
|
205
|
-
|
206
|
-
|
207
188
|
private
|
208
189
|
|
209
190
|
def t(key, options = {})
|
210
191
|
self.class.translate(key, options)
|
211
192
|
end
|
212
|
-
|
213
|
-
|
214
|
-
def transfer_records(klass, objects, options = {})
|
215
|
-
record_ids = objects.flat_map { |o|
|
216
|
-
o.send(klass.name.underscore + '_ids')
|
217
|
-
}
|
218
|
-
unless record_ids.empty?
|
219
|
-
options[:foreign_key] ||= self.class.name.underscore + '_id'
|
220
|
-
update_options = options.except(:foreign_key)
|
221
|
-
update_options[options[:foreign_key]] = id
|
222
|
-
klass.where(id: record_ids).update_all(update_options)
|
223
|
-
end
|
224
|
-
end
|
225
|
-
|
226
193
|
end
|
227
|
-
|
228
194
|
end
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module RailsCoreExtensions
|
2
|
+
class TransferRecords
|
3
|
+
def initialize(parent, klass, options = {})
|
4
|
+
@parent = parent
|
5
|
+
@klass = klass
|
6
|
+
@options = options
|
7
|
+
end
|
8
|
+
|
9
|
+
def transfer_from(objects)
|
10
|
+
record_ids = objects.flat_map { |o|
|
11
|
+
o.send(@klass.name.underscore + '_ids')
|
12
|
+
}
|
13
|
+
unless record_ids.empty?
|
14
|
+
@options[:foreign_key] ||= @parent.class.name.underscore + '_id'
|
15
|
+
update_options = @options.except(:foreign_key)
|
16
|
+
update_options[@options[:foreign_key]] = @parent.id
|
17
|
+
@klass.where(id: record_ids).update_all(update_options)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
@@ -19,8 +19,8 @@ Gem::Specification.new do |spec|
|
|
19
19
|
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
20
20
|
spec.require_paths = ['lib']
|
21
21
|
|
22
|
-
spec.add_dependency 'activerecord', ['>= 2.3.0'
|
23
|
-
spec.add_dependency 'actionpack', ['>= 2.3.0'
|
22
|
+
spec.add_dependency 'activerecord', ['>= 2.3.0']
|
23
|
+
spec.add_dependency 'actionpack', ['>= 2.3.0']
|
24
24
|
|
25
25
|
spec.add_development_dependency 'bundler', '~> 1.3'
|
26
26
|
spec.add_development_dependency 'rake'
|
@@ -2,24 +2,31 @@ require 'spec_helper'
|
|
2
2
|
|
3
3
|
require 'rails_core_extensions/sortable'
|
4
4
|
|
5
|
-
connect_to_sqlite
|
6
|
-
|
7
5
|
describe RailsCoreExtensions::Sortable do
|
8
|
-
|
9
|
-
|
6
|
+
let(:model_class) {
|
7
|
+
Class.new(ActiveRecord::Base) do
|
10
8
|
default_scope -> { order(:name) }
|
11
9
|
end
|
12
|
-
|
13
|
-
|
14
|
-
|
10
|
+
}
|
11
|
+
|
12
|
+
before do
|
13
|
+
connect_to_sqlite
|
14
|
+
|
15
|
+
stub_const 'Model', model_class
|
16
|
+
|
17
|
+
models
|
15
18
|
end
|
16
19
|
|
20
|
+
let(:one) { Model.create!(name: 'One', position: 1, category_id: 1) }
|
21
|
+
let(:two) { Model.create!(name: 'Two', position: 2, category_id: 1) }
|
22
|
+
let(:thr) { Model.create!(name: 'Thr', position: 3, category_id: 2) }
|
23
|
+
let(:models) { [one, two, thr] }
|
24
|
+
|
17
25
|
after do
|
18
|
-
|
19
|
-
Object.send(:remove_const, 'Model')
|
26
|
+
models.each(&:destroy)
|
20
27
|
end
|
21
28
|
|
22
|
-
let(:params) { { model_body: [
|
29
|
+
let(:params) { { model_body: [one.id, thr.id, two.id] } }
|
23
30
|
subject { RailsCoreExtensions::Sortable.new(params, 'models') }
|
24
31
|
|
25
32
|
describe 'when unscoped' do
|
@@ -35,14 +42,14 @@ describe RailsCoreExtensions::Sortable do
|
|
35
42
|
let(:scope) { Model.where(category_id: 1).reorder(:position) }
|
36
43
|
specify { expect(scope.pluck(:name)).to eq %w(One Two) }
|
37
44
|
|
38
|
-
let(:params) { { category_id: 1, scope: :category_id, model_1_body: [
|
45
|
+
let(:params) { { category_id: 1, scope: :category_id, model_1_body: [two.id, one.id] } }
|
39
46
|
it 'should correctly sort' do
|
40
47
|
subject.sort
|
41
48
|
expect(scope.pluck(:name)).to eq %w(Two One)
|
42
49
|
end
|
43
50
|
|
44
51
|
describe 'when params scoped differently' do
|
45
|
-
let(:params) { { category_id: 1, scope: :category_id, category_1_body: [
|
52
|
+
let(:params) { { category_id: 1, scope: :category_id, category_1_body: [two.id, one.id] } }
|
46
53
|
it 'should correctly sort' do
|
47
54
|
subject.sort
|
48
55
|
expect(scope.pluck(:name)).to eq %w(Two One)
|
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ActiveRecordCloning do
|
4
|
+
let(:attrs) {
|
5
|
+
{
|
6
|
+
name: 'Bill',
|
7
|
+
age: '50',
|
8
|
+
position: 6,
|
9
|
+
category_id: 1
|
10
|
+
}
|
11
|
+
}
|
12
|
+
let(:record) { model_class.create!(attrs) }
|
13
|
+
let(:model_class) { Class.new(ActiveRecord::Base) { self.table_name = 'models' } }
|
14
|
+
|
15
|
+
before do
|
16
|
+
connect_to_sqlite
|
17
|
+
ActiveRecord::Base.send :include, ActiveRecordCloning
|
18
|
+
stub_const 'Model', model_class
|
19
|
+
Model.clones_attributes_reset
|
20
|
+
end
|
21
|
+
|
22
|
+
after do
|
23
|
+
Model.delete_all
|
24
|
+
end
|
25
|
+
|
26
|
+
context 'cloned attributes should clone everything' do
|
27
|
+
subject(:clone) { record.clone }
|
28
|
+
specify { expect(subject.name).to eq 'Bill' }
|
29
|
+
specify { expect(subject.age).to eq '50' }
|
30
|
+
specify { expect(subject.position).to eq 6 }
|
31
|
+
specify { expect(subject.category_id).to eq 1 }
|
32
|
+
end
|
33
|
+
|
34
|
+
context 'when model is standard' do
|
35
|
+
context 'clone excluding should exclude' do
|
36
|
+
subject(:clone_excluding) { record.clone_excluding(:category_id) }
|
37
|
+
specify { expect(subject.name).to eq 'Bill' }
|
38
|
+
specify { expect(subject.age).to eq '50' }
|
39
|
+
specify { expect(subject.position).to eq 6 }
|
40
|
+
specify { expect(subject.category_id).to be nil }
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
context 'when model excludes attributes by default' do
|
45
|
+
before do
|
46
|
+
model_class.class_eval do
|
47
|
+
clones_attributes_except :category_id
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context 'clone excluding should exclude' do
|
52
|
+
subject(:clone_excluding) { record.clone_excluding }
|
53
|
+
specify { expect(subject.name).to eq 'Bill' }
|
54
|
+
specify { expect(subject.age).to eq '50' }
|
55
|
+
specify { expect(subject.position).to eq 6 }
|
56
|
+
specify { expect(subject.category_id).to be nil }
|
57
|
+
end
|
58
|
+
|
59
|
+
context 'clone excluding should exclude additional arguments' do
|
60
|
+
subject(:clone_excluding) { record.clone_excluding(:position) }
|
61
|
+
specify { expect(subject.name).to eq 'Bill' }
|
62
|
+
specify { expect(subject.age).to eq '50' }
|
63
|
+
specify { expect(subject.position).to eq nil }
|
64
|
+
specify { expect(subject.category_id).to be nil }
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
context 'when model includes attributes by default' do
|
69
|
+
before do
|
70
|
+
model_class.class_eval do
|
71
|
+
clones_attributes :name, :age
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
context 'clone excluding should exclude' do
|
76
|
+
subject(:clone_excluding) { record.clone_excluding }
|
77
|
+
specify { expect(subject.name).to eq 'Bill' }
|
78
|
+
specify { expect(subject.age).to eq '50' }
|
79
|
+
specify { expect(subject.position).to eq nil }
|
80
|
+
specify { expect(subject.category_id).to be nil }
|
81
|
+
end
|
82
|
+
|
83
|
+
context 'clone excluding should exclude additional arguments' do
|
84
|
+
subject(:clone_excluding) { record.clone_excluding(:age) }
|
85
|
+
specify { expect(subject.name).to eq 'Bill' }
|
86
|
+
specify { expect(subject.age).to eq nil }
|
87
|
+
specify { expect(subject.position).to eq nil }
|
88
|
+
specify { expect(subject.category_id).to be nil }
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,14 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
connect_to_sqlite
|
4
|
-
|
5
3
|
describe "optional_fields" do
|
6
|
-
|
7
|
-
|
4
|
+
let(:model_class) {
|
5
|
+
Class.new(ActiveRecord::Base) do
|
8
6
|
optional_fields :name, :age, -> { [:age] }
|
9
7
|
end
|
8
|
+
}
|
9
|
+
|
10
|
+
before do
|
11
|
+
stub_const 'Model', model_class
|
10
12
|
end
|
11
|
-
after { Object.send(:remove_const, 'Model') }
|
12
13
|
|
13
14
|
it 'should know what fields are optional' do
|
14
15
|
expect(Model).to be_age_enabled
|
@@ -21,13 +22,56 @@ describe "optional_fields" do
|
|
21
22
|
end
|
22
23
|
end
|
23
24
|
|
24
|
-
describe
|
25
|
-
|
26
|
-
|
27
|
-
|
25
|
+
describe 'enum_int' do
|
26
|
+
let(:model_class) {
|
27
|
+
Class.new(ActiveRecord::Base) do
|
28
|
+
enum_int :category_id, %w(one two thr)
|
29
|
+
end
|
30
|
+
}
|
28
31
|
before do
|
29
|
-
|
32
|
+
connect_to_sqlite
|
33
|
+
stub_const 'Model', model_class
|
34
|
+
end
|
35
|
+
let(:one) { Model.new(category_id: 'one') }
|
36
|
+
|
37
|
+
it 'should define constants' do
|
38
|
+
expect(Model::CATEGORY_ID_OPTIONS).to eq %w(one two thr)
|
39
|
+
expect(Model::CATEGORY_ID_ONE).to eq 0
|
40
|
+
expect(Model::CATEGORY_ID_TWO).to eq 1
|
41
|
+
expect(Model::CATEGORY_ID_THR).to eq 2
|
42
|
+
end
|
43
|
+
|
44
|
+
it 'should define methods' do
|
45
|
+
expect(one.category_id_one?).to be true
|
46
|
+
expect(one.category_id_two?).to be false
|
47
|
+
expect(one.category_id_thr?).to be false
|
48
|
+
end
|
49
|
+
|
50
|
+
it 'should define select options' do
|
51
|
+
expect(Model::CATEGORY_ID_SELECT_OPTIONS).to eq([
|
52
|
+
['One', 0], ['Two', 1], ['Thr', 2]
|
53
|
+
])
|
54
|
+
end
|
55
|
+
|
56
|
+
context 'when short name' do
|
57
|
+
let(:model_class) {
|
58
|
+
Class.new(ActiveRecord::Base) do
|
59
|
+
enum_int :category_id, %w(one two thr), short_name: true
|
60
|
+
end
|
61
|
+
}
|
62
|
+
|
63
|
+
it 'should define methods' do
|
64
|
+
expect(one.one?).to be true
|
65
|
+
expect(one.two?).to be false
|
66
|
+
expect(one.thr?).to be false
|
67
|
+
end
|
30
68
|
end
|
69
|
+
end
|
70
|
+
|
71
|
+
describe "ActiveRecord::Base" do
|
72
|
+
let(:mock_model) { double }
|
73
|
+
let(:model_class) { Class.new(ActiveRecord::Base) }
|
74
|
+
before { stub_const 'Model', model_class }
|
31
75
|
|
32
76
|
it "should create a new record if new_or_update! is passed a hash without an :id" do
|
33
77
|
attributes = {:fake_column => 'nothing really'}
|
@@ -37,11 +81,10 @@ describe "ActiveRecord::Base" do
|
|
37
81
|
|
38
82
|
it "should update record if new_or_update! is passed hash with :id" do
|
39
83
|
attributes = {:fake_column => 'nothing really', :id => 1}
|
40
|
-
expect(Model).to receive(:find) {
|
41
|
-
expect(
|
84
|
+
expect(Model).to receive(:find) { mock_model }
|
85
|
+
expect(mock_model).to receive(:update_attributes!)
|
42
86
|
Model.new_or_update!(attributes)
|
43
87
|
end
|
44
|
-
|
45
88
|
end
|
46
89
|
|
47
90
|
describe RailsCoreExtensions::ActionControllerSortable do
|
@@ -60,67 +103,36 @@ describe RailsCoreExtensions::ActionControllerSortable do
|
|
60
103
|
end
|
61
104
|
|
62
105
|
describe ActiveRecordExtensions do
|
63
|
-
|
64
|
-
|
65
|
-
def transfer_children_from(old_parent)
|
66
|
-
transfer_records(Child, [old_parent])
|
67
|
-
end
|
68
|
-
end
|
69
|
-
class Child < ActiveRecord::Base
|
70
|
-
belongs_to :parent
|
71
|
-
end
|
72
|
-
|
73
|
-
let(:old) { Parent.create! }
|
74
|
-
let(:new) { Parent.create! }
|
75
|
-
|
76
|
-
before do
|
77
|
-
new.children.create!
|
78
|
-
old.children.create!
|
79
|
-
end
|
80
|
-
|
81
|
-
after do
|
82
|
-
Parent.delete_all
|
83
|
-
Child.delete_all
|
84
|
-
end
|
85
|
-
|
86
|
-
it 'should transfer records' do
|
87
|
-
expect(new.children.size).to eq 1
|
88
|
-
expect(old.children.size).to eq 1
|
89
|
-
new.transfer_children_from(old)
|
90
|
-
expect(new.reload.children.size).to eq 2
|
91
|
-
expect(old.reload.children.size).to eq 0
|
92
|
-
end
|
93
|
-
end
|
94
|
-
|
95
|
-
describe ActiveRecordExtensions do
|
96
|
-
before(:all) do
|
97
|
-
Model = Class.new(ActiveRecord::Base) do
|
106
|
+
let(:model_class) {
|
107
|
+
Class.new(ActiveRecord::Base) do
|
98
108
|
cache_all_attributes :by => 'name'
|
99
109
|
end
|
100
|
-
|
101
|
-
|
110
|
+
}
|
111
|
+
let(:first) { Model.create!(:name => 'First') }
|
112
|
+
let(:second) { Model.create!(:name => 'Second') }
|
113
|
+
let(:expected) {
|
114
|
+
{
|
115
|
+
'First' => first.attributes,
|
116
|
+
'Second' => second.attributes
|
117
|
+
}
|
118
|
+
}
|
102
119
|
|
103
120
|
before do
|
121
|
+
connect_to_sqlite
|
122
|
+
stub_const 'Model', model_class
|
104
123
|
allow(Model).to receive(:cache) { ActiveSupport::Cache::MemoryStore.new }
|
105
124
|
allow(Model).to receive(:should_cache?) { true }
|
106
|
-
|
107
|
-
|
108
|
-
after do
|
109
|
-
Model.delete_all
|
125
|
+
[first, second]
|
110
126
|
end
|
111
127
|
|
112
128
|
it 'should cache all attributes' do
|
113
|
-
@first = Model.create!(:name => 'First')
|
114
|
-
@second = Model.create!(:name => 'Second')
|
115
|
-
|
116
|
-
expected = {'First' => @first.attributes, 'Second' => @second.attributes}
|
117
|
-
|
118
129
|
# Test underlying generate attributes hash method works
|
119
130
|
expect(Model.generate_attributes_hash).to eq expected
|
120
131
|
expect(Model.attribute_cache).to eq expected
|
121
132
|
|
122
133
|
# Test after save/destroy it updates
|
123
|
-
|
124
|
-
expect(Model.attribute_cache).to eq 'Second' =>
|
134
|
+
first.destroy
|
135
|
+
expect(Model.attribute_cache).to eq 'Second' => second.attributes
|
136
|
+
second.destroy # Clean up after
|
125
137
|
end
|
126
138
|
end
|
data/spec/breadcrumb_spec.rb
CHANGED
@@ -1,16 +1,15 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
connect_to_sqlite
|
4
|
-
|
5
3
|
describe RailsCoreExtensions::PositionInitializer, 'When repositioning' do
|
6
4
|
class Child < ActiveRecord::Base; end
|
7
5
|
|
8
6
|
before do
|
7
|
+
connect_to_sqlite
|
9
8
|
Child.create!(parent_id: 1, name: 'A child')
|
10
9
|
end
|
11
10
|
|
12
11
|
after do
|
13
|
-
|
12
|
+
child.destroy
|
14
13
|
end
|
15
14
|
|
16
15
|
subject { RailsCoreExtensions::PositionInitializer.new(Child, :parent_id) }
|
@@ -34,6 +33,11 @@ describe RailsCoreExtensions::PositionInitializer, 'When repositioning' do
|
|
34
33
|
Child.create!(parent_id: 1, name: 'Third child')
|
35
34
|
end
|
36
35
|
|
36
|
+
after do
|
37
|
+
child2.destroy
|
38
|
+
child3.destroy
|
39
|
+
end
|
40
|
+
|
37
41
|
context 'when re-positioned' do
|
38
42
|
before { subject.positionalize }
|
39
43
|
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,36 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe RailsCoreExtensions::TransferRecords do
|
4
|
+
class Parent < ActiveRecord::Base
|
5
|
+
has_many :children, dependent: :destroy
|
6
|
+
def transfer_children_from(old_parent)
|
7
|
+
RailsCoreExtensions::TransferRecords.new(self, Child).transfer_from([old_parent])
|
8
|
+
end
|
9
|
+
end
|
10
|
+
class Child < ActiveRecord::Base
|
11
|
+
belongs_to :parent
|
12
|
+
end
|
13
|
+
|
14
|
+
let(:old) { Parent.create! }
|
15
|
+
let(:new) { Parent.create! }
|
16
|
+
|
17
|
+
before do
|
18
|
+
connect_to_sqlite
|
19
|
+
new.children.create!
|
20
|
+
old.children.create!
|
21
|
+
end
|
22
|
+
|
23
|
+
after do
|
24
|
+
old.destroy
|
25
|
+
new.destroy
|
26
|
+
end
|
27
|
+
|
28
|
+
it 'should transfer records' do
|
29
|
+
expect(new.children.size).to eq 1
|
30
|
+
expect(old.children.size).to eq 1
|
31
|
+
new.transfer_children_from(old)
|
32
|
+
expect(new.reload.children.size).to eq 2
|
33
|
+
expect(old.reload.children.size).to eq 0
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails_core_extensions
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0
|
4
|
+
version: 0.1.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Michael Noack
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2016-
|
12
|
+
date: 2016-07-28 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: activerecord
|
@@ -18,9 +18,6 @@ dependencies:
|
|
18
18
|
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: 2.3.0
|
21
|
-
- - "<"
|
22
|
-
- !ruby/object:Gem::Version
|
23
|
-
version: 5.0.0
|
24
21
|
type: :runtime
|
25
22
|
prerelease: false
|
26
23
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -28,9 +25,6 @@ dependencies:
|
|
28
25
|
- - ">="
|
29
26
|
- !ruby/object:Gem::Version
|
30
27
|
version: 2.3.0
|
31
|
-
- - "<"
|
32
|
-
- !ruby/object:Gem::Version
|
33
|
-
version: 5.0.0
|
34
28
|
- !ruby/object:Gem::Dependency
|
35
29
|
name: actionpack
|
36
30
|
requirement: !ruby/object:Gem::Requirement
|
@@ -38,9 +32,6 @@ dependencies:
|
|
38
32
|
- - ">="
|
39
33
|
- !ruby/object:Gem::Version
|
40
34
|
version: 2.3.0
|
41
|
-
- - "<"
|
42
|
-
- !ruby/object:Gem::Version
|
43
|
-
version: 5.0.0
|
44
35
|
type: :runtime
|
45
36
|
prerelease: false
|
46
37
|
version_requirements: !ruby/object:Gem::Requirement
|
@@ -48,9 +39,6 @@ dependencies:
|
|
48
39
|
- - ">="
|
49
40
|
- !ruby/object:Gem::Version
|
50
41
|
version: 2.3.0
|
51
|
-
- - "<"
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 5.0.0
|
54
42
|
- !ruby/object:Gem::Dependency
|
55
43
|
name: bundler
|
56
44
|
requirement: !ruby/object:Gem::Requirement
|
@@ -217,12 +205,14 @@ files:
|
|
217
205
|
- ".rspec"
|
218
206
|
- ".ruby-style.yml"
|
219
207
|
- ".travis.yml"
|
208
|
+
- CHANGELOG.md
|
220
209
|
- Gemfile
|
221
210
|
- LICENSE.txt
|
222
211
|
- README.md
|
223
212
|
- Rakefile
|
224
213
|
- gemfiles/rails3.gemfile
|
225
214
|
- gemfiles/rails4.gemfile
|
215
|
+
- gemfiles/rails5.gemfile
|
226
216
|
- lib/rails_core_extensions.rb
|
227
217
|
- lib/rails_core_extensions/action_controller_sortable.rb
|
228
218
|
- lib/rails_core_extensions/action_view_currency_extensions.rb
|
@@ -243,11 +233,13 @@ files:
|
|
243
233
|
- lib/rails_core_extensions/sortable.rb
|
244
234
|
- lib/rails_core_extensions/tasks/position_initializer.rake
|
245
235
|
- lib/rails_core_extensions/time_with_zone.rb
|
236
|
+
- lib/rails_core_extensions/transfer_records.rb
|
246
237
|
- lib/rails_core_extensions/version.rb
|
247
238
|
- rails_core_extensions.gemspec
|
248
239
|
- spec/action_controller_sortable_spec.rb
|
249
240
|
- spec/action_view_extensions_spec.rb
|
250
241
|
- spec/active_model_extensions_spec.rb
|
242
|
+
- spec/active_record_cloning_spec.rb
|
251
243
|
- spec/active_record_extensions_spec.rb
|
252
244
|
- spec/breadcrumb_spec.rb
|
253
245
|
- spec/concurrency_spec.rb
|
@@ -256,6 +248,7 @@ files:
|
|
256
248
|
- spec/spec_helper.rb
|
257
249
|
- spec/spec_helper_model_base.rb
|
258
250
|
- spec/support/coverage_loader.rb
|
251
|
+
- spec/transfer_records_spec.rb
|
259
252
|
homepage: http://github.com/sealink/rails_core_extensions
|
260
253
|
licenses:
|
261
254
|
- MIT
|
@@ -284,6 +277,7 @@ test_files:
|
|
284
277
|
- spec/action_controller_sortable_spec.rb
|
285
278
|
- spec/action_view_extensions_spec.rb
|
286
279
|
- spec/active_model_extensions_spec.rb
|
280
|
+
- spec/active_record_cloning_spec.rb
|
287
281
|
- spec/active_record_extensions_spec.rb
|
288
282
|
- spec/breadcrumb_spec.rb
|
289
283
|
- spec/concurrency_spec.rb
|
@@ -292,3 +286,4 @@ test_files:
|
|
292
286
|
- spec/spec_helper.rb
|
293
287
|
- spec/spec_helper_model_base.rb
|
294
288
|
- spec/support/coverage_loader.rb
|
289
|
+
- spec/transfer_records_spec.rb
|