mongoid_alize 0.1.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/lib/mongoid/alize/callback.rb +34 -0
- data/lib/mongoid/alize/callbacks/from/many.rb +36 -0
- data/lib/mongoid/alize/callbacks/from/one.rb +47 -0
- data/lib/mongoid/alize/callbacks/to/many_from_many.rb +15 -0
- data/lib/mongoid/alize/callbacks/to/many_from_one.rb +15 -0
- data/lib/mongoid/alize/callbacks/to/one_from_many.rb +15 -0
- data/lib/mongoid/alize/callbacks/to/one_from_one.rb +15 -0
- data/lib/mongoid/alize/from_callback.rb +23 -0
- data/lib/mongoid/alize/macros.rb +68 -0
- data/lib/mongoid/alize/to_callback.rb +32 -0
- data/lib/mongoid/alize/to_many_callback.rb +45 -0
- data/lib/mongoid/alize/to_one_callback.rb +44 -0
- data/lib/mongoid_alize.rb +27 -0
- data/spec/app/models/head.rb +22 -0
- data/spec/app/models/person.rb +21 -0
- data/spec/helpers/macros_helper.rb +45 -0
- data/spec/mongoid/alize/callback_spec.rb +27 -0
- data/spec/mongoid/alize/callbacks/from/many_spec.rb +53 -0
- data/spec/mongoid/alize/callbacks/from/one_spec.rb +60 -0
- data/spec/mongoid/alize/callbacks/to/many_from_many_spec.rb +97 -0
- data/spec/mongoid/alize/callbacks/to/many_from_one_spec.rb +106 -0
- data/spec/mongoid/alize/callbacks/to/one_from_many_spec.rb +73 -0
- data/spec/mongoid/alize/callbacks/to/one_from_one_spec.rb +82 -0
- data/spec/mongoid/alize/macros_spec.rb +65 -0
- data/spec/mongoid_alize_spec.rb +166 -0
- data/spec/spec_helper.rb +38 -0
- metadata +102 -0
@@ -0,0 +1,34 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
class Callback
|
4
|
+
|
5
|
+
attr_accessor :fields
|
6
|
+
|
7
|
+
attr_accessor :klass
|
8
|
+
attr_accessor :relation
|
9
|
+
|
10
|
+
attr_accessor :inverse_klass
|
11
|
+
attr_accessor :inverse_relation
|
12
|
+
|
13
|
+
def initialize(_klass, _relation, _fields)
|
14
|
+
self.klass = _klass
|
15
|
+
self.relation = _relation
|
16
|
+
self.fields = _fields
|
17
|
+
|
18
|
+
reflect = _klass.relations[_relation.to_s]
|
19
|
+
self.inverse_klass = reflect.klass
|
20
|
+
self.inverse_relation = reflect.inverse
|
21
|
+
end
|
22
|
+
|
23
|
+
def attach
|
24
|
+
# implement in subclasses
|
25
|
+
end
|
26
|
+
|
27
|
+
protected
|
28
|
+
|
29
|
+
def joined_fields
|
30
|
+
(fields + [:_id]).map {|f| "'#{f}'" }.join(", ")
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
module Callbacks
|
4
|
+
module From
|
5
|
+
class Many < FromCallback
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def define_callback
|
10
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
11
|
+
def #{callback_name}
|
12
|
+
self.#{prefixed_name} = self.#{relation}.map do |model|
|
13
|
+
model.attributes.slice(#{joined_fields})
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
protected :#{callback_name}
|
18
|
+
CALLBACK
|
19
|
+
end
|
20
|
+
|
21
|
+
def define_fields
|
22
|
+
unless !!klass.fields[prefixed_name]
|
23
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
24
|
+
field :#{prefixed_name}, :type => Array
|
25
|
+
CALLBACK
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def prefixed_name
|
30
|
+
"#{relation}_fields"
|
31
|
+
end
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,47 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
module Callbacks
|
4
|
+
module From
|
5
|
+
class One < FromCallback
|
6
|
+
|
7
|
+
protected
|
8
|
+
|
9
|
+
def define_callback
|
10
|
+
field_sets = ""
|
11
|
+
fields.each do |name|
|
12
|
+
field_sets << "self.set(:#{prefixed_field_name(name)}, relation && relation.read_attribute(:#{name}))\n"
|
13
|
+
end
|
14
|
+
|
15
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
16
|
+
def #{callback_name}
|
17
|
+
relation = self.#{relation}
|
18
|
+
#{field_sets}
|
19
|
+
true
|
20
|
+
end
|
21
|
+
|
22
|
+
protected :#{callback_name}
|
23
|
+
CALLBACK
|
24
|
+
end
|
25
|
+
|
26
|
+
def define_fields
|
27
|
+
fields.each do |name|
|
28
|
+
prefixed_name = prefixed_field_name(name)
|
29
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
30
|
+
field :#{prefixed_name}, :type => #{inverse_field_type(name)}
|
31
|
+
CALLBACK
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def prefixed_field_name(name)
|
36
|
+
"#{relation}_#{name}"
|
37
|
+
end
|
38
|
+
|
39
|
+
def inverse_field_type(name)
|
40
|
+
field = inverse_klass.fields[name.to_s]
|
41
|
+
field.options[:type] ? field.type : String
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
class FromCallback < Callback
|
4
|
+
|
5
|
+
def attach
|
6
|
+
define_fields
|
7
|
+
|
8
|
+
define_callback
|
9
|
+
set_callback
|
10
|
+
end
|
11
|
+
|
12
|
+
protected
|
13
|
+
|
14
|
+
def set_callback
|
15
|
+
klass.set_callback(:create, :before, callback_name)
|
16
|
+
end
|
17
|
+
|
18
|
+
def callback_name
|
19
|
+
"denormalize_from_#{relation}"
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
module Macros
|
4
|
+
|
5
|
+
def alize(relation, *fields)
|
6
|
+
|
7
|
+
fields = default_alize_fields(relation) if fields.empty?
|
8
|
+
|
9
|
+
one = Mongoid::Relations::One
|
10
|
+
many = Mongoid::Relations::Many
|
11
|
+
|
12
|
+
def (many = many.dup).==(klass)
|
13
|
+
[Mongoid::Relations::Many,
|
14
|
+
Mongoid::Relations::Referenced::Many].map(&:name).include?(klass.name)
|
15
|
+
end
|
16
|
+
|
17
|
+
klass = self
|
18
|
+
reflect = klass.relations[relation.to_s]
|
19
|
+
|
20
|
+
from_one = Mongoid::Alize::Callbacks::From::One
|
21
|
+
from_many = Mongoid::Alize::Callbacks::From::Many
|
22
|
+
|
23
|
+
relation_superclass = reflect.relation.superclass
|
24
|
+
callback_klass =
|
25
|
+
case [relation_superclass]
|
26
|
+
when [one] then from_one
|
27
|
+
when [many] then from_many
|
28
|
+
end
|
29
|
+
|
30
|
+
callback_klass.
|
31
|
+
new(klass, relation, fields).
|
32
|
+
attach
|
33
|
+
|
34
|
+
inverse_klass = reflect.klass
|
35
|
+
inverse_relation = reflect.inverse
|
36
|
+
|
37
|
+
if inverse_klass &&
|
38
|
+
(inverse_reflect = inverse_klass.relations[inverse_relation.to_s])
|
39
|
+
|
40
|
+
to_one_from_one = Mongoid::Alize::Callbacks::To::OneFromOne
|
41
|
+
to_one_from_many = Mongoid::Alize::Callbacks::To::OneFromMany
|
42
|
+
to_many_from_one = Mongoid::Alize::Callbacks::To::ManyFromOne
|
43
|
+
to_many_from_many = Mongoid::Alize::Callbacks::To::ManyFromMany
|
44
|
+
|
45
|
+
inverse_relation_superclass = inverse_reflect.relation.superclass
|
46
|
+
inverse_callback_klass =
|
47
|
+
case [relation_superclass, inverse_relation_superclass]
|
48
|
+
when [one, one] then to_one_from_one
|
49
|
+
when [many, one] then to_many_from_one
|
50
|
+
when [one, many] then to_one_from_many
|
51
|
+
when [many, many] then to_many_from_many
|
52
|
+
end
|
53
|
+
|
54
|
+
inverse_callback_klass.
|
55
|
+
new(inverse_klass, inverse_relation, fields).
|
56
|
+
attach
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def default_alize_fields(relation)
|
61
|
+
self.relations[relation.to_s].klass.
|
62
|
+
fields.reject { |name, field|
|
63
|
+
name =~ /^_/
|
64
|
+
}.keys
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
class ToCallback < Callback
|
4
|
+
|
5
|
+
def attach
|
6
|
+
define_callback
|
7
|
+
set_callback
|
8
|
+
|
9
|
+
define_destroy_callback
|
10
|
+
set_destroy_callback
|
11
|
+
end
|
12
|
+
|
13
|
+
protected
|
14
|
+
|
15
|
+
def set_callback
|
16
|
+
klass.set_callback(:save, :after, callback_name)
|
17
|
+
end
|
18
|
+
|
19
|
+
def set_destroy_callback
|
20
|
+
klass.set_callback(:destroy, :after, destroy_callback_name)
|
21
|
+
end
|
22
|
+
|
23
|
+
def callback_name
|
24
|
+
"denormalize_to_#{relation}"
|
25
|
+
end
|
26
|
+
|
27
|
+
def destroy_callback_name
|
28
|
+
"denormalize_destroy_to_#{relation}"
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
class ToManyCallback < ToCallback
|
4
|
+
protected
|
5
|
+
|
6
|
+
def define_callback
|
7
|
+
_callback(callback_name,
|
8
|
+
"inverse.push(:#{prefixed_name}, self.attributes.slice(#{joined_fields}))")
|
9
|
+
end
|
10
|
+
|
11
|
+
def define_destroy_callback
|
12
|
+
_callback(destroy_callback_name)
|
13
|
+
end
|
14
|
+
|
15
|
+
def _callback(_callback_name, push_content="")
|
16
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
17
|
+
def #{_callback_name}
|
18
|
+
|
19
|
+
(#{iterable_relation}).each do |inverse|
|
20
|
+
|
21
|
+
# this pull works in the DB, but not in memory
|
22
|
+
# ($pull w/ expression not currently supported by Mongoid)
|
23
|
+
inverse.pull(:#{prefixed_name}, { "_id" => self.id })
|
24
|
+
|
25
|
+
# manually do the pull in memory for now
|
26
|
+
if inverse.#{prefixed_name}
|
27
|
+
inverse.#{prefixed_name}.reject! do |hash|
|
28
|
+
hash["_id"] == self.id
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
#{push_content}
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
protected :#{_callback_name}
|
37
|
+
CALLBACK
|
38
|
+
end
|
39
|
+
|
40
|
+
def prefixed_name
|
41
|
+
"#{inverse_relation}_fields"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module Mongoid
|
2
|
+
module Alize
|
3
|
+
class ToOneCallback < ToCallback
|
4
|
+
protected
|
5
|
+
|
6
|
+
def define_callback
|
7
|
+
_callback(callback_name, to_one_field_sets)
|
8
|
+
end
|
9
|
+
|
10
|
+
def define_destroy_callback
|
11
|
+
_callback(destroy_callback_name, to_one_destroy_field_sets)
|
12
|
+
end
|
13
|
+
|
14
|
+
def to_one_field_sets
|
15
|
+
fields.map { |field|
|
16
|
+
"relation.set(:#{prefixed_field_name(field)}, self.read_attribute(:#{field}))"
|
17
|
+
}.join("\n")
|
18
|
+
end
|
19
|
+
|
20
|
+
def to_one_destroy_field_sets
|
21
|
+
fields.map { |field|
|
22
|
+
"relation.set(:#{prefixed_field_name(field)}, nil)"
|
23
|
+
}.join("\n")
|
24
|
+
end
|
25
|
+
|
26
|
+
def _callback(_callback_name, field_sets)
|
27
|
+
klass.class_eval <<-CALLBACK, __FILE__, __LINE__ + 1
|
28
|
+
def #{_callback_name}
|
29
|
+
(#{iterable_relation}).each do |relation|
|
30
|
+
#{field_sets}
|
31
|
+
end
|
32
|
+
true
|
33
|
+
end
|
34
|
+
|
35
|
+
protected :#{_callback_name}
|
36
|
+
CALLBACK
|
37
|
+
end
|
38
|
+
|
39
|
+
def prefixed_field_name(name)
|
40
|
+
"#{inverse_relation}_#{name}"
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'mongoid/alize/callback'
|
2
|
+
|
3
|
+
require 'mongoid/alize/from_callback.rb'
|
4
|
+
|
5
|
+
require 'mongoid/alize/to_callback.rb'
|
6
|
+
require 'mongoid/alize/to_one_callback.rb'
|
7
|
+
require 'mongoid/alize/to_many_callback.rb'
|
8
|
+
|
9
|
+
require 'mongoid/alize/callbacks/from/one.rb'
|
10
|
+
require 'mongoid/alize/callbacks/from/many.rb'
|
11
|
+
|
12
|
+
require 'mongoid/alize/callbacks/to/one_from_one.rb'
|
13
|
+
require 'mongoid/alize/callbacks/to/one_from_many.rb'
|
14
|
+
require 'mongoid/alize/callbacks/to/many_from_one.rb'
|
15
|
+
require 'mongoid/alize/callbacks/to/many_from_many.rb'
|
16
|
+
|
17
|
+
require 'mongoid/alize/macros'
|
18
|
+
|
19
|
+
module Mongoid
|
20
|
+
module Alize
|
21
|
+
extend ActiveSupport::Concern
|
22
|
+
|
23
|
+
included do
|
24
|
+
extend Mongoid::Alize::Macros
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
class Head
|
2
|
+
include Mongoid::Document
|
3
|
+
include Mongoid::Alize
|
4
|
+
|
5
|
+
field :size, type: Integer
|
6
|
+
field :weight
|
7
|
+
|
8
|
+
# to whom it's attached
|
9
|
+
belongs_to :person
|
10
|
+
|
11
|
+
# in who's possession it is
|
12
|
+
belongs_to :captor, :class_name => "Person", :inverse_of => :heads
|
13
|
+
|
14
|
+
# who'd otherwise like to possess it
|
15
|
+
has_and_belongs_to_many :wanted_by, :class_name => "Person", :inverse_of => :wants
|
16
|
+
|
17
|
+
# who it sees
|
18
|
+
has_many :sees, :class_name => "Person", :inverse_of => :seen_by
|
19
|
+
|
20
|
+
# a relation with no inverse
|
21
|
+
has_many :admirer, :class_name => "Person", :inverse_of => nil
|
22
|
+
end
|