selfish_associations 0.0.0 → 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.
- checksums.yaml +4 -4
- data/lib/selfish_associations/associations/association.rb +57 -33
- data/lib/selfish_associations/associations/has_many.rb +1 -1
- data/lib/selfish_associations/associations/has_one.rb +1 -3
- data/lib/selfish_associations/base.rb +2 -2
- data/lib/selfish_associations/builder.rb +3 -2
- data/lib/selfish_associations/scope_readers/instance.rb +38 -0
- data/lib/selfish_associations/scope_readers/relation.rb +61 -0
- data/lib/selfish_associations/{association_traverser.rb → utils/association_traverser.rb} +6 -2
- data/lib/selfish_associations/utils/nilifier.rb +24 -0
- data/lib/selfish_associations/{path_merger.rb → utils/path_merger.rb} +0 -0
- data/lib/selfish_associations.rb +12 -6
- metadata +7 -5
- data/lib/selfish_associations/scope_reader.rb +0 -55
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3bd7fff1c41265161aea2372a9fb041ce4ff77e0
|
|
4
|
+
data.tar.gz: 7af54ffb489231247f270348800a6e144418d847
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 93cdb13cfba94868478e470979fb9cbc4696771ae45344ead80bb9cb3f578039d61622dc833e96914fa86b5869bc2a0a3dfa8a79f012fca3623d8a8b6fcc8e35
|
|
7
|
+
data.tar.gz: 3a50a8ef46c954d305ddfce23a041b53b059b33103e7fc88f53c9fa80db0b0a24ca9f3633a9fe953c965678f3e1662f2f614211b0c5a0abf2b8963a7daab39aa
|
|
@@ -16,14 +16,8 @@ module SelfishAssociations
|
|
|
16
16
|
@scope = scope
|
|
17
17
|
@foreign_class_name = (options[:class_name] || name.to_s.classify).to_s
|
|
18
18
|
@foreign_key = options[:foreign_key] == false ? false : (options[:foreign_key] || @model.name.foreign_key).to_sym
|
|
19
|
-
|
|
19
|
+
@foreign_key_scope = @foreign_key.present? ? foreign_key_scope : nil
|
|
20
20
|
validate
|
|
21
|
-
|
|
22
|
-
@reader = SelfishAssociations::ScopeReader.new(@model)
|
|
23
|
-
# Can't use ivar inside Lambda
|
|
24
|
-
foreign_key = @foreign_key
|
|
25
|
-
add_scope(->(selph){ where foreign_key => selph.id }) if @foreign_key.present?
|
|
26
|
-
add_scope(@scope) if @scope.present?
|
|
27
21
|
end
|
|
28
22
|
|
|
29
23
|
def inspect
|
|
@@ -34,63 +28,93 @@ module SelfishAssociations
|
|
|
34
28
|
@foreign_class ||= self.class.const_get(@foreign_class_name)
|
|
35
29
|
end
|
|
36
30
|
|
|
37
|
-
def add_scope(scope)
|
|
38
|
-
@reader.read(scope)
|
|
39
|
-
end
|
|
40
|
-
|
|
41
31
|
def join
|
|
42
|
-
conditions = arelize_conditions(
|
|
32
|
+
conditions = arelize_conditions(relation_reader.conditions_for_find)
|
|
43
33
|
arel_join = @model.arel_table.join(foreign_class.arel_table).on(conditions).join_sources
|
|
44
34
|
@model.joins(joins_for_find).joins(arel_join).merge(foreign_class.all)
|
|
45
35
|
end
|
|
46
36
|
|
|
47
|
-
def
|
|
48
|
-
foreign_class.create(instance_create_attributes(instance))
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
def matches(instance)
|
|
37
|
+
def matches_for(instance)
|
|
52
38
|
foreign_class.where(instance_find_conditions(instance))
|
|
53
39
|
end
|
|
54
40
|
|
|
41
|
+
def create_for(instance)
|
|
42
|
+
foreign_class.create(instance_create_attributes(instance))
|
|
43
|
+
end
|
|
55
44
|
|
|
56
45
|
private
|
|
57
46
|
|
|
47
|
+
def apply_scopes(reader)
|
|
48
|
+
reader.read(@scope) if @scope.present?
|
|
49
|
+
reader.read(@foreign_key_scope) if @foreign_key.present?
|
|
50
|
+
return reader
|
|
51
|
+
end
|
|
52
|
+
|
|
58
53
|
def arelize_conditions(conditions)
|
|
59
54
|
conditions.map do |foreign_field, node|
|
|
60
55
|
foreign_class.arel_table[foreign_field].eq(node)
|
|
61
|
-
end.reduce
|
|
56
|
+
end.reduce(&:and)
|
|
62
57
|
end
|
|
63
58
|
|
|
64
59
|
def instance_find_conditions(instance)
|
|
65
|
-
|
|
60
|
+
read_instance_find_conditions(instance)
|
|
61
|
+
# TODO: dynamically determine if we should use lookup_instance_find_conditions instead
|
|
62
|
+
# cannot use if the scope constains non-associations
|
|
63
|
+
# should not use if all associations are preloaded on instance
|
|
64
|
+
# cannot use if instance contains unpersisted changes
|
|
66
65
|
end
|
|
67
66
|
|
|
68
|
-
def
|
|
69
|
-
|
|
67
|
+
def relation_reader
|
|
68
|
+
@relation_reader ||= apply_scopes(SelfishAssociations::ScopeReaders::Relation.new(@model))
|
|
70
69
|
end
|
|
71
70
|
|
|
72
|
-
def
|
|
73
|
-
|
|
71
|
+
def instance_reader(instance)
|
|
72
|
+
apply_scopes(ScopeReaders::Instance.new(instance))
|
|
74
73
|
end
|
|
75
74
|
|
|
76
|
-
def
|
|
77
|
-
|
|
75
|
+
def read_instance_find_conditions(instance)
|
|
76
|
+
instance_reader(instance).attributes_for_find
|
|
78
77
|
end
|
|
79
78
|
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
79
|
+
def read_instance_create_attributes(instance)
|
|
80
|
+
instance_reader(instance).attributes_for_create
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def lookup_instance_find_conditions(instance)
|
|
84
|
+
instantiate_conditions(instance, relation_reader.conditions_for_find)
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def lookup_instance_create_attributes(instance)
|
|
88
|
+
instantiate_conditions(instance, relation_reader.attributes_for_create)
|
|
89
|
+
end
|
|
90
|
+
|
|
91
|
+
def instantiate_conditions(instance, conditions)
|
|
84
92
|
arel_conditions, static_conditions = conditions.partition{|field, value| value.is_a?(::Arel::Attribute)}.map(&:to_h)
|
|
85
93
|
selector = arel_conditions.map{|field, arel| arel.as(field.to_s)}
|
|
86
|
-
|
|
87
|
-
arel_conditions.keys.each{|k| static_conditions[k] =
|
|
94
|
+
instance = @model.joins(joins_for_find).select(selector).find_by(id: instance.id)
|
|
95
|
+
arel_conditions.keys.each{|k| static_conditions[k] = instance[k]}
|
|
88
96
|
return static_conditions
|
|
89
97
|
end
|
|
90
98
|
|
|
99
|
+
def joins_for_find
|
|
100
|
+
relation_reader.joins_for_find
|
|
101
|
+
end
|
|
102
|
+
|
|
103
|
+
def joins_for_create
|
|
104
|
+
relation_reader.joins_for_create
|
|
105
|
+
end
|
|
106
|
+
|
|
107
|
+
def foreign_key_scope
|
|
108
|
+
# TODO: pass foreign_key in rather than using the closure
|
|
109
|
+
foreign_key = @foreign_key
|
|
110
|
+
return ->(obj){ where foreign_key => obj.id }
|
|
111
|
+
end
|
|
112
|
+
|
|
91
113
|
def validate
|
|
92
|
-
|
|
93
|
-
|
|
114
|
+
if @scope.present?
|
|
115
|
+
@scope.is_a?(Proc) or raise SelfishAssociations::SelfishException, "Scope must be a Proc"
|
|
116
|
+
@scope.arity == 0 || @scope.arity == 1 or raise SelfishAssociations::SelfishException, "Scope must have arity of 0 or 1"
|
|
117
|
+
end
|
|
94
118
|
@model.is_a?(Class) && @model < ActiveRecord::Base or raise SelfishAssociations::SelfishException, "Tried to define a SelfishAssociation for an invalid object (#{@model})"
|
|
95
119
|
end
|
|
96
120
|
end
|
|
@@ -2,9 +2,7 @@ module SelfishAssociations
|
|
|
2
2
|
module Associations
|
|
3
3
|
class HasOne < SelfishAssociations::Association
|
|
4
4
|
def find(instance)
|
|
5
|
-
|
|
6
|
-
# foreign_class.instance_exec(instance, @scope).first
|
|
7
|
-
foreign_class.find_by(instance_find_conditions(instance))
|
|
5
|
+
matches_for(instance).first
|
|
8
6
|
end
|
|
9
7
|
end
|
|
10
8
|
end
|
|
@@ -15,11 +15,11 @@ module SelfishAssociations
|
|
|
15
15
|
|
|
16
16
|
module ClassMethods
|
|
17
17
|
def has_one_selfish(name, scope = nil, **options)
|
|
18
|
-
SelfishAssociations::Builder.new(self).add_association(SelfishAssociations::
|
|
18
|
+
SelfishAssociations::Builder.new(self).add_association(name, SelfishAssociations::Associations::HasOne.new(name, self, scope, options))
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def has_many_selfish(name, scope = nil, **options)
|
|
22
|
-
SelfishAssociations::Builder.new(self).add_association(SelfishAssociations::
|
|
22
|
+
SelfishAssociations::Builder.new(self).add_association(name, SelfishAssociations::Associations::HasMany.new(name, self, scope, options))
|
|
23
23
|
end
|
|
24
24
|
|
|
25
25
|
def selfish_joins(name)
|
|
@@ -6,10 +6,11 @@ module SelfishAssociations
|
|
|
6
6
|
|
|
7
7
|
def initialize_methods_class
|
|
8
8
|
@model.const_set("SelfishAssociationMethods", Module.new) unless defined? @model::SelfishAssociationMethods
|
|
9
|
-
@model.include @model::SelfishAssociationMethods if
|
|
9
|
+
@model.include @model::SelfishAssociationMethods if !@model.ancestors.include?(@model::SelfishAssociationMethods)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
def add_association(assoc)
|
|
12
|
+
def add_association(name, assoc)
|
|
13
|
+
initialize_methods_class
|
|
13
14
|
@model.selfish_associations[name] = assoc
|
|
14
15
|
|
|
15
16
|
@model::SelfishAssociationMethods.class_eval do
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
module SelfishAssociations
|
|
2
|
+
module ScopeReaders
|
|
3
|
+
class Instance < BasicObject
|
|
4
|
+
attr_reader :attributes_for_find, :attributes_for_create
|
|
5
|
+
|
|
6
|
+
def initialize(instance)
|
|
7
|
+
@instance = Nilifier.new(instance)
|
|
8
|
+
@attributes_for_find = {}
|
|
9
|
+
@attributes_for_create = {}
|
|
10
|
+
end
|
|
11
|
+
|
|
12
|
+
def read(scope)
|
|
13
|
+
args = scope.arity == 0 ? [] : [@instance]
|
|
14
|
+
instance_exec(*args, &scope)
|
|
15
|
+
return self
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def where(conditions)
|
|
19
|
+
unnilify(conditions)
|
|
20
|
+
create_with(conditions)
|
|
21
|
+
@attributes_for_find.merge!(conditions)
|
|
22
|
+
return self
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def create_with(conditions)
|
|
26
|
+
unnilify(conditions)
|
|
27
|
+
@attributes_for_create.merge!(conditions)
|
|
28
|
+
return self
|
|
29
|
+
end
|
|
30
|
+
|
|
31
|
+
def unnilify(conditions)
|
|
32
|
+
conditions.keys.each do |key|
|
|
33
|
+
conditions[key] = conditions[key].unnilify if conditions[key].respond_to?(:unnilify?)
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
end
|
|
38
|
+
end
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# A scope reader is an object that response to scope methods such as `where` and
|
|
2
|
+
# `create_with`. It must return a ScopeReader for each of these methods so that
|
|
3
|
+
# these methods can be chained. For it to be useful, these methods must also have
|
|
4
|
+
# side effects that can be inspected by a third party.
|
|
5
|
+
#
|
|
6
|
+
# For SelfishAssociations, we generally want to support passing a single argument
|
|
7
|
+
# to the scope lambda. E.g. `->(record){ where field: record.matching_field }`. In
|
|
8
|
+
# order to collect useful information, we may want to pass a special object in place
|
|
9
|
+
# of `record`: one that can respond to the same methods that `record` could respond
|
|
10
|
+
# to, but in doing so collects information about each call that is being made. This
|
|
11
|
+
# is what we are using the `AssociationTraverser` for in `ScopeReaders::Relation`.
|
|
12
|
+
# This traverser can respond to relations and field names of the record model.
|
|
13
|
+
# Similarly, it returns a modified traverser in respons to this so that those calls
|
|
14
|
+
# may also be chained. For more, see association_traverser.rb.
|
|
15
|
+
|
|
16
|
+
module SelfishAssociations
|
|
17
|
+
module ScopeReaders
|
|
18
|
+
class Relation < BasicObject
|
|
19
|
+
attr_reader :conditions_for_find, :attributes_for_create
|
|
20
|
+
attr_reader :traverser
|
|
21
|
+
|
|
22
|
+
def initialize(klass)
|
|
23
|
+
@traverser = ::SelfishAssociations::AssociationTraverser.new(klass)
|
|
24
|
+
@conditions_for_find = {}
|
|
25
|
+
@joins_for_find = []
|
|
26
|
+
@attributes_for_create = {}
|
|
27
|
+
@joins_for_create = []
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def read(scope)
|
|
31
|
+
args = scope.arity == 0 ? [] : [@traverser]
|
|
32
|
+
instance_exec(*args, &scope)
|
|
33
|
+
return self
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
# TODO: implement argless where() and not()
|
|
37
|
+
def where(conditions)
|
|
38
|
+
create_with(conditions)
|
|
39
|
+
@conditions_for_find.merge!(conditions)
|
|
40
|
+
@joins_for_find += @traverser.associations!(merge: false)
|
|
41
|
+
@traverser.reset!
|
|
42
|
+
return self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def create_with(conditions)
|
|
46
|
+
@attributes_for_create.merge!(conditions)
|
|
47
|
+
@joins_for_create += @traverser.associations!(merge: false)
|
|
48
|
+
@traverser.reset!
|
|
49
|
+
return self
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def joins_for_find
|
|
53
|
+
::SelfishAssociations::PathMerger.new(@joins_for_find).merge
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def joins_for_create
|
|
57
|
+
::SelfishAssociations::PathMerger.new(@joins_for_create).merge
|
|
58
|
+
end
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
@@ -9,8 +9,8 @@
|
|
|
9
9
|
# t.bar.baz.id
|
|
10
10
|
# # => Arel::Attribute(table: "bazs", field: "id")
|
|
11
11
|
#
|
|
12
|
-
# As a Traverser gets iterated accross
|
|
13
|
-
# it has seen. You can then call :associations! to fetch these
|
|
12
|
+
# As a Traverser gets iterated accross associations, it collects every model that
|
|
13
|
+
# it has seen. You can then call :associations! to fetch these associations.
|
|
14
14
|
#
|
|
15
15
|
# e.g., continuing from above
|
|
16
16
|
# # t.associations!
|
|
@@ -71,6 +71,10 @@ module SelfishAssociations
|
|
|
71
71
|
@path << method
|
|
72
72
|
@klass = @klass.reflect_on_association(method).klass
|
|
73
73
|
return self
|
|
74
|
+
elsif @klass.selfish_associations[method].present?
|
|
75
|
+
@path << method
|
|
76
|
+
@klass = @klass.selfish_associations[method].foreign_class
|
|
77
|
+
return self
|
|
74
78
|
else
|
|
75
79
|
message = "No association or field named #{method} found for class #{@klass}"
|
|
76
80
|
reset!
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
module SelfishAssociations
|
|
2
|
+
class Nilifier < BasicObject
|
|
3
|
+
def initialize(object)
|
|
4
|
+
@object = object
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def inspect
|
|
8
|
+
@object.inspect + " (nil-safe)"
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
def unnilify
|
|
12
|
+
@object
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
def respond_to?(method)
|
|
16
|
+
true
|
|
17
|
+
end
|
|
18
|
+
|
|
19
|
+
def method_missing(method, *args)
|
|
20
|
+
result = @object.respond_to?(method) ? @object.public_send(method, *args) : nil
|
|
21
|
+
::SelfishAssociations::Nilifier.new(result)
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
File without changes
|
data/lib/selfish_associations.rb
CHANGED
|
@@ -1,7 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
require 'selfish_associations/base'
|
|
2
|
+
require 'selfish_associations/builder'
|
|
3
|
+
require 'selfish_associations/selfish_exception'
|
|
4
|
+
require 'selfish_associations/utils/association_traverser'
|
|
5
|
+
require 'selfish_associations/utils/nilifier'
|
|
6
|
+
require 'selfish_associations/utils/path_merger'
|
|
7
|
+
require 'selfish_associations/scope_readers/instance'
|
|
8
|
+
require 'selfish_associations/scope_readers/relation'
|
|
9
|
+
require 'selfish_associations/associations/association'
|
|
10
|
+
require 'selfish_associations/associations/has_one'
|
|
11
|
+
require 'selfish_associations/associations/has_many'
|
|
2
12
|
|
|
3
|
-
|
|
4
|
-
require 'selfish_associations/association'
|
|
5
|
-
require 'selfish_associations/path_merger'
|
|
6
|
-
require 'selfish_associations/scope_reader'
|
|
7
|
-
require 'selfish_associations/selfish_exception'
|
|
13
|
+
ActiveRecord::Base.include(SelfishAssociations::Base)
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: selfish_associations
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.1.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Andrew Schwartz
|
|
@@ -10,22 +10,24 @@ bindir: bin
|
|
|
10
10
|
cert_chain: []
|
|
11
11
|
date: 2016-05-04 00:00:00.000000000 Z
|
|
12
12
|
dependencies: []
|
|
13
|
-
description: Create
|
|
13
|
+
description: Create joinable associations with instance/record-level constraints
|
|
14
14
|
email: ozydingo@gmail.com
|
|
15
15
|
executables: []
|
|
16
16
|
extensions: []
|
|
17
17
|
extra_rdoc_files: []
|
|
18
18
|
files:
|
|
19
19
|
- lib/selfish_associations.rb
|
|
20
|
-
- lib/selfish_associations/association_traverser.rb
|
|
21
20
|
- lib/selfish_associations/associations/association.rb
|
|
22
21
|
- lib/selfish_associations/associations/has_many.rb
|
|
23
22
|
- lib/selfish_associations/associations/has_one.rb
|
|
24
23
|
- lib/selfish_associations/base.rb
|
|
25
24
|
- lib/selfish_associations/builder.rb
|
|
26
|
-
- lib/selfish_associations/
|
|
27
|
-
- lib/selfish_associations/
|
|
25
|
+
- lib/selfish_associations/scope_readers/instance.rb
|
|
26
|
+
- lib/selfish_associations/scope_readers/relation.rb
|
|
28
27
|
- lib/selfish_associations/selfish_exception.rb
|
|
28
|
+
- lib/selfish_associations/utils/association_traverser.rb
|
|
29
|
+
- lib/selfish_associations/utils/nilifier.rb
|
|
30
|
+
- lib/selfish_associations/utils/path_merger.rb
|
|
29
31
|
homepage: https://github.com/ozydingo/selfish_associations
|
|
30
32
|
licenses:
|
|
31
33
|
- MIT
|
|
@@ -1,55 +0,0 @@
|
|
|
1
|
-
# A SelfishAssociations::ScopeReader is responsible for reading a scope lambda, such
|
|
2
|
-
# as `->(foo){ where language_id: foo.language_id}`. The reader collects information
|
|
3
|
-
# about the scope in order to apply it either to an instnace-level find, e.g.,
|
|
4
|
-
# `where(language_id: 1)`, or to a joins, e.g., `where("language_id = foos.language_id")
|
|
5
|
-
# It does this by responding to `where` and `create_with` methods that you might
|
|
6
|
-
# use in a scope and keeping track of the resulitng Arel Nodes in order to build
|
|
7
|
-
# the find or joins query, using an SelfishAssociations::AssociationTraverser to interpret
|
|
8
|
-
# the conditions themselves.
|
|
9
|
-
|
|
10
|
-
module SelfishAssociations
|
|
11
|
-
class ScopeReader < BasicObject
|
|
12
|
-
attr_reader :traverser
|
|
13
|
-
|
|
14
|
-
def initialize(klass)
|
|
15
|
-
@traverser = ::SelfishAssociations::AssociationTraverser.new(klass)
|
|
16
|
-
@conditions_for_find = {}
|
|
17
|
-
@joins_for_find = []
|
|
18
|
-
@attribuets_for_create = {}
|
|
19
|
-
@joins_for_create = []
|
|
20
|
-
end
|
|
21
|
-
|
|
22
|
-
def read(scope)
|
|
23
|
-
args = scope.arity == 0 ? [] : [@traverser]
|
|
24
|
-
instance_exec(*args, &scope)
|
|
25
|
-
end
|
|
26
|
-
|
|
27
|
-
def where(conditions)
|
|
28
|
-
@conditions_for_find.merge!(conditions)
|
|
29
|
-
@joins_for_find += @traverser.associations!(merge: false)
|
|
30
|
-
@traverser.reset!
|
|
31
|
-
return self
|
|
32
|
-
end
|
|
33
|
-
|
|
34
|
-
def create_with(conditions)
|
|
35
|
-
@attribuets_for_create.merge!(conditions)
|
|
36
|
-
@joins_for_create += @traverser.associations!
|
|
37
|
-
@traverser.reset!
|
|
38
|
-
return self
|
|
39
|
-
end
|
|
40
|
-
|
|
41
|
-
attr_reader :conditions_for_find, :attribuets_for_create
|
|
42
|
-
|
|
43
|
-
def joins_for_find
|
|
44
|
-
::SelfishAssociations::PathMerger.new(@joins_for_find).merge
|
|
45
|
-
end
|
|
46
|
-
|
|
47
|
-
def joins_for_create
|
|
48
|
-
::SelfishAssociations::PathMerger.new(@joins_for_create).merge
|
|
49
|
-
end
|
|
50
|
-
|
|
51
|
-
# TODO: implement `.where.not`
|
|
52
|
-
# TODO: join to other SelfishAssociations associations
|
|
53
|
-
|
|
54
|
-
end
|
|
55
|
-
end
|