smart_collection 0.0.1 → 0.1
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/smart_collection/associations/preloader/smart_collection.rb +11 -20
- data/lib/smart_collection/associations/smart_collection_association.rb +1 -1
- data/lib/smart_collection/cache_manager/cache_store.rb +9 -3
- data/lib/smart_collection/cache_manager/table.rb +6 -6
- data/lib/smart_collection/cache_manager.rb +5 -1
- data/lib/smart_collection/config.rb +6 -2
- data/lib/smart_collection/mixin.rb +18 -13
- data/lib/smart_collection/reflection/smart_collection_reflection.rb +8 -1
- data/lib/smart_collection/version.rb +3 -0
- data/lib/smart_collection.rb +0 -4
- metadata +28 -7
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA1:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 9f479b5262f4acf4557bce9c9afaefdd07c4c204
|
|
4
|
+
data.tar.gz: a1c9524cfad044566fae79aa21a6bb2286c581bf
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 21811df6d87e734e1565ea5f29c665e1057ca8f7206e1f53b71582d74c35ed821637eff906d5bb5d430d52c366024377c7829ecf48de3a86bf5f631a3e9a67d0
|
|
7
|
+
data.tar.gz: b92c5993149a07987a08bfa22826334611fd5cdc9fd7970daa5a3f321d340a6bbe9f62cd8a316a2eeafb3daad818cd99bc6a2fe00a7df9cd64ce6cd9bba8c1ff
|
|
@@ -3,11 +3,11 @@ module SmartCollection
|
|
|
3
3
|
module Preloader
|
|
4
4
|
class SmartCollectionCachedByTable < ActiveRecord::Associations::Preloader::HasManyThrough
|
|
5
5
|
def through_reflection
|
|
6
|
-
|
|
6
|
+
reflection.active_record.reflect_on_association(:cached_items)
|
|
7
7
|
end
|
|
8
8
|
|
|
9
9
|
def source_reflection
|
|
10
|
-
association_name = reflection.options[:smart_collection].
|
|
10
|
+
association_name = reflection.options[:smart_collection].item_name
|
|
11
11
|
through_reflection.klass.reflect_on_association(association_name)
|
|
12
12
|
end
|
|
13
13
|
|
|
@@ -15,43 +15,34 @@ module SmartCollection
|
|
|
15
15
|
owners.reject(&:cache_exists?).each(&:update_cache)
|
|
16
16
|
super
|
|
17
17
|
end
|
|
18
|
-
|
|
19
|
-
private
|
|
20
|
-
|
|
21
18
|
end
|
|
22
19
|
|
|
23
20
|
class SmartCollectionCachedByCacheStore < ActiveRecord::Associations::Preloader::CollectionAssociation
|
|
24
21
|
def associated_records_by_owner preloader
|
|
25
22
|
owners.reject(&:cache_exists?).each(&:update_cache)
|
|
26
|
-
|
|
27
|
-
|
|
23
|
+
config = reflection.options[:smart_collection]
|
|
24
|
+
loaded = config.cache_manager.read_multi(owners)
|
|
25
|
+
records = config.item_class.where(id: loaded.values.flatten.uniq).map{|x| [x.id, x]}.to_h
|
|
28
26
|
loaded.map do |owner, ids|
|
|
29
27
|
[owner, ids.map{|x| records[x]}]
|
|
30
28
|
end
|
|
31
29
|
end
|
|
32
|
-
|
|
33
|
-
def preload(preloader)
|
|
34
|
-
associated_records_by_owner(preloader).each do |owner, records|
|
|
35
|
-
association = owner.association(reflection.name)
|
|
36
|
-
association.loaded!
|
|
37
|
-
association.target.concat(records)
|
|
38
|
-
end
|
|
39
|
-
end
|
|
40
30
|
end
|
|
31
|
+
|
|
41
32
|
end
|
|
42
33
|
end
|
|
43
34
|
|
|
44
35
|
module ActiveRecordPreloaderPatch
|
|
45
36
|
def preloader_for(reflection, owners, rhs_klass)
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
end
|
|
50
|
-
case reflection.options[:smart_collection].cache_manager
|
|
37
|
+
config = reflection.options[:smart_collection]
|
|
38
|
+
if config
|
|
39
|
+
case config.cache_manager
|
|
51
40
|
when SmartCollection::CacheManager::CacheStore
|
|
52
41
|
SmartCollection::Associations::Preloader::SmartCollectionCachedByCacheStore
|
|
53
42
|
when SmartCollection::CacheManager::Table
|
|
54
43
|
SmartCollection::Associations::Preloader::SmartCollectionCachedByTable
|
|
44
|
+
else
|
|
45
|
+
raise RuntimeError, "Turn on cache to enable preloading."
|
|
55
46
|
end
|
|
56
47
|
else
|
|
57
48
|
super
|
|
@@ -2,12 +2,18 @@ module SmartCollection
|
|
|
2
2
|
class CacheManager
|
|
3
3
|
class CacheStore < CacheManager
|
|
4
4
|
|
|
5
|
+
def initialize model:, config:
|
|
6
|
+
super
|
|
7
|
+
|
|
8
|
+
@cache_key_proc = @config.cache_config[:cache_key_proc] || -> (owner) { "_smart_collection_#{owner.class.name}_#{owner.id}" }
|
|
9
|
+
end
|
|
10
|
+
|
|
5
11
|
def cache_store
|
|
6
12
|
@config.cache_config[:cache_store]
|
|
7
13
|
end
|
|
8
14
|
|
|
9
15
|
def cache_key owner
|
|
10
|
-
|
|
16
|
+
@cache_key_proc.(owner)
|
|
11
17
|
end
|
|
12
18
|
|
|
13
19
|
def update owner
|
|
@@ -17,7 +23,7 @@ module SmartCollection
|
|
|
17
23
|
owner.update(cache_expires_at: Time.now + expires_in)
|
|
18
24
|
end
|
|
19
25
|
|
|
20
|
-
def
|
|
26
|
+
def read_scope owner
|
|
21
27
|
@config.item_class.where(id: Marshal.load(cache_store.read(cache_key owner)))
|
|
22
28
|
end
|
|
23
29
|
|
|
@@ -30,7 +36,7 @@ module SmartCollection
|
|
|
30
36
|
end
|
|
31
37
|
|
|
32
38
|
def cache_exists? owner
|
|
33
|
-
|
|
39
|
+
owner.cache_expires_at && owner.cache_expires_at > Time.now && cache_store.exist?(cache_key owner)
|
|
34
40
|
end
|
|
35
41
|
|
|
36
42
|
end
|
|
@@ -9,17 +9,17 @@ module SmartCollection
|
|
|
9
9
|
end
|
|
10
10
|
|
|
11
11
|
def define_cache_association_for model
|
|
12
|
-
|
|
12
|
+
config = @config
|
|
13
13
|
cached_item_model = nil
|
|
14
14
|
model.class_eval do
|
|
15
15
|
cached_item_model = Class.new ActiveRecord::Base do
|
|
16
16
|
self.table_name = 'smart_collection_cached_items'
|
|
17
|
-
belongs_to
|
|
17
|
+
belongs_to config.item_name, class_name: config.item_class_name, foreign_key: :item_id
|
|
18
18
|
end
|
|
19
19
|
const_set("CachedItem", cached_item_model)
|
|
20
20
|
|
|
21
21
|
has_many :cached_items, class_name: cached_item_model.name, foreign_key: :collection_id
|
|
22
|
-
has_many "cached_#{
|
|
22
|
+
has_many "cached_#{config.items_name}".to_sym, class_name: config.item_class_name, through: :cached_items, source: config.item_name
|
|
23
23
|
end
|
|
24
24
|
@cache_model = cached_item_model
|
|
25
25
|
end
|
|
@@ -29,16 +29,16 @@ module SmartCollection
|
|
|
29
29
|
|
|
30
30
|
@cache_model.where(collection_id: owner.id).delete_all
|
|
31
31
|
@cache_model.connection.execute "INSERT INTO #{@cache_model.table_name} (collection_id, item_id) #{association.uncached_scope.select(owner.id, :id).to_sql}"
|
|
32
|
-
owner.
|
|
32
|
+
owner.update_column(:cache_expires_at, Time.now + expires_in)
|
|
33
33
|
end
|
|
34
34
|
|
|
35
|
-
def
|
|
35
|
+
def read_scope owner
|
|
36
36
|
cache_association = owner.association("cached_#{@config.items_name}")
|
|
37
37
|
cache_association.scope
|
|
38
38
|
end
|
|
39
39
|
|
|
40
40
|
def cache_exists? owner
|
|
41
|
-
|
|
41
|
+
owner.cache_expires_at && owner.cache_expires_at > Time.now
|
|
42
42
|
end
|
|
43
43
|
|
|
44
44
|
end
|
|
@@ -11,12 +11,16 @@ module SmartCollection
|
|
|
11
11
|
@raw_config[:items]
|
|
12
12
|
end
|
|
13
13
|
|
|
14
|
+
def item_name
|
|
15
|
+
items_name.to_s.singularize.to_sym
|
|
16
|
+
end
|
|
17
|
+
|
|
14
18
|
def item_class_name
|
|
15
|
-
@raw_config[:
|
|
19
|
+
@raw_config[:class_name]
|
|
16
20
|
end
|
|
17
21
|
|
|
18
22
|
def item_class
|
|
19
|
-
item_class_name.constantize
|
|
23
|
+
@item_class ||= item_class_name.constantize
|
|
20
24
|
end
|
|
21
25
|
|
|
22
26
|
def cache_config
|
|
@@ -14,7 +14,13 @@ module SmartCollection
|
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def smart_collection_mixin
|
|
17
|
-
|
|
17
|
+
self.class.smart_collection_mixin
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
module ClassMethods
|
|
22
|
+
def smart_collection_mixin
|
|
23
|
+
@__smart_collection_mixin ||= ancestors.find do |x|
|
|
18
24
|
x.instance_of? Mixin
|
|
19
25
|
end
|
|
20
26
|
end
|
|
@@ -22,24 +28,23 @@ module SmartCollection
|
|
|
22
28
|
|
|
23
29
|
attr_reader :config
|
|
24
30
|
|
|
25
|
-
def initialize
|
|
26
|
-
@raw_config =
|
|
27
|
-
items: items,
|
|
28
|
-
item_class: item_class,
|
|
29
|
-
cached_by: cached_by
|
|
30
|
-
}
|
|
31
|
+
def initialize raw_config
|
|
32
|
+
@raw_config = raw_config
|
|
31
33
|
end
|
|
32
34
|
|
|
33
35
|
def included base
|
|
34
|
-
COLLECTIONS[base] = true
|
|
35
36
|
@config = config = SmartCollection::Config.new(@raw_config)
|
|
36
|
-
name = config.items_name
|
|
37
37
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
38
|
+
reflection_options = {smart_collection: config}
|
|
39
|
+
if config.item_class_name
|
|
40
|
+
reflection_options[:class_name] = config.item_class_name
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
reflection = Builder::SmartCollectionAssociation.build(base, config.items_name, nil, reflection_options)
|
|
44
|
+
::ActiveRecord::Reflection.add_reflection base, config.items_name, reflection
|
|
45
|
+
|
|
42
46
|
base.include(InstanceMethods)
|
|
47
|
+
base.extend(ClassMethods)
|
|
43
48
|
|
|
44
49
|
if cache_class = CacheManager.determine_class(@raw_config)
|
|
45
50
|
config.cache_manager = cache_class.new(model: base, config: config)
|
|
@@ -6,7 +6,14 @@ module SmartCollection
|
|
|
6
6
|
end
|
|
7
7
|
|
|
8
8
|
def check_eager_loadable!
|
|
9
|
-
|
|
9
|
+
unless options[:smart_collection].cache_manager.instance_of? SmartCollection::CacheManager::Table
|
|
10
|
+
raise RuntimeError, 'eager_load is only supported when using table for cache.'
|
|
11
|
+
end
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def chain
|
|
15
|
+
items_name = options[:smart_collection].items_name
|
|
16
|
+
active_record.reflect_on_association("cached_#{items_name}".to_sym).chain
|
|
10
17
|
end
|
|
11
18
|
end
|
|
12
19
|
end
|
data/lib/smart_collection.rb
CHANGED
metadata
CHANGED
|
@@ -1,29 +1,35 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: smart_collection
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: '0.1'
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- CicholGricenchos
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date: 2018-01-
|
|
11
|
+
date: 2018-01-09 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: activerecord
|
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
|
16
16
|
requirements:
|
|
17
|
-
- - "
|
|
17
|
+
- - ">="
|
|
18
|
+
- !ruby/object:Gem::Version
|
|
19
|
+
version: '5.0'
|
|
20
|
+
- - "<"
|
|
18
21
|
- !ruby/object:Gem::Version
|
|
19
|
-
version: '
|
|
22
|
+
version: '6.0'
|
|
20
23
|
type: :runtime
|
|
21
24
|
prerelease: false
|
|
22
25
|
version_requirements: !ruby/object:Gem::Requirement
|
|
23
26
|
requirements:
|
|
24
|
-
- - "
|
|
27
|
+
- - ">="
|
|
25
28
|
- !ruby/object:Gem::Version
|
|
26
|
-
version: '5'
|
|
29
|
+
version: '5.0'
|
|
30
|
+
- - "<"
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '6.0'
|
|
27
33
|
- !ruby/object:Gem::Dependency
|
|
28
34
|
name: pry
|
|
29
35
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -66,6 +72,20 @@ dependencies:
|
|
|
66
72
|
- - ">="
|
|
67
73
|
- !ruby/object:Gem::Version
|
|
68
74
|
version: '0'
|
|
75
|
+
- !ruby/object:Gem::Dependency
|
|
76
|
+
name: rake
|
|
77
|
+
requirement: !ruby/object:Gem::Requirement
|
|
78
|
+
requirements:
|
|
79
|
+
- - ">="
|
|
80
|
+
- !ruby/object:Gem::Version
|
|
81
|
+
version: '0'
|
|
82
|
+
type: :development
|
|
83
|
+
prerelease: false
|
|
84
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
85
|
+
requirements:
|
|
86
|
+
- - ">="
|
|
87
|
+
- !ruby/object:Gem::Version
|
|
88
|
+
version: '0'
|
|
69
89
|
description: ''
|
|
70
90
|
email:
|
|
71
91
|
- cichol@live.cn
|
|
@@ -83,6 +103,7 @@ files:
|
|
|
83
103
|
- lib/smart_collection/config.rb
|
|
84
104
|
- lib/smart_collection/mixin.rb
|
|
85
105
|
- lib/smart_collection/reflection/smart_collection_reflection.rb
|
|
106
|
+
- lib/smart_collection/version.rb
|
|
86
107
|
homepage: https://github.com/CicholGricenchos/smart_collection
|
|
87
108
|
licenses:
|
|
88
109
|
- MIT
|
|
@@ -106,5 +127,5 @@ rubyforge_project:
|
|
|
106
127
|
rubygems_version: 2.5.2.1
|
|
107
128
|
signing_key:
|
|
108
129
|
specification_version: 4
|
|
109
|
-
summary:
|
|
130
|
+
summary: collections by rules
|
|
110
131
|
test_files: []
|