rails_core_extensions 0.0.1 → 0.1.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.
- 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
|