deferring 0.0.8 → 0.0.9
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 +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
|