active_model_cachers 2.1.5 → 2.1.6
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/.gitignore +9 -9
- data/.travis.yml +2 -2
- data/CHANGELOG.md +62 -57
- data/CODE_OF_CONDUCT.md +48 -48
- data/LICENSE.txt +21 -21
- data/README.md +23 -10
- data/Rakefile +10 -10
- data/active_model_cachers.gemspec +1 -1
- data/bin/console +14 -14
- data/bin/setup +8 -8
- data/gemfiles/3.2.gemfile +11 -11
- data/gemfiles/4.2.gemfile +11 -11
- data/gemfiles/5.0.gemfile +11 -11
- data/gemfiles/5.1.gemfile +11 -11
- data/gemfiles/5.2.gemfile +11 -11
- data/lib/active_model_cachers.rb +0 -0
- data/lib/active_model_cachers/active_record/attr_model.rb +124 -103
- data/lib/active_model_cachers/active_record/cacher.rb +97 -97
- data/lib/active_model_cachers/active_record/extension.rb +119 -107
- data/lib/active_model_cachers/active_record/global_callbacks.rb +67 -67
- data/lib/active_model_cachers/cache_service.rb +151 -151
- data/lib/active_model_cachers/cache_service_factory.rb +55 -55
- data/lib/active_model_cachers/column_value_cache.rb +47 -47
- data/lib/active_model_cachers/config.rb +6 -6
- data/lib/active_model_cachers/false_object.rb +5 -5
- data/lib/active_model_cachers/hook/associations.rb +43 -43
- data/lib/active_model_cachers/hook/dependencies.rb +38 -38
- data/lib/active_model_cachers/hook/on_model_delete.rb +29 -29
- data/lib/active_model_cachers/nil_object.rb +5 -5
- data/lib/active_model_cachers/patches/patch_rails_3.rb +49 -49
- data/lib/active_model_cachers/patches/uninitialized_attribute.rb +9 -9
- data/lib/active_model_cachers/version.rb +4 -4
- metadata +13 -7
data/bin/setup
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
#!/usr/bin/env bash
|
2
|
-
set -euo pipefail
|
3
|
-
IFS=$'\n\t'
|
4
|
-
set -vx
|
5
|
-
|
6
|
-
bundle install --gemfile=gemfiles/3.2.gemfile
|
7
|
-
|
8
|
-
# Do any other automated setup that you need to do here
|
1
|
+
#!/usr/bin/env bash
|
2
|
+
set -euo pipefail
|
3
|
+
IFS=$'\n\t'
|
4
|
+
set -vx
|
5
|
+
|
6
|
+
bundle install --gemfile=gemfiles/3.2.gemfile
|
7
|
+
|
8
|
+
# Do any other automated setup that you need to do here
|
data/gemfiles/3.2.gemfile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem "activerecord", "~> 3.2.0"
|
4
|
-
gem "request_store", "~> 1.4.0"
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem "simplecov"
|
8
|
-
end
|
9
|
-
|
10
|
-
gemspec :path => "../"
|
11
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "activerecord", "~> 3.2.0"
|
4
|
+
gem "request_store", "~> 1.4.0"
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem "simplecov"
|
8
|
+
end
|
9
|
+
|
10
|
+
gemspec :path => "../"
|
11
|
+
|
data/gemfiles/4.2.gemfile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem "activerecord", "~> 4.2.0"
|
4
|
-
gem "request_store", "~> 1.4.0"
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem "simplecov"
|
8
|
-
end
|
9
|
-
|
10
|
-
gemspec :path => "../"
|
11
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "activerecord", "~> 4.2.0"
|
4
|
+
gem "request_store", "~> 1.4.0"
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem "simplecov"
|
8
|
+
end
|
9
|
+
|
10
|
+
gemspec :path => "../"
|
11
|
+
|
data/gemfiles/5.0.gemfile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem "activerecord", "~> 5.0.0"
|
4
|
-
gem "request_store", "~> 1.4.0"
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem "simplecov"
|
8
|
-
end
|
9
|
-
|
10
|
-
gemspec :path => "../"
|
11
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "activerecord", "~> 5.0.0"
|
4
|
+
gem "request_store", "~> 1.4.0"
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem "simplecov"
|
8
|
+
end
|
9
|
+
|
10
|
+
gemspec :path => "../"
|
11
|
+
|
data/gemfiles/5.1.gemfile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem "activerecord", "~> 5.1.0"
|
4
|
-
gem "request_store", "~> 1.4.0"
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem "simplecov"
|
8
|
-
end
|
9
|
-
|
10
|
-
gemspec :path => "../"
|
11
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "activerecord", "~> 5.1.0"
|
4
|
+
gem "request_store", "~> 1.4.0"
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem "simplecov"
|
8
|
+
end
|
9
|
+
|
10
|
+
gemspec :path => "../"
|
11
|
+
|
data/gemfiles/5.2.gemfile
CHANGED
@@ -1,11 +1,11 @@
|
|
1
|
-
source 'https://rubygems.org'
|
2
|
-
|
3
|
-
gem "activerecord", "~> 5.2.0"
|
4
|
-
gem "request_store", "~> 1.4.0"
|
5
|
-
|
6
|
-
group :test do
|
7
|
-
gem "simplecov"
|
8
|
-
end
|
9
|
-
|
10
|
-
gemspec :path => "../"
|
11
|
-
|
1
|
+
source 'https://rubygems.org'
|
2
|
+
|
3
|
+
gem "activerecord", "~> 5.2.0"
|
4
|
+
gem "request_store", "~> 1.4.0"
|
5
|
+
|
6
|
+
group :test do
|
7
|
+
gem "simplecov"
|
8
|
+
end
|
9
|
+
|
10
|
+
gemspec :path => "../"
|
11
|
+
|
data/lib/active_model_cachers.rb
CHANGED
File without changes
|
@@ -1,103 +1,124 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module ActiveModelCachers
|
3
|
-
module ActiveRecord
|
4
|
-
class AttrModel
|
5
|
-
attr_reader :klass, :column, :reflect
|
6
|
-
|
7
|
-
def initialize(klass, column, primary_key: nil, foreign_key: nil)
|
8
|
-
@klass = klass
|
9
|
-
@column = column
|
10
|
-
@primary_key = primary_key
|
11
|
-
@foreign_key = foreign_key
|
12
|
-
@reflect = klass.reflect_on_association(column)
|
13
|
-
end
|
14
|
-
|
15
|
-
def association?
|
16
|
-
return (@reflect != nil)
|
17
|
-
end
|
18
|
-
|
19
|
-
def class_name
|
20
|
-
return if not association?
|
21
|
-
return @reflect.class_name
|
22
|
-
end
|
23
|
-
|
24
|
-
def join_table
|
25
|
-
return nil if @reflect == nil
|
26
|
-
options = @reflect.options
|
27
|
-
return options[:through] if options[:through]
|
28
|
-
return (options[:join_table] || @reflect.send(:derive_join_table)) if @reflect.macro == :has_and_belongs_to_many
|
29
|
-
return nil
|
30
|
-
end
|
31
|
-
|
32
|
-
def
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
return @
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
return
|
53
|
-
return if
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
return
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
return
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
return
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
return
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
return binding if
|
84
|
-
return
|
85
|
-
end
|
86
|
-
|
87
|
-
def
|
88
|
-
return
|
89
|
-
return @klass.
|
90
|
-
end
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ActiveModelCachers
|
3
|
+
module ActiveRecord
|
4
|
+
class AttrModel
|
5
|
+
attr_reader :klass, :column, :reflect
|
6
|
+
|
7
|
+
def initialize(klass, column, primary_key: nil, foreign_key: nil)
|
8
|
+
@klass = klass
|
9
|
+
@column = column
|
10
|
+
@primary_key = primary_key
|
11
|
+
@foreign_key = foreign_key
|
12
|
+
@reflect = klass.reflect_on_association(column)
|
13
|
+
end
|
14
|
+
|
15
|
+
def association?
|
16
|
+
return (@reflect != nil)
|
17
|
+
end
|
18
|
+
|
19
|
+
def class_name
|
20
|
+
return if not association?
|
21
|
+
return @reflect.class_name
|
22
|
+
end
|
23
|
+
|
24
|
+
def join_table
|
25
|
+
return nil if @reflect == nil
|
26
|
+
options = @reflect.options
|
27
|
+
return options[:through] if options[:through]
|
28
|
+
return (options[:join_table] || @reflect.send(:derive_join_table)) if @reflect.macro == :has_and_belongs_to_many
|
29
|
+
return nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def join_table_class_name
|
33
|
+
join_table.try{|table_name| @klass.reflect_on_association(table_name).try(:class_name) || through_klass.name }
|
34
|
+
end
|
35
|
+
|
36
|
+
def through_reflection
|
37
|
+
@klass.new.association(@column).reflection.through_reflection
|
38
|
+
end
|
39
|
+
|
40
|
+
def through_klass
|
41
|
+
through_reflection.try(:klass) || through_klass_for_rails_3
|
42
|
+
end
|
43
|
+
|
44
|
+
def belongs_to?
|
45
|
+
return false if not association?
|
46
|
+
return @reflect.belongs_to?
|
47
|
+
end
|
48
|
+
|
49
|
+
def has_one?
|
50
|
+
return false if not association?
|
51
|
+
#return @reflect.has_one? # Rails 3 doesn't have this method
|
52
|
+
return false if @reflect.collection?
|
53
|
+
return false if @reflect.belongs_to?
|
54
|
+
return true
|
55
|
+
end
|
56
|
+
|
57
|
+
def primary_key
|
58
|
+
return @primary_key if @primary_key
|
59
|
+
return if not association?
|
60
|
+
return (@reflect.belongs_to? ? @reflect.klass : @reflect.active_record).primary_key
|
61
|
+
end
|
62
|
+
|
63
|
+
def foreign_key(reverse: false)
|
64
|
+
return @foreign_key if @foreign_key
|
65
|
+
return if not association?
|
66
|
+
# key may be symbol if specify foreign_key in association options
|
67
|
+
return @reflect.chain.last.foreign_key.to_s if reverse and join_table
|
68
|
+
return (@reflect.belongs_to? == reverse ? primary_key : @reflect.foreign_key).to_s
|
69
|
+
end
|
70
|
+
|
71
|
+
def single_association?
|
72
|
+
return false if not association?
|
73
|
+
return !collection?
|
74
|
+
end
|
75
|
+
|
76
|
+
def collection?
|
77
|
+
return false if not association?
|
78
|
+
return @reflect.collection?
|
79
|
+
end
|
80
|
+
|
81
|
+
def query_model(binding, id)
|
82
|
+
return query_self(binding, id) if @column == nil
|
83
|
+
return query_association(binding, id) if association?
|
84
|
+
return query_attribute(binding, id)
|
85
|
+
end
|
86
|
+
|
87
|
+
def extract_class_and_column
|
88
|
+
return [class_name, nil] if single_association?
|
89
|
+
return [@klass.to_s, @column]
|
90
|
+
end
|
91
|
+
|
92
|
+
private
|
93
|
+
|
94
|
+
def query_self(binding, id)
|
95
|
+
return binding if binding.is_a?(::ActiveRecord::Base)
|
96
|
+
return @klass.find_by(primary_key => id)
|
97
|
+
end
|
98
|
+
|
99
|
+
def query_attribute(binding, id)
|
100
|
+
return binding.send(@column) if binding.is_a?(::ActiveRecord::Base) and binding.has_attribute?(@column)
|
101
|
+
return @klass.where(id: id).limit(1).pluck(@column).first
|
102
|
+
end
|
103
|
+
|
104
|
+
def query_association(binding, id)
|
105
|
+
return binding.association(@column).load_target if binding.is_a?(::ActiveRecord::Base)
|
106
|
+
id = @reflect.active_record.where(id: id).limit(1).pluck(foreign_key).first if foreign_key != 'id'
|
107
|
+
case
|
108
|
+
when collection? ; return id ? @reflect.klass.where(@reflect.foreign_key => id).to_a : []
|
109
|
+
when has_one? ; return id ? @reflect.klass.find_by(foreign_key(reverse: true) => id) : nil
|
110
|
+
else ; return id ? @reflect.klass.find_by(primary_key => id) : nil
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def through_klass_for_rails_3
|
115
|
+
const_name = "HABTM_#{@reflect.klass.name.pluralize}"
|
116
|
+
@klass.const_defined?(const_name) ? @klass.const_get(const_name) : @klass.const_set(const_name, create_through_klass_for_rails_3)
|
117
|
+
end
|
118
|
+
|
119
|
+
def create_through_klass_for_rails_3
|
120
|
+
Class.new(::ActiveRecord::Base).tap{|s| s.table_name = join_table }
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
124
|
+
end
|
@@ -1,97 +1,97 @@
|
|
1
|
-
# frozen_string_literal: true
|
2
|
-
module ActiveModelCachers
|
3
|
-
module ActiveRecord
|
4
|
-
class Cacher
|
5
|
-
@defined_map = {}
|
6
|
-
|
7
|
-
class << self
|
8
|
-
def get_cacher_klass(klass)
|
9
|
-
@defined_map[klass] ||= create_cacher_klass_at(klass)
|
10
|
-
end
|
11
|
-
|
12
|
-
def define_cacher_method(attr, primary_key, service_klasses)
|
13
|
-
cacher_klass = get_cacher_klass(attr.klass)
|
14
|
-
method = attr.column
|
15
|
-
return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
|
16
|
-
cacher_klass.send(:define_methods, method, {
|
17
|
-
method => ->{ exec_by(attr, primary_key, service_klasses, :get) },
|
18
|
-
"peek_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :peek) },
|
19
|
-
"clean_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :clean_cache) },
|
20
|
-
})
|
21
|
-
end
|
22
|
-
|
23
|
-
def define_find_by(attr, primary_key, service_klasses)
|
24
|
-
if @find_by_mapping == nil
|
25
|
-
@find_by_mapping = {}
|
26
|
-
define_methods(:find_by, {
|
27
|
-
:find_by => ->(args){ exec_find_by(args, :get) },
|
28
|
-
:peek_by => ->(args){ exec_find_by(args, :peek) },
|
29
|
-
:clean_by => ->(args){ exec_find_by(args, :clean_cache) },
|
30
|
-
})
|
31
|
-
end
|
32
|
-
@find_by_mapping[primary_key] = [attr, service_klasses]
|
33
|
-
end
|
34
|
-
|
35
|
-
private
|
36
|
-
|
37
|
-
def define_methods(attribute, methods_mapping)
|
38
|
-
if attributes.include?(attribute)
|
39
|
-
methods_mapping.keys.each{|s| undef_method(s) }
|
40
|
-
else
|
41
|
-
attributes << attribute
|
42
|
-
end
|
43
|
-
methods_mapping.each{|method, block| define_method(method, &block) }
|
44
|
-
end
|
45
|
-
|
46
|
-
def get_data_from_find_by_mapping(primary_key)
|
47
|
-
return if @find_by_mapping == nil
|
48
|
-
return @find_by_mapping[primary_key]
|
49
|
-
end
|
50
|
-
|
51
|
-
def create_cacher_klass_at(target)
|
52
|
-
cacher_klass = Class.new(self)
|
53
|
-
cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
|
54
|
-
cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
|
55
|
-
cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
|
56
|
-
cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }
|
57
|
-
|
58
|
-
target.define_singleton_method(:cacher_at){|id| cacher_klass.new(id: id) }
|
59
|
-
target.define_singleton_method(:cacher){ cacher_klass.new }
|
60
|
-
target.send(:define_method, :cacher){ cacher_klass.new(model: self) }
|
61
|
-
return cacher_klass
|
62
|
-
end
|
63
|
-
end
|
64
|
-
|
65
|
-
def initialize(id: nil, model: nil)
|
66
|
-
@id = id
|
67
|
-
@model = model
|
68
|
-
end
|
69
|
-
|
70
|
-
private
|
71
|
-
|
72
|
-
def exec_find_by(args, method) # e.g. args = {course_id: xx}
|
73
|
-
primary_key = args.keys.sort.first # Support only one key now.
|
74
|
-
attr, service_klasses = self.class.send(:get_data_from_find_by_mapping, primary_key)
|
75
|
-
return if service_klasses == nil
|
76
|
-
return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
|
77
|
-
end
|
78
|
-
|
79
|
-
def exec_by(attr, primary_key, service_klasses, method, data: nil)
|
80
|
-
bindings = [@model]
|
81
|
-
reflects = (attr.belongs_to? ? [] : [attr.reflect])
|
82
|
-
if @model and attr.association?
|
83
|
-
if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
|
84
|
-
association = @model.association(attr.column)
|
85
|
-
bindings << association.load_target if association.loaded?
|
86
|
-
end
|
87
|
-
end
|
88
|
-
data ||= (@model ? @model.send(primary_key) : nil) || @id
|
89
|
-
service_klasses.each_with_index do |service_klass, index|
|
90
|
-
data = service_klass.instance(data).send(method, binding: bindings[index], reflect: reflects[index])
|
91
|
-
return if data == nil
|
92
|
-
end
|
93
|
-
return data
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
97
|
-
end
|
1
|
+
# frozen_string_literal: true
|
2
|
+
module ActiveModelCachers
|
3
|
+
module ActiveRecord
|
4
|
+
class Cacher
|
5
|
+
@defined_map = {}
|
6
|
+
|
7
|
+
class << self
|
8
|
+
def get_cacher_klass(klass)
|
9
|
+
@defined_map[klass] ||= create_cacher_klass_at(klass)
|
10
|
+
end
|
11
|
+
|
12
|
+
def define_cacher_method(attr, primary_key, service_klasses)
|
13
|
+
cacher_klass = get_cacher_klass(attr.klass)
|
14
|
+
method = attr.column
|
15
|
+
return cacher_klass.define_find_by(attr, primary_key, service_klasses) if method == nil
|
16
|
+
cacher_klass.send(:define_methods, method, {
|
17
|
+
method => ->{ exec_by(attr, primary_key, service_klasses, :get) },
|
18
|
+
"peek_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :peek) },
|
19
|
+
"clean_#{method}" => ->{ exec_by(attr, primary_key, service_klasses, :clean_cache) },
|
20
|
+
})
|
21
|
+
end
|
22
|
+
|
23
|
+
def define_find_by(attr, primary_key, service_klasses)
|
24
|
+
if @find_by_mapping == nil
|
25
|
+
@find_by_mapping = {}
|
26
|
+
define_methods(:find_by, {
|
27
|
+
:find_by => ->(args){ exec_find_by(args, :get) },
|
28
|
+
:peek_by => ->(args){ exec_find_by(args, :peek) },
|
29
|
+
:clean_by => ->(args){ exec_find_by(args, :clean_cache) },
|
30
|
+
})
|
31
|
+
end
|
32
|
+
@find_by_mapping[primary_key] = [attr, service_klasses]
|
33
|
+
end
|
34
|
+
|
35
|
+
private
|
36
|
+
|
37
|
+
def define_methods(attribute, methods_mapping)
|
38
|
+
if attributes.include?(attribute)
|
39
|
+
methods_mapping.keys.each{|s| undef_method(s) }
|
40
|
+
else
|
41
|
+
attributes << attribute
|
42
|
+
end
|
43
|
+
methods_mapping.each{|method, block| define_method(method, &block) }
|
44
|
+
end
|
45
|
+
|
46
|
+
def get_data_from_find_by_mapping(primary_key)
|
47
|
+
return if @find_by_mapping == nil
|
48
|
+
return @find_by_mapping[primary_key]
|
49
|
+
end
|
50
|
+
|
51
|
+
def create_cacher_klass_at(target)
|
52
|
+
cacher_klass = Class.new(self)
|
53
|
+
cacher_klass.instance_variable_set(:@find_by_mapping, nil) # to remove warning: instance variable @find_by_mapping not initialized
|
54
|
+
cacher_klass.define_singleton_method(:attributes){ @attributes ||= [] }
|
55
|
+
cacher_klass.send(:define_method, 'peek'){|column| send("peek_#{column}") }
|
56
|
+
cacher_klass.send(:define_method, 'clean'){|column| send("clean_#{column}") }
|
57
|
+
|
58
|
+
target.define_singleton_method(:cacher_at){|id| cacher_klass.new(id: id) }
|
59
|
+
target.define_singleton_method(:cacher){ cacher_klass.new }
|
60
|
+
target.send(:define_method, :cacher){ cacher_klass.new(model: self) }
|
61
|
+
return cacher_klass
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
def initialize(id: nil, model: nil)
|
66
|
+
@id = id
|
67
|
+
@model = model
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def exec_find_by(args, method) # e.g. args = {course_id: xx}
|
73
|
+
primary_key = args.keys.sort.first # Support only one key now.
|
74
|
+
attr, service_klasses = self.class.send(:get_data_from_find_by_mapping, primary_key)
|
75
|
+
return if service_klasses == nil
|
76
|
+
return exec_by(attr, primary_key, service_klasses, method, data: args[primary_key])
|
77
|
+
end
|
78
|
+
|
79
|
+
def exec_by(attr, primary_key, service_klasses, method, data: nil)
|
80
|
+
bindings = [@model]
|
81
|
+
reflects = (attr.belongs_to? ? [] : [attr.reflect])
|
82
|
+
if @model and attr.association?
|
83
|
+
if attr.belongs_to? and method != :clean_cache # no need to load binding when just cleaning cache
|
84
|
+
association = @model.association(attr.column)
|
85
|
+
bindings << association.load_target if association.loaded?
|
86
|
+
end
|
87
|
+
end
|
88
|
+
data ||= (@model ? @model.send(primary_key) : nil) || @id
|
89
|
+
service_klasses.each_with_index do |service_klass, index|
|
90
|
+
data = service_klass.instance(data).send(method, binding: bindings[index], reflect: reflects[index])
|
91
|
+
return if data == nil
|
92
|
+
end
|
93
|
+
return data
|
94
|
+
end
|
95
|
+
end
|
96
|
+
end
|
97
|
+
end
|