mongoid_alize 0.1.0 → 0.2.0
Sign up to get free protection for your applications and to get access to all the features.
- data/config/locales/en.yml +10 -0
- data/lib/mongoid/alize/callback.rb +47 -3
- data/lib/mongoid/alize/callbacks/from/many.rb +6 -8
- data/lib/mongoid/alize/callbacks/from/one.rb +21 -9
- data/lib/mongoid/alize/callbacks/to/many_from_many.rb +2 -1
- data/lib/mongoid/alize/callbacks/to/many_from_one.rb +1 -1
- data/lib/mongoid/alize/callbacks/to/one_from_many.rb +1 -1
- data/lib/mongoid/alize/callbacks/to/one_from_one.rb +1 -1
- data/lib/mongoid/alize/errors/alize_error.rb +13 -0
- data/lib/mongoid/alize/errors/already_defined_field.rb +15 -0
- data/lib/mongoid/alize/errors/invalid_field.rb +15 -0
- data/lib/mongoid/alize/from_callback.rb +16 -3
- data/lib/mongoid/alize/to_callback.rb +29 -5
- data/lib/mongoid/alize/to_many_callback.rb +26 -21
- data/lib/mongoid/alize/to_one_callback.rb +2 -3
- data/lib/mongoid_alize.rb +6 -1
- data/spec/app/models/head.rb +4 -0
- data/spec/app/models/person.rb +3 -0
- data/spec/mongoid/alize/callback_spec.rb +46 -8
- data/spec/mongoid/alize/callbacks/from/many_spec.rb +92 -18
- data/spec/mongoid/alize/callbacks/from/one_spec.rb +106 -23
- data/spec/mongoid/alize/callbacks/to/many_from_many_spec.rb +9 -16
- data/spec/mongoid/alize/callbacks/to/many_from_one_spec.rb +8 -15
- data/spec/mongoid/alize/callbacks/to/one_from_many_spec.rb +14 -17
- data/spec/mongoid/alize/callbacks/to/one_from_one_spec.rb +12 -15
- data/spec/mongoid/alize/from_callback_spec.rb +44 -0
- data/spec/mongoid/alize/to_callback_spec.rb +74 -0
- data/spec/mongoid_alize_spec.rb +152 -16
- data/spec/spec_helper.rb +6 -0
- metadata +27 -21
@@ -6,6 +6,7 @@ module Mongoid
|
|
6
6
|
|
7
7
|
attr_accessor :klass
|
8
8
|
attr_accessor :relation
|
9
|
+
attr_accessor :reflect
|
9
10
|
|
10
11
|
attr_accessor :inverse_klass
|
11
12
|
attr_accessor :inverse_relation
|
@@ -15,9 +16,12 @@ module Mongoid
|
|
15
16
|
self.relation = _relation
|
16
17
|
self.fields = _fields
|
17
18
|
|
18
|
-
reflect = _klass.relations[_relation.to_s]
|
19
|
-
self.inverse_klass = reflect.klass
|
20
|
-
self.inverse_relation = reflect.inverse
|
19
|
+
self.reflect = _klass.relations[_relation.to_s]
|
20
|
+
self.inverse_klass = self.reflect.klass
|
21
|
+
self.inverse_relation = self.reflect.inverse
|
22
|
+
|
23
|
+
self.klass.send(:attr_accessor, :force_denormalization)
|
24
|
+
self.inverse_klass.send(:attr_accessor, :force_denormalization)
|
21
25
|
end
|
22
26
|
|
23
27
|
def attach
|
@@ -26,9 +30,49 @@ module Mongoid
|
|
26
30
|
|
27
31
|
protected
|
28
32
|
|
33
|
+
def callback_attached?(callback_type, callback_name)
|
34
|
+
!!klass.send(:"_#{callback_type}_callbacks").
|
35
|
+
map(&:raw_filter).include?(callback_name)
|
36
|
+
end
|
37
|
+
|
38
|
+
def callback_defined?(callback_name)
|
39
|
+
klass.method_defined?(callback_name)
|
40
|
+
end
|
41
|
+
|
42
|
+
def alias_callback
|
43
|
+
unless callback_defined?(aliased_callback_name)
|
44
|
+
klass.send(:alias_method, aliased_callback_name, callback_name)
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def callback_name
|
49
|
+
"_#{aliased_callback_name}"
|
50
|
+
end
|
51
|
+
|
52
|
+
def aliased_callback_name
|
53
|
+
"denormalize_#{direction}_#{relation}"
|
54
|
+
end
|
55
|
+
|
29
56
|
def joined_fields
|
30
57
|
(fields + [:_id]).map {|f| "'#{f}'" }.join(", ")
|
31
58
|
end
|
59
|
+
|
60
|
+
def joined_field_values(source)
|
61
|
+
<<-RUBY
|
62
|
+
[#{joined_fields}].inject({}) { |hash, name|
|
63
|
+
hash[name] = #{source}.send(name)
|
64
|
+
hash
|
65
|
+
}
|
66
|
+
RUBY
|
67
|
+
end
|
68
|
+
|
69
|
+
def force_param
|
70
|
+
"(force=false)"
|
71
|
+
end
|
72
|
+
|
73
|
+
def force_check
|
74
|
+
"force || self.force_denormalization"
|
75
|
+
end
|
32
76
|
end
|
33
77
|
end
|
34
78
|
end
|
@@ -8,22 +8,20 @@ module Mongoid
|
|
8
8
|
|
9
9
|
def define_callback
|
10
10
|
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
11
|
-
def #{callback_name}
|
11
|
+
def #{callback_name}#{force_param}
|
12
12
|
self.#{prefixed_name} = self.#{relation}.map do |model|
|
13
|
-
|
13
|
+
#{joined_field_values("model")}
|
14
14
|
end
|
15
15
|
end
|
16
|
-
|
17
16
|
protected :#{callback_name}
|
18
17
|
CALLBACK
|
19
18
|
end
|
20
19
|
|
21
20
|
def define_fields
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
end
|
21
|
+
ensure_field_not_defined!(prefixed_name, klass)
|
22
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
23
|
+
field :#{prefixed_name}, :type => Array, :default => []
|
24
|
+
CALLBACK
|
27
25
|
end
|
28
26
|
|
29
27
|
def prefixed_name
|
@@ -9,13 +9,18 @@ module Mongoid
|
|
9
9
|
def define_callback
|
10
10
|
field_sets = ""
|
11
11
|
fields.each do |name|
|
12
|
-
field_sets << "self.
|
12
|
+
field_sets << "self.send(:#{prefixed_field_name(name)}=,
|
13
|
+
relation && relation.send(:#{name}))\n"
|
13
14
|
end
|
14
15
|
|
15
16
|
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
16
|
-
def #{callback_name}
|
17
|
-
|
18
|
-
|
17
|
+
def #{callback_name}#{force_param}
|
18
|
+
if #{force_check} ||
|
19
|
+
#{!reflect.stores_foreign_key?} ||
|
20
|
+
self.#{reflect.key}_changed?
|
21
|
+
relation = self.#{relation}
|
22
|
+
#{field_sets}
|
23
|
+
end
|
19
24
|
true
|
20
25
|
end
|
21
26
|
|
@@ -26,9 +31,11 @@ module Mongoid
|
|
26
31
|
def define_fields
|
27
32
|
fields.each do |name|
|
28
33
|
prefixed_name = prefixed_field_name(name)
|
29
|
-
|
30
|
-
|
31
|
-
|
34
|
+
unless field_defined?(prefixed_name, klass)
|
35
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
36
|
+
field :#{prefixed_name}, :type => #{inverse_field_type(name)}
|
37
|
+
CALLBACK
|
38
|
+
end
|
32
39
|
end
|
33
40
|
end
|
34
41
|
|
@@ -37,8 +44,13 @@ module Mongoid
|
|
37
44
|
end
|
38
45
|
|
39
46
|
def inverse_field_type(name)
|
40
|
-
|
41
|
-
|
47
|
+
name = name.to_s
|
48
|
+
|
49
|
+
name = "_id" if name == "id"
|
50
|
+
name = "_type" if name == "type"
|
51
|
+
|
52
|
+
field = inverse_klass.fields[name]
|
53
|
+
(field && field.options[:type]) ? field.type : String
|
42
54
|
end
|
43
55
|
end
|
44
56
|
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
module Errors
|
4
|
+
|
5
|
+
class InvalidField < AlizeError
|
6
|
+
def initialize(name, inverse_klass)
|
7
|
+
super(
|
8
|
+
translate("invalid_field", { :name => name, :inverse_klass => inverse_klass })
|
9
|
+
)
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -6,17 +6,30 @@ module Mongoid
|
|
6
6
|
define_fields
|
7
7
|
|
8
8
|
define_callback
|
9
|
+
alias_callback
|
9
10
|
set_callback
|
10
11
|
end
|
11
12
|
|
12
13
|
protected
|
13
14
|
|
14
15
|
def set_callback
|
15
|
-
|
16
|
+
unless callback_attached?("save", aliased_callback_name)
|
17
|
+
klass.set_callback(:save, :before, aliased_callback_name)
|
18
|
+
end
|
16
19
|
end
|
17
20
|
|
18
|
-
def
|
19
|
-
|
21
|
+
def ensure_field_not_defined!(prefixed_name, klass)
|
22
|
+
if field_defined?(prefixed_name, klass)
|
23
|
+
raise Mongoid::Alize::Errors::AlreadyDefinedField.new(prefixed_name, klass.name)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def field_defined?(prefixed_name, klass)
|
28
|
+
!!klass.fields[prefixed_name]
|
29
|
+
end
|
30
|
+
|
31
|
+
def direction
|
32
|
+
"from"
|
20
33
|
end
|
21
34
|
end
|
22
35
|
end
|
@@ -4,28 +4,52 @@ module Mongoid
|
|
4
4
|
|
5
5
|
def attach
|
6
6
|
define_callback
|
7
|
+
alias_callback
|
7
8
|
set_callback
|
8
9
|
|
9
10
|
define_destroy_callback
|
11
|
+
alias_destroy_callback
|
10
12
|
set_destroy_callback
|
11
13
|
end
|
12
14
|
|
13
15
|
protected
|
14
16
|
|
15
17
|
def set_callback
|
16
|
-
|
18
|
+
unless callback_attached?("save", aliased_callback_name)
|
19
|
+
klass.set_callback(:save, :after, aliased_callback_name)
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
def set_destroy_callback
|
20
|
-
|
24
|
+
unless callback_attached?("destroy", aliased_destroy_callback_name)
|
25
|
+
klass.set_callback(:destroy, :after, aliased_destroy_callback_name)
|
26
|
+
end
|
21
27
|
end
|
22
28
|
|
23
|
-
def
|
24
|
-
|
29
|
+
def alias_destroy_callback
|
30
|
+
unless callback_defined?(aliased_destroy_callback_name)
|
31
|
+
klass.send(:alias_method, aliased_destroy_callback_name, destroy_callback_name)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def aliased_destroy_callback_name
|
36
|
+
"denormalize_destroy_#{direction}_#{relation}"
|
25
37
|
end
|
26
38
|
|
27
39
|
def destroy_callback_name
|
28
|
-
"
|
40
|
+
"_#{aliased_destroy_callback_name}"
|
41
|
+
end
|
42
|
+
|
43
|
+
def plain_relation
|
44
|
+
"self.#{relation}"
|
45
|
+
end
|
46
|
+
|
47
|
+
def surrounded_relation
|
48
|
+
"self.#{relation} ? [self.#{relation}] : []"
|
49
|
+
end
|
50
|
+
|
51
|
+
def direction
|
52
|
+
"to"
|
29
53
|
end
|
30
54
|
end
|
31
55
|
end
|
@@ -4,36 +4,41 @@ module Mongoid
|
|
4
4
|
protected
|
5
5
|
|
6
6
|
def define_callback
|
7
|
-
|
8
|
-
|
7
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
8
|
+
def #{callback_name}#{force_param}
|
9
|
+
data = #{joined_field_values("self")}
|
10
|
+
(#{iterable_relation}).each do |inverse|
|
11
|
+
#{pull_from_inverse}
|
12
|
+
inverse.push(:#{prefixed_name}, data)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
protected :#{callback_name}
|
16
|
+
CALLBACK
|
9
17
|
end
|
10
18
|
|
11
19
|
def define_destroy_callback
|
12
|
-
_callback(destroy_callback_name)
|
13
|
-
end
|
14
|
-
|
15
|
-
def _callback(_callback_name, push_content="")
|
16
20
|
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
17
|
-
def #{
|
18
|
-
|
21
|
+
def #{destroy_callback_name}
|
19
22
|
(#{iterable_relation}).each do |inverse|
|
23
|
+
#{pull_from_inverse}
|
24
|
+
end
|
25
|
+
end
|
26
|
+
protected :#{destroy_callback_name}
|
27
|
+
CALLBACK
|
28
|
+
end
|
20
29
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
if inverse.#{prefixed_name}
|
27
|
-
inverse.#{prefixed_name}.reject! do |hash|
|
28
|
-
hash["_id"] == self.id
|
29
|
-
end
|
30
|
-
end
|
30
|
+
def pull_from_inverse
|
31
|
+
<<-CALLBACK
|
32
|
+
# this pull works in the DB, but not in memory
|
33
|
+
# ($pull w/ expression not currently supported by Mongoid)
|
34
|
+
inverse.pull(:#{prefixed_name}, { "_id" => self.id })
|
31
35
|
|
32
|
-
|
36
|
+
# manually do the pull in memory for now
|
37
|
+
if inverse.#{prefixed_name}
|
38
|
+
inverse.#{prefixed_name}.reject! do |hash|
|
39
|
+
hash["_id"] == self.id
|
33
40
|
end
|
34
41
|
end
|
35
|
-
|
36
|
-
protected :#{_callback_name}
|
37
42
|
CALLBACK
|
38
43
|
end
|
39
44
|
|
@@ -13,7 +13,7 @@ module Mongoid
|
|
13
13
|
|
14
14
|
def to_one_field_sets
|
15
15
|
fields.map { |field|
|
16
|
-
"relation.set(:#{prefixed_field_name(field)}, self.
|
16
|
+
"relation.set(:#{prefixed_field_name(field)}, self.send(:#{field}))"
|
17
17
|
}.join("\n")
|
18
18
|
end
|
19
19
|
|
@@ -25,13 +25,12 @@ module Mongoid
|
|
25
25
|
|
26
26
|
def _callback(_callback_name, field_sets)
|
27
27
|
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
28
|
-
def #{_callback_name}
|
28
|
+
def #{_callback_name}#{force_param}
|
29
29
|
(#{iterable_relation}).each do |relation|
|
30
30
|
#{field_sets}
|
31
31
|
end
|
32
32
|
true
|
33
33
|
end
|
34
|
-
|
35
34
|
protected :#{_callback_name}
|
36
35
|
CALLBACK
|
37
36
|
end
|
data/lib/mongoid_alize.rb
CHANGED
@@ -1,7 +1,10 @@
|
|
1
|
+
require 'mongoid/alize/errors/alize_error'
|
2
|
+
require 'mongoid/alize/errors/invalid_field'
|
3
|
+
require 'mongoid/alize/errors/already_defined_field'
|
4
|
+
|
1
5
|
require 'mongoid/alize/callback'
|
2
6
|
|
3
7
|
require 'mongoid/alize/from_callback.rb'
|
4
|
-
|
5
8
|
require 'mongoid/alize/to_callback.rb'
|
6
9
|
require 'mongoid/alize/to_one_callback.rb'
|
7
10
|
require 'mongoid/alize/to_many_callback.rb'
|
@@ -16,6 +19,8 @@ require 'mongoid/alize/callbacks/to/many_from_many.rb'
|
|
16
19
|
|
17
20
|
require 'mongoid/alize/macros'
|
18
21
|
|
22
|
+
I18n.load_path << File.join(File.dirname(__FILE__), "..", "config", "locales", "en.yml")
|
23
|
+
|
19
24
|
module Mongoid
|
20
25
|
module Alize
|
21
26
|
extend ActiveSupport::Concern
|