deferred_associations 0.5.8 → 0.6.3
Sign up to get free protection for your applications and to get access to all the features.
- 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
|