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 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