deferred_associations 0.5.8 → 0.6.3
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/CHANGELOG +18 -0
- data/Readme.markdown +58 -27
- data/VERSION +1 -1
- data/bin/run_all_specs +25 -0
- data/deferred_associations.gemspec +3 -2
- data/lib/has_and_belongs_to_many_with_deferred_save.rb +3 -2
- data/lib/has_many_with_deferred_save.rb +8 -8
- data/spec/db/schema.rb +6 -0
- data/spec/models/room.rb +1 -3
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 36ea01ec9f183372ada7f082fcfedae522768719
|
4
|
+
data.tar.gz: dce7549d0c83be9d0c4e05bc17c939c769d445e9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: d215d8fbdde1bdd5c7011521e3bd86e7f48ae9f10177977f3e8ef1eec412db2ed3cb566e02fde7356a5b9407ad43dc88d1cdbe1e41f3cfe8971c4a9fc6809a15
|
7
|
+
data.tar.gz: 537f53870f1ab7baa2de4d06552971c9465c0cf376d4208b6528529ae02b3dfdfc7cd368cb54b2995c198613291f15fb8f61e1aaa57d8889b9115aa6f7ae87e8
|
data/CHANGELOG
CHANGED
@@ -1,3 +1,21 @@
|
|
1
|
+
0.6.3
|
2
|
+
=====
|
3
|
+
* Revert Changes form 0.6.1/0.6.2
|
4
|
+
- Keeping track of all array changes would be very clumsy, especially when dealling with :pop, :keep_if, :<< and so
|
5
|
+
on and so forth.
|
6
|
+
- The application has to deal with it for itself
|
7
|
+
|
8
|
+
0.6.2
|
9
|
+
=====
|
10
|
+
* Changes hash include the name of the association instead of their ids ("people" instead of "person_ids")
|
11
|
+
* Changes hash (and updated_at field) is only set, if the association is really changed
|
12
|
+
|
13
|
+
0.6.1
|
14
|
+
=====
|
15
|
+
* setting an association will now result in model.changed? to be true.
|
16
|
+
Also model.changes will include the old attribute key with the old value.
|
17
|
+
This allows the :autosave option on associated objects to work correctly.
|
18
|
+
|
1
19
|
0.5.8
|
2
20
|
=====
|
3
21
|
* fix preloading of HABTM associations in ActiveRecord >= 4.0
|
data/Readme.markdown
CHANGED
@@ -11,35 +11,42 @@ How to install
|
|
11
11
|
Usage
|
12
12
|
=====
|
13
13
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
if tables.size > 15
|
26
|
-
errors.add :tables, "There are too many tables in this room"
|
27
|
-
end
|
28
|
-
# Neither people nor tables are saved to the database, if a validation error is added
|
29
|
-
end
|
30
|
-
|
31
|
-
def check_change
|
32
|
-
# you can check, if there were changes to the association
|
33
|
-
if people != people_without_deferred_save
|
34
|
-
self.updated_at = Time.now.utc
|
35
|
-
end
|
36
|
-
end
|
14
|
+
```ruby
|
15
|
+
class Room < ActiveRecord::Base
|
16
|
+
has_and_belongs_to_many_with_deferred_save :people
|
17
|
+
has_many_with_deferred_save :tables
|
18
|
+
|
19
|
+
validate :usage
|
20
|
+
before_save :check_change
|
21
|
+
|
22
|
+
def usage
|
23
|
+
if people.size > 30
|
24
|
+
errors.add :people, "There are too many people in this room"
|
37
25
|
end
|
26
|
+
if tables.size > 15
|
27
|
+
errors.add :tables, "There are too many tables in this room"
|
28
|
+
end
|
29
|
+
# Neither people nor tables are saved to the database, if a validation error is added
|
30
|
+
end
|
31
|
+
|
32
|
+
def check_change
|
33
|
+
# you can check, if there were changes to the association
|
34
|
+
if people != people_without_deferred_save
|
35
|
+
self.update_some_relation_data(people)
|
36
|
+
end
|
37
|
+
|
38
|
+
# you can also use the rails-internal changes hash
|
39
|
+
if changes.include?("people")
|
40
|
+
self.do_stuff!
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
```
|
38
45
|
|
39
46
|
Compatibility
|
40
47
|
=============
|
41
48
|
|
42
|
-
Tested with Rails 2.3.18, 3.2.22, 4.1.14, 4.2.5 on Ruby 1.9.3, 2.2.4, 2.3.
|
49
|
+
Tested with Rails 2.3.18, 3.2.22, 4.1.14, 4.2.5 on Ruby 1.9.3, 2.2.4, 2.3.1 and JRuby 1.7, JRuby 9.1.0.0
|
43
50
|
|
44
51
|
Note, that Rails 3.2.14 associations are partly broken under JRuby cause of https://github.com/rails/rails/issues/11595
|
45
52
|
You'll need to upgrade activerecord-jdbc-adapter to >= 1.3.0.beta1, if you want to use this combination.
|
@@ -47,21 +54,45 @@ You'll need to upgrade activerecord-jdbc-adapter to >= 1.3.0.beta1, if you want
|
|
47
54
|
Gotchas
|
48
55
|
=======
|
49
56
|
|
50
|
-
Be aware, that the habtm association objects sometimes asks the database instead of giving you the data directly from the array. So you can get something
|
57
|
+
1. Be aware, that the habtm association objects sometimes asks the database instead of giving you the data directly from the array. So you can get something
|
51
58
|
like
|
52
59
|
|
60
|
+
```ruby
|
53
61
|
room = Room.create
|
54
62
|
room.people << Person.create
|
55
63
|
room.people.first # => nil, since the DB doesn't have the association saved yet
|
64
|
+
```
|
56
65
|
|
57
|
-
|
58
|
-
Also it is good to know, that the array you set to an association is stored there directly, so after setting a list, the typical association
|
66
|
+
2. Also it is good to know, that the array you set to an association is stored there directly, so after setting a list, the typical association
|
59
67
|
methods are not working:
|
60
68
|
|
69
|
+
```ruby
|
61
70
|
room = Room.create
|
62
71
|
room.people.klass # => Person
|
63
72
|
room.people = [Person.first]
|
64
73
|
room.people.klass # => undefined method klass for #Array:0x007fa3b9efc2c0`
|
74
|
+
```
|
75
|
+
|
76
|
+
3. If the association is changed, it's name is stored in the changes hash. Therefore, updated_at of the containing record will be set on the next update.
|
77
|
+
If an association is updated with the same array again, if will not be marked as changed. But if the order is changed, it will be marked!
|
78
|
+
|
79
|
+
```ruby
|
80
|
+
people = [Person.create, Person.create]
|
81
|
+
room = Room.create
|
82
|
+
room.people = [people.first, people.second]
|
83
|
+
room.changed? # => true
|
84
|
+
room.save!
|
85
|
+
|
86
|
+
room.people = [people.first, people.second]
|
87
|
+
room.changed? # => false
|
88
|
+
room.save!
|
89
|
+
room.updated_at # => is still the same as above
|
90
|
+
|
91
|
+
room.people = [people.second, people.first]
|
92
|
+
room.changed? # => true
|
93
|
+
room.save!
|
94
|
+
room.updated_at # => got touched!
|
95
|
+
```
|
65
96
|
|
66
97
|
Bugs
|
67
98
|
====
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.6.3
|
data/bin/run_all_specs
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
|
3
|
+
DIR=`pwd`
|
4
|
+
|
5
|
+
if [[ $DIR == *bin ]]; then
|
6
|
+
cd ..
|
7
|
+
fi
|
8
|
+
|
9
|
+
echo "Your ruby version: "
|
10
|
+
echo `ruby -v`
|
11
|
+
|
12
|
+
ls -c gemfiles/*.gemfile | while read line
|
13
|
+
do
|
14
|
+
|
15
|
+
echo "Run Spec for gemfile: $line"
|
16
|
+
export BUNDLE_GEMFILE=$line
|
17
|
+
bundle install
|
18
|
+
bundle exec rspec
|
19
|
+
echo ""
|
20
|
+
echo ""
|
21
|
+
echo ""
|
22
|
+
echo "========="
|
23
|
+
done
|
24
|
+
|
25
|
+
unset BUNDLE_GEMFILE
|
@@ -2,11 +2,11 @@
|
|
2
2
|
|
3
3
|
Gem::Specification.new do |s|
|
4
4
|
s.name = 'deferred_associations'
|
5
|
-
s.version = '0.
|
5
|
+
s.version = '0.6.3'
|
6
6
|
|
7
7
|
s.required_rubygems_version = Gem::Requirement.new('>= 0') if s.respond_to? :required_rubygems_version=
|
8
8
|
s.authors = ['Martin Koerner', 'Tyler Rick', 'Alessio Caiazza']
|
9
|
-
s.date = '2016-
|
9
|
+
s.date = '2016-05-13'
|
10
10
|
s.description = "Makes ActiveRecord defer/postpone saving the records you add to an habtm (has_and_belongs_to_many) or has_many\n association until you call model.save, allowing validation in the style of normal attributes. Additionally you\n can check inside before_save filters, if the association was altered."
|
11
11
|
s.email = 'martin.koerner@objectfab.de'
|
12
12
|
s.licenses = 'MIT'
|
@@ -20,6 +20,7 @@ Gem::Specification.new do |s|
|
|
20
20
|
'VERSION',
|
21
21
|
'deferred_associations.gemspec',
|
22
22
|
'init.rb',
|
23
|
+
'bin/run_all_specs',
|
23
24
|
'lib/array_to_association_wrapper.rb',
|
24
25
|
'lib/deferred_associations.rb',
|
25
26
|
'lib/has_and_belongs_to_many_with_deferred_save.rb',
|
@@ -79,10 +79,11 @@ module ActiveRecord
|
|
79
79
|
|
80
80
|
send "use_original_collection_reader_behavior_for_#{collection_name}=", true
|
81
81
|
send("initialize_unsaved_#{collection_name}") if send("unsaved_#{collection_name}").nil?
|
82
|
+
|
83
|
+
# vv This is where the actual save occurs vv
|
82
84
|
send "#{collection_name}_without_deferred_save=", send("unsaved_#{collection_name}")
|
83
|
-
# /\ This is where the actual save occurs.
|
84
|
-
send "use_original_collection_reader_behavior_for_#{collection_name}=", false
|
85
85
|
|
86
|
+
send "use_original_collection_reader_behavior_for_#{collection_name}=", false
|
86
87
|
true
|
87
88
|
end
|
88
89
|
after_save "do_#{collection_name}_save!"
|
@@ -3,6 +3,7 @@ module ActiveRecord
|
|
3
3
|
module ClassMethods
|
4
4
|
def has_many_with_deferred_save(*args)
|
5
5
|
collection_name = args[0].to_s
|
6
|
+
collection_singular_ids = "#{collection_name.singularize}_ids"
|
6
7
|
|
7
8
|
return if method_defined?("#{collection_name}_with_deferred_save")
|
8
9
|
|
@@ -14,18 +15,19 @@ module ActiveRecord
|
|
14
15
|
|
15
16
|
after_save "hmwds_update_#{collection_name}"
|
16
17
|
|
17
|
-
define_obj_setter collection_name
|
18
|
+
define_obj_setter collection_name, collection_singular_ids
|
18
19
|
define_obj_getter collection_name
|
19
|
-
define_id_setter collection_name
|
20
|
-
define_id_getter collection_name
|
20
|
+
define_id_setter collection_name, collection_singular_ids
|
21
|
+
define_id_getter collection_name, collection_singular_ids
|
21
22
|
|
22
23
|
define_update_method collection_name
|
23
24
|
define_reload_method collection_name
|
24
25
|
end
|
25
26
|
|
26
|
-
def define_obj_setter(collection_name)
|
27
|
+
def define_obj_setter(collection_name, collection_singular_ids)
|
27
28
|
define_method("#{collection_name}_with_deferred_save=") do |objs|
|
28
29
|
instance_variable_set "@hmwds_temp_#{collection_name}", objs || []
|
30
|
+
attribute_will_change!(collection_name) if objs != send("#{collection_name}_without_deferred_save")
|
29
31
|
end
|
30
32
|
|
31
33
|
method_name = "#{collection_name}="
|
@@ -56,10 +58,9 @@ module ActiveRecord
|
|
56
58
|
alias_method_chain collection_name, :deferred_save
|
57
59
|
end
|
58
60
|
|
59
|
-
def define_id_setter(collection_name)
|
61
|
+
def define_id_setter(collection_name, collection_singular_ids)
|
60
62
|
# only needed for ActiveRecord >= 3.0
|
61
63
|
if ActiveRecord::VERSION::STRING >= '3'
|
62
|
-
collection_singular_ids = "#{collection_name.singularize}_ids"
|
63
64
|
define_method "#{collection_singular_ids}_with_deferred_save=" do |ids|
|
64
65
|
ids = Array.wrap(ids).reject(&:blank?)
|
65
66
|
new_values = send("#{collection_name}_without_deferred_save").klass.find(ids)
|
@@ -69,8 +70,7 @@ module ActiveRecord
|
|
69
70
|
end
|
70
71
|
end
|
71
72
|
|
72
|
-
def define_id_getter(collection_name)
|
73
|
-
collection_singular_ids = "#{collection_name.singularize}_ids"
|
73
|
+
def define_id_getter(collection_name, collection_singular_ids)
|
74
74
|
define_method "#{collection_singular_ids}_with_deferred_save" do
|
75
75
|
send(collection_name).map { |e| e[:id] }
|
76
76
|
end
|
data/spec/db/schema.rb
CHANGED
@@ -15,6 +15,7 @@ ActiveRecord::Schema.define(version: 1) do
|
|
15
15
|
create_table 'rooms', force: true do |t|
|
16
16
|
t.column 'name', :string
|
17
17
|
t.column 'maximum_occupancy', :integer
|
18
|
+
t.column 'updated_at', :datetime
|
18
19
|
end
|
19
20
|
|
20
21
|
create_table 'doors_rooms', id: false, force: true do |t|
|
@@ -35,4 +36,9 @@ ActiveRecord::Schema.define(version: 1) do
|
|
35
36
|
t.column 'name', :string
|
36
37
|
t.column 'table_id', :integer
|
37
38
|
end
|
39
|
+
|
40
|
+
create_table 'windows', force: true do |t|
|
41
|
+
t.column 'name', :string
|
42
|
+
t.column 'room_id', :integer
|
43
|
+
end
|
38
44
|
end
|
data/spec/models/room.rb
CHANGED
@@ -13,15 +13,13 @@ class Room < ActiveRecord::Base
|
|
13
13
|
has_many_with_deferred_save :tables
|
14
14
|
has_many_with_deferred_save :chairs, through: :tables # TODO: test compatibility with through associations
|
15
15
|
|
16
|
-
has_and_belongs_to_many_with_deferred_save :doors
|
17
|
-
has_many_with_deferred_save :tables
|
18
16
|
|
19
17
|
before_save :diff_after_module
|
20
18
|
|
21
19
|
validate :people_count
|
22
20
|
|
23
21
|
def people_count
|
24
|
-
errors.add :people, 'This room has reached its maximum occupancy' if people.size > maximum_occupancy
|
22
|
+
errors.add :people, 'This room has reached its maximum occupancy' if maximum_occupancy && people.size > maximum_occupancy
|
25
23
|
end
|
26
24
|
|
27
25
|
# Just in case they try to bypass our new accessor and call people_without_deferred_save directly...
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: deferred_associations
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.6.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Martin Koerner
|
@@ -10,7 +10,7 @@ authors:
|
|
10
10
|
autorequire:
|
11
11
|
bindir: bin
|
12
12
|
cert_chain: []
|
13
|
-
date: 2016-
|
13
|
+
date: 2016-05-13 00:00:00.000000000 Z
|
14
14
|
dependencies:
|
15
15
|
- !ruby/object:Gem::Dependency
|
16
16
|
name: activerecord
|
@@ -54,6 +54,7 @@ files:
|
|
54
54
|
- CHANGELOG
|
55
55
|
- Readme.markdown
|
56
56
|
- VERSION
|
57
|
+
- bin/run_all_specs
|
57
58
|
- deferred_associations.gemspec
|
58
59
|
- init.rb
|
59
60
|
- lib/array_to_association_wrapper.rb
|