deferring 0.0.8 → 0.0.9
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +8 -8
- data/gemfiles/rails_30.gemfile.lock +1 -1
- data/gemfiles/rails_32.gemfile.lock +1 -1
- data/gemfiles/rails_40.gemfile.lock +1 -1
- data/gemfiles/rails_41.gemfile.lock +1 -1
- data/lib/deferring.rb +68 -27
- data/lib/deferring/version.rb +1 -1
- data/spec/lib/deferring_has_many_spec.rb +15 -0
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
---
|
2
2
|
!binary "U0hBMQ==":
|
3
3
|
metadata.gz: !binary |-
|
4
|
-
|
4
|
+
ZDI2ZGZlZTRiMjIzMmE3NGUxYjE5N2Y1NThiNDA2ZWJmYzc4NGRhMQ==
|
5
5
|
data.tar.gz: !binary |-
|
6
|
-
|
6
|
+
MWE1NDE1MTI2YTY0OGI5YzQyMTk3NDg1NjczNGNhMDE5YThhMWE2ZQ==
|
7
7
|
SHA512:
|
8
8
|
metadata.gz: !binary |-
|
9
|
-
|
10
|
-
|
11
|
-
|
9
|
+
ZjYzZmRmNGY2YmNmMDM3YjZmM2ViZDliYWZhN2IyOThiNDIxYjE0ZDhkZmI2
|
10
|
+
ZGY5ZWJiYjhiMjMxZDM4ZjlhNmM3N2Y0NWI2NWQ2Zjc1ZmEwMjA2M2E1YmI5
|
11
|
+
MWUwMmNkMmI4YzQxNGNhNTJmNzk3MDNlOTlkYzAwYTM2M2QxOGU=
|
12
12
|
data.tar.gz: !binary |-
|
13
|
-
|
14
|
-
|
15
|
-
|
13
|
+
MGVjYzM2MjA3NDFkYjU2NjA0ZDU0Yzk2ZWYzMmVjYzdhNTA0MTYwZTcwZWNj
|
14
|
+
YTY5MmJiNmQ1M2U2MGI4MDk1M2I4YTU3ZmE1NGU0MGI2NWZlMWU4MGFiMzI3
|
15
|
+
Yzc3MWFlZDVmZjIzODVkZDU3YTY5MWM4NjNlNGMyMTc1NGYyNzQ=
|
data/lib/deferring.rb
CHANGED
@@ -34,44 +34,85 @@ module Deferring
|
|
34
34
|
def deferred_accepts_nested_attributes_for(*args)
|
35
35
|
options = args.extract_options!
|
36
36
|
inverse_association_name = options.fetch(:as, self.name.underscore.to_sym)
|
37
|
-
|
37
|
+
reject_if = options.delete(:reject_if)
|
38
38
|
accepts_nested_attributes_for(*args, options)
|
39
39
|
|
40
40
|
association_name = args.first.to_s
|
41
41
|
|
42
42
|
# teams_attributes=
|
43
|
-
define_method :"#{association_name}_attributes=" do |
|
43
|
+
define_method :"#{association_name}_attributes=" do |attributes_collection|
|
44
44
|
find_or_create_deferred_association(association_name, [], inverse_association_name)
|
45
45
|
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
# Example:
|
50
|
-
# {
|
51
|
-
# first: { name: 'Service Desk' },
|
52
|
-
# second: { name: 'DBA' }
|
53
|
-
# }
|
54
|
-
# becomes
|
55
|
-
# [
|
56
|
-
# { name: 'Service Desk' },
|
57
|
-
# { name: 'DBA'}
|
58
|
-
# ]
|
59
|
-
attributes = attributes.values if attributes.is_a? Hash
|
60
|
-
|
61
|
-
# Remove the attributes that are to be destroyed from the ids that are to
|
62
|
-
# be assigned to the DeferredAssociation instance.
|
63
|
-
attributes.reject! { |record| record.delete(:_destroy) == '1' }
|
64
|
-
|
65
|
-
# Remove the attributes that fail the pass :reject_if proc.
|
66
|
-
attributes.reject! { |record| reject_if_proc.call(record) } if reject_if_proc
|
46
|
+
unless attributes_collection.is_a?(Hash) || attributes_collection.is_a?(Array)
|
47
|
+
raise ArgumentError, "Hash or Array expected, got #{attributes_collection.class.name} (#{attributes_collection.inspect})"
|
48
|
+
end
|
67
49
|
|
68
|
-
|
50
|
+
# TODO: Implement :limit checks. Check rails source.
|
69
51
|
|
70
|
-
|
71
|
-
|
52
|
+
if attributes_collection.is_a? Hash
|
53
|
+
keys = attributes_collection.keys
|
54
|
+
attributes_collection = if keys.include?('id') || keys.include?(:id)
|
55
|
+
[attributes_collection]
|
56
|
+
else
|
57
|
+
attributes_collection.values
|
58
|
+
end
|
72
59
|
end
|
73
60
|
|
74
|
-
|
61
|
+
attributes_collection.each do |attributes|
|
62
|
+
attributes = attributes.with_indifferent_access
|
63
|
+
|
64
|
+
if attributes['id'].blank?
|
65
|
+
if !reject_new_record?(attributes)
|
66
|
+
send(:"#{association_name}").build(attributes.except(*unassignable_keys))
|
67
|
+
end
|
68
|
+
|
69
|
+
elsif existing_record = send(:"#{association_name}").detect { |record| record.id.to_s == attributes['id'].to_s }
|
70
|
+
if !call_reject_if(attributes)
|
71
|
+
|
72
|
+
existing_record.attributes = attributes.except(*unassignable_keys)
|
73
|
+
|
74
|
+
# TODO: Implement value_to_boolean code from rails for checking _destroy field.
|
75
|
+
if attributes['_destroy'] == '1' && options[:allow_destroy]
|
76
|
+
# remove from existing records
|
77
|
+
send(:"#{association_name}").delete(existing_record)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
81
|
+
else # new record referenced by id
|
82
|
+
if !call_reject_if(attributes)
|
83
|
+
klass = self.class.reflect_on_association(:"#{association_name}").klass
|
84
|
+
|
85
|
+
attribute_ids = attributes_collection.map { |a| a['id'] || a[:id] }.compact
|
86
|
+
# TODO: Find out how to get send(:"#{association_name}").scoped.where working
|
87
|
+
new_records = attribute_ids.empty? ? [] : klass.where(klass.primary_key => attribute_ids)
|
88
|
+
new_record = new_records.detect { |record| record.id.to_s == attributes['id'].to_s }
|
89
|
+
|
90
|
+
send(:"#{association_name}").push(new_record)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
# Determines if a new record should be build by checking for
|
97
|
+
# has_destroy_flag? or if a <tt>:reject_if</tt> proc exists for this
|
98
|
+
# association and evaluates to +true+.
|
99
|
+
define_method :reject_new_record? do |attributes|
|
100
|
+
# TODO: Implement value_to_boolean code from rails for checking _destroy field.
|
101
|
+
attributes['_destroy'] == '1' || call_reject_if(attributes)
|
102
|
+
end
|
103
|
+
|
104
|
+
define_method :call_reject_if do |attributes|
|
105
|
+
return false if attributes['_destroy'] == '1'
|
106
|
+
case callback = reject_if
|
107
|
+
when Symbol
|
108
|
+
method(callback).arity == 0 ? send(callback) : send(callback, attributes)
|
109
|
+
when Proc
|
110
|
+
callback.call(attributes)
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
define_method :unassignable_keys do
|
115
|
+
%w(_destroy)
|
75
116
|
end
|
76
117
|
|
77
118
|
generate_find_or_create_deferred_association_method
|
data/lib/deferring/version.rb
CHANGED
@@ -122,6 +122,21 @@ RSpec.describe 'deferred has_many associations' do
|
|
122
122
|
expect{ p.save! }.to change{ Person.first.issues.size }.from(3).to(2)
|
123
123
|
end
|
124
124
|
|
125
|
+
it 'updates associated records' do
|
126
|
+
p = Person.first
|
127
|
+
p.issues << printer_issue << db_issue << sandwich_issue
|
128
|
+
p.save
|
129
|
+
|
130
|
+
# Update printer issue.
|
131
|
+
p = Person.first
|
132
|
+
p.attributes = {
|
133
|
+
issues_attributes: [{ id: printer_issue.id, subject: 'Toner low!' }]
|
134
|
+
}
|
135
|
+
p.save!
|
136
|
+
|
137
|
+
expect(Issue.find(printer_issue.id).subject).to eq 'Toner low!'
|
138
|
+
end
|
139
|
+
|
125
140
|
it 'sets associated records when posting a hash of hashes' do
|
126
141
|
p = Person.first
|
127
142
|
p.attributes = {
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deferring
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.9
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Robin Roestenburg
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-09-
|
11
|
+
date: 2014-09-08 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: activerecord
|