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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- ZmJiMDFiYWJiZWI2Y2UzNTU3NDk3ZmNiOWNhNmYwNzBhNmUwZDk1Yg==
4
+ ZDI2ZGZlZTRiMjIzMmE3NGUxYjE5N2Y1NThiNDA2ZWJmYzc4NGRhMQ==
5
5
  data.tar.gz: !binary |-
6
- Y2YwOWRmZjA1NzkwMzZiZGIwYzU0NDdjMWQ4MWFkZGRkODNhMjA1MQ==
6
+ MWE1NDE1MTI2YTY0OGI5YzQyMTk3NDg1NjczNGNhMDE5YThhMWE2ZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDg0NTNkMzkwYjc2ZjJhZjgxNzE1NGMyMjE2YTcwMzVjNWE1MDEzYjM2MzVk
10
- YTc3MDRjOGM4YjJmNTBhNGQ3YmMwYzQ5Njk1N2QxOWUxMTFhMmEzNWQwOGIw
11
- YzNlOGFmNjAwZjg3OWI1NWY0NWZiY2VkNTdmMTM4Mzc2ZmY0NzA=
9
+ ZjYzZmRmNGY2YmNmMDM3YjZmM2ViZDliYWZhN2IyOThiNDIxYjE0ZDhkZmI2
10
+ ZGY5ZWJiYjhiMjMxZDM4ZjlhNmM3N2Y0NWI2NWQ2Zjc1ZmEwMjA2M2E1YmI5
11
+ MWUwMmNkMmI4YzQxNGNhNTJmNzk3MDNlOTlkYzAwYTM2M2QxOGU=
12
12
  data.tar.gz: !binary |-
13
- N2RlNzQxOTBhYzk5NGQzN2Q0OWM1NjE4MDI4YmVmNjlkYmNhMTk0OGMwODk1
14
- N2UyNzhiZGIzYzllMDVkYjY4MzJlNjViZWVhZGZhZTQxNWQ3ZmI5NDhiMzIx
15
- MDBjZGFmYWE5YjZiOTAyMmYzOGM5NWZmMGRmZTZjOWIzNmU0NGM=
13
+ MGVjYzM2MjA3NDFkYjU2NjA0ZDU0Yzk2ZWYzMmVjYzdhNTA0MTYwZTcwZWNj
14
+ YTY5MmJiNmQ1M2U2MGI4MDk1M2I4YTU3ZmE1NGU0MGI2NWZlMWU4MGFiMzI3
15
+ Yzc3MWFlZDVmZjIzODVkZDU3YTY5MWM4NjNlNGMyMTc1NGYyNzQ=
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.7)
4
+ deferring (0.0.9)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.7)
4
+ deferring (0.0.9)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.7)
4
+ deferring (0.0.9)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: ../
3
3
  specs:
4
- deferring (0.0.7)
4
+ deferring (0.0.9)
5
5
  activerecord (> 3.0)
6
6
 
7
7
  GEM
@@ -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
- reject_if_proc = options.delete(:reject_if)
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 |attributes|
43
+ define_method :"#{association_name}_attributes=" do |attributes_collection|
44
44
  find_or_create_deferred_association(association_name, [], inverse_association_name)
45
45
 
46
- # Convert the attributes to an array if a Hash is passed. This is possible
47
- # as the keys of the hash are ignored in this case.
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
- klass = self.class.reflect_on_association(:"#{association_name}").klass
50
+ # TODO: Implement :limit checks. Check rails source.
69
51
 
70
- objects = attributes.map do |record|
71
- record[:id] ? klass.find(record[:id]) : klass.new(record)
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
- send(:"deferred_#{association_name}").objects = objects
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
@@ -1,5 +1,5 @@
1
1
  # encoding: UTF-8
2
2
 
3
3
  module Deferring
4
- VERSION = '0.0.8'
4
+ VERSION = '0.0.9'
5
5
  end
@@ -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.8
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-02 00:00:00.000000000 Z
11
+ date: 2014-09-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activerecord