mongoid_alize 0.1.0 → 0.2.0
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.
- 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
|