thermos 0.5.2 → 1.0.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/Rakefile +4 -0
- data/lib/thermos/beverage.rb +37 -24
- data/lib/thermos/notifier.rb +1 -3
- data/lib/thermos/refill_job.rb +12 -4
- data/lib/thermos/version.rb +1 -1
- data/lib/thermos.rb +48 -13
- data/test/dependencies_test.rb +307 -0
- data/test/dummy/app/models/category.rb +4 -6
- data/test/dummy/config/application.rb +2 -5
- data/test/dummy/config/boot.rb +3 -3
- data/test/dummy/config/environment.rb +1 -1
- data/test/dummy/config/environments/development.rb +4 -4
- data/test/dummy/config/environments/production.rb +6 -5
- data/test/dummy/config/environments/test.rb +3 -3
- data/test/dummy/config/initializers/assets.rb +1 -1
- data/test/dummy/config/initializers/session_store.rb +1 -1
- data/test/dummy/config/routes.rb +0 -9
- data/test/dummy/db/schema.rb +9 -11
- data/test/filter_test.rb +52 -0
- data/test/queue_test.rb +36 -0
- data/test/test_helper.rb +15 -5
- data/test/thermos_test.rb +18 -368
- metadata +74 -40
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 8436d0765dee9eafadbbb9994cce8aaed1e5746d96bc735fccdf55a945dcb4a8
|
4
|
+
data.tar.gz: 19fd374d31d2885979d791ab9dc0bfe021c9c61053b97ed4f96a0a5d862afa75
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: dd71bd6038960d9c556b3d55b697a6126d14573bb12ddc131e52a592629e39cc15e054c54cb0ee44aaf90a7b9879a43fc72571a9920c3ceae7b3a0721fb09cc2
|
7
|
+
data.tar.gz: 6de309fc56d581825c7497cd137595769ca81eff2298f9ba791b5809511bf1281e9b7376feac34849592c660605c9f53b5304e751f3e53df55cea8d377bf5413
|
data/Rakefile
CHANGED
data/lib/thermos/beverage.rb
CHANGED
@@ -2,33 +2,44 @@
|
|
2
2
|
|
3
3
|
module Thermos
|
4
4
|
class Beverage
|
5
|
-
attr_reader :key, :model, :deps, :action, :lookup_key, :filter
|
5
|
+
attr_reader :key, :model, :deps, :action, :lookup_key, :filter, :queue
|
6
6
|
|
7
|
-
def initialize(
|
7
|
+
def initialize(
|
8
|
+
key:,
|
9
|
+
model:,
|
10
|
+
deps:,
|
11
|
+
action:,
|
12
|
+
lookup_key: nil,
|
13
|
+
filter: nil,
|
14
|
+
queue: nil
|
15
|
+
)
|
8
16
|
@key = key
|
9
17
|
@model = model
|
10
18
|
@lookup_key = lookup_key || :id
|
11
19
|
@filter = filter || nil
|
12
20
|
@deps = generate_deps(model, deps)
|
13
21
|
@action = action
|
22
|
+
@queue = queue || ActiveJob::Base.default_queue_name
|
14
23
|
|
15
24
|
set_observers
|
16
25
|
end
|
17
26
|
|
18
27
|
def lookup_keys_for_dep_model(dep_model)
|
19
|
-
@deps
|
20
|
-
dep.klass == dep_model.class
|
21
|
-
|
22
|
-
|
28
|
+
@deps
|
29
|
+
.select { |dep| dep.klass == dep_model.class }
|
30
|
+
.flat_map do |dep|
|
31
|
+
lookup_keys = []
|
23
32
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
33
|
+
@model
|
34
|
+
.joins(dep.path)
|
35
|
+
.where(dep.table => { id: dep_model.id })
|
36
|
+
.find_each do |model|
|
37
|
+
lookup_keys << model.send(@lookup_key) if should_fill?(model)
|
38
|
+
end
|
29
39
|
|
30
|
-
|
31
|
-
|
40
|
+
lookup_keys
|
41
|
+
end
|
42
|
+
.uniq
|
32
43
|
end
|
33
44
|
|
34
45
|
def should_fill?(model)
|
@@ -50,23 +61,25 @@ module Thermos
|
|
50
61
|
deps.reduce([]) do |acc, dep|
|
51
62
|
if dep.is_a? Symbol
|
52
63
|
acc << Dependency.new(
|
53
|
-
model: root || model,
|
54
|
-
ref: model.reflect_on_association(dep),
|
55
|
-
path: path || dep
|
64
|
+
model: root || model,
|
65
|
+
ref: model.reflect_on_association(dep),
|
66
|
+
path: path || dep,
|
67
|
+
)
|
56
68
|
elsif dep.is_a? Array
|
57
|
-
dep.each do |d|
|
69
|
+
dep.each do |d|
|
58
70
|
acc << Dependency.new(
|
59
|
-
model: root || model,
|
60
|
-
ref: model.reflect_on_association(d),
|
61
|
-
path: path || d
|
71
|
+
model: root || model,
|
72
|
+
ref: model.reflect_on_association(d),
|
73
|
+
path: path || d,
|
74
|
+
)
|
62
75
|
end
|
63
76
|
elsif dep.is_a? Hash
|
64
|
-
dep.each do |k,v|
|
77
|
+
dep.each do |k, v|
|
65
78
|
ref = model.reflect_on_association(k)
|
66
79
|
acc << Dependency.new(
|
67
|
-
model: root || model,
|
68
|
-
ref: ref,
|
69
|
-
path: path || k
|
80
|
+
model: root || model,
|
81
|
+
ref: ref,
|
82
|
+
path: path || k,
|
70
83
|
)
|
71
84
|
acc.concat(generate_deps(ref.class_name.constantize, v, model, dep))
|
72
85
|
end
|
data/lib/thermos/notifier.rb
CHANGED
data/lib/thermos/refill_job.rb
CHANGED
@@ -10,16 +10,24 @@ module Thermos
|
|
10
10
|
def refill_primary_caches(model)
|
11
11
|
BeverageStorage.instance.beverages.each do |beverage|
|
12
12
|
if beverage.model == model.class && beverage.should_fill?(model)
|
13
|
-
Thermos::RebuildCacheJob.
|
13
|
+
Thermos::RebuildCacheJob.set(queue: beverage.queue).perform_later(
|
14
|
+
beverage.key,
|
15
|
+
model.send(beverage.lookup_key),
|
16
|
+
)
|
14
17
|
end
|
15
18
|
end
|
16
19
|
end
|
17
20
|
|
18
21
|
def refill_dependency_caches(model)
|
19
22
|
BeverageStorage.instance.beverages.each do |beverage|
|
20
|
-
beverage
|
21
|
-
|
22
|
-
|
23
|
+
beverage
|
24
|
+
.lookup_keys_for_dep_model(model)
|
25
|
+
.each do |lookup_key|
|
26
|
+
Thermos::RebuildCacheJob.set(queue: beverage.queue).perform_later(
|
27
|
+
beverage.key,
|
28
|
+
lookup_key,
|
29
|
+
)
|
30
|
+
end
|
23
31
|
end
|
24
32
|
end
|
25
33
|
end
|
data/lib/thermos/version.rb
CHANGED
data/lib/thermos.rb
CHANGED
@@ -1,27 +1,62 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
|
-
require
|
4
|
-
require
|
5
|
-
require
|
6
|
-
require
|
7
|
-
require
|
8
|
-
require
|
3
|
+
require "thermos/beverage"
|
4
|
+
require "thermos/beverage_storage"
|
5
|
+
require "thermos/dependency"
|
6
|
+
require "thermos/notifier"
|
7
|
+
require "thermos/refill_job"
|
8
|
+
require "thermos/rebuild_cache_job"
|
9
9
|
|
10
10
|
module Thermos
|
11
|
-
def self.keep_warm(
|
12
|
-
|
11
|
+
def self.keep_warm(
|
12
|
+
key:,
|
13
|
+
model:,
|
14
|
+
id:,
|
15
|
+
deps: [],
|
16
|
+
lookup_key: nil,
|
17
|
+
filter: nil,
|
18
|
+
queue: nil,
|
19
|
+
&block
|
20
|
+
)
|
21
|
+
fill(
|
22
|
+
key: key,
|
23
|
+
model: model,
|
24
|
+
deps: deps,
|
25
|
+
lookup_key: lookup_key,
|
26
|
+
filter: filter,
|
27
|
+
queue: queue,
|
28
|
+
&block
|
29
|
+
)
|
13
30
|
drink(key: key, id: id)
|
14
31
|
end
|
15
32
|
|
16
|
-
def self.fill(
|
33
|
+
def self.fill(
|
34
|
+
key:,
|
35
|
+
model:,
|
36
|
+
deps: [],
|
37
|
+
lookup_key: nil,
|
38
|
+
filter: nil,
|
39
|
+
queue: nil,
|
40
|
+
&block
|
41
|
+
)
|
17
42
|
BeverageStorage.instance.add_beverage(
|
18
|
-
Beverage.new(
|
43
|
+
Beverage.new(
|
44
|
+
key: key,
|
45
|
+
model: model,
|
46
|
+
deps: deps,
|
47
|
+
action: block,
|
48
|
+
lookup_key: lookup_key,
|
49
|
+
filter: filter,
|
50
|
+
queue: queue,
|
51
|
+
),
|
19
52
|
)
|
20
53
|
end
|
21
54
|
|
22
55
|
def self.drink(key:, id:)
|
23
|
-
Rails
|
24
|
-
|
25
|
-
|
56
|
+
Rails
|
57
|
+
.cache
|
58
|
+
.fetch([key, id]) do
|
59
|
+
BeverageStorage.instance.get_beverage(key).action.call(id)
|
60
|
+
end
|
26
61
|
end
|
27
62
|
end
|
@@ -0,0 +1,307 @@
|
|
1
|
+
require "test_helper"
|
2
|
+
|
3
|
+
class DependenciesTest < ActiveSupport::TestCase
|
4
|
+
self.use_transactional_tests = true
|
5
|
+
teardown :clear_cache
|
6
|
+
|
7
|
+
test "rebuilds the cache on has_many model change" do
|
8
|
+
mock = Minitest::Mock.new
|
9
|
+
category = categories(:baseball)
|
10
|
+
category_item = category_items(:baseball_glove)
|
11
|
+
|
12
|
+
Thermos.fill(key: "key", model: Category, deps: [:category_items]) do |id|
|
13
|
+
mock.call(id)
|
14
|
+
end
|
15
|
+
|
16
|
+
mock.expect(:call, 1, [category.id])
|
17
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
18
|
+
mock.verify
|
19
|
+
|
20
|
+
mock.expect(:call, 2, [category.id])
|
21
|
+
category_item.update!(name: "foo")
|
22
|
+
mock.verify
|
23
|
+
|
24
|
+
mock.expect(:call, 3, [category.id])
|
25
|
+
assert_equal 2, Thermos.drink(key: "key", id: category.id)
|
26
|
+
assert_raises(MockExpectationError) { mock.verify }
|
27
|
+
end
|
28
|
+
|
29
|
+
test "does not rebuild the cache for an unrelated has_many model change" do
|
30
|
+
mock = Minitest::Mock.new
|
31
|
+
category = categories(:baseball)
|
32
|
+
category_item = CategoryItem.create(category: nil)
|
33
|
+
|
34
|
+
Thermos.fill(key: "key", model: Category, deps: [:category_items]) do |id|
|
35
|
+
mock.call(id)
|
36
|
+
end
|
37
|
+
|
38
|
+
mock.expect(:call, 1, [category.id])
|
39
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
40
|
+
mock.verify
|
41
|
+
|
42
|
+
mock.expect(:call, 2, [category.id])
|
43
|
+
category_item.update!(name: "foo")
|
44
|
+
assert_raises(MockExpectationError) { mock.verify }
|
45
|
+
|
46
|
+
mock.expect(:call, 3, [category.id])
|
47
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
48
|
+
assert_raises(MockExpectationError) { mock.verify }
|
49
|
+
end
|
50
|
+
|
51
|
+
test "re-builds the cache for new has_many records" do
|
52
|
+
mock = Minitest::Mock.new
|
53
|
+
category = categories(:baseball)
|
54
|
+
|
55
|
+
Thermos.fill(key: "key", model: Category, deps: [:category_items]) do |id|
|
56
|
+
mock.call(id)
|
57
|
+
end
|
58
|
+
|
59
|
+
mock.expect(:call, 1, [category.id])
|
60
|
+
CategoryItem.create!(category: category)
|
61
|
+
mock.verify
|
62
|
+
|
63
|
+
mock.expect(:call, 2, [category.id])
|
64
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
65
|
+
assert_raises(MockExpectationError) { mock.verify }
|
66
|
+
end
|
67
|
+
|
68
|
+
test "re-builds the cache for has_many record changes when filter condition is met" do
|
69
|
+
mock = Minitest::Mock.new
|
70
|
+
category = categories(:baseball)
|
71
|
+
filter = ->(model) { model.ball? }
|
72
|
+
|
73
|
+
Thermos.fill(
|
74
|
+
key: "key",
|
75
|
+
model: Category,
|
76
|
+
deps: [:category_items],
|
77
|
+
filter: filter,
|
78
|
+
) { |id| mock.call(id) }
|
79
|
+
|
80
|
+
mock.expect(:call, 1, [category.id])
|
81
|
+
CategoryItem.create!(category: category)
|
82
|
+
mock.verify
|
83
|
+
|
84
|
+
category.update!(name: "hockey")
|
85
|
+
|
86
|
+
mock.expect(:call, 1, [category.id])
|
87
|
+
CategoryItem.create!(category: category)
|
88
|
+
assert_raises(MockExpectationError) { mock.verify }
|
89
|
+
end
|
90
|
+
|
91
|
+
test "rebuilds the cache on belongs_to model change" do
|
92
|
+
mock = Minitest::Mock.new
|
93
|
+
category = categories(:baseball)
|
94
|
+
store = stores(:sports)
|
95
|
+
|
96
|
+
Thermos.fill(key: "key", model: Category, deps: [:store]) do |id|
|
97
|
+
mock.call(id)
|
98
|
+
end
|
99
|
+
|
100
|
+
mock.expect(:call, 1, [category.id])
|
101
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
102
|
+
mock.verify
|
103
|
+
|
104
|
+
mock.expect(:call, 2, [category.id])
|
105
|
+
store.update!(name: "foo")
|
106
|
+
mock.verify
|
107
|
+
|
108
|
+
mock.expect(:call, 3, [category.id])
|
109
|
+
assert_equal 2, Thermos.drink(key: "key", id: category.id)
|
110
|
+
assert_raises(MockExpectationError) { mock.verify }
|
111
|
+
end
|
112
|
+
|
113
|
+
test "does not rebuild the cache for an unrelated belongs_to model change" do
|
114
|
+
mock = Minitest::Mock.new
|
115
|
+
category = categories(:baseball)
|
116
|
+
store = Store.create!
|
117
|
+
|
118
|
+
Thermos.fill(key: "key", model: Category, deps: [:store]) do |id|
|
119
|
+
mock.call(id)
|
120
|
+
end
|
121
|
+
|
122
|
+
mock.expect(:call, 1, [category.id])
|
123
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
124
|
+
mock.verify
|
125
|
+
|
126
|
+
mock.expect(:call, 2, [category.id])
|
127
|
+
store.update!(name: "foo")
|
128
|
+
assert_raises(MockExpectationError) { mock.verify }
|
129
|
+
|
130
|
+
mock.expect(:call, 3, [category.id])
|
131
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
132
|
+
assert_raises(MockExpectationError) { mock.verify }
|
133
|
+
end
|
134
|
+
|
135
|
+
test "re-builds the cache for new belongs_to records" do
|
136
|
+
mock = Minitest::Mock.new
|
137
|
+
category = categories(:baseball)
|
138
|
+
|
139
|
+
Thermos.fill(key: "key", model: Category, deps: [:store]) do |id|
|
140
|
+
mock.call(id)
|
141
|
+
end
|
142
|
+
|
143
|
+
mock.expect(:call, 1, [category.id])
|
144
|
+
mock.expect(:call, 1, [category.id])
|
145
|
+
Store.create!(name: "foo", categories: [category])
|
146
|
+
mock.verify
|
147
|
+
|
148
|
+
mock.expect(:call, 2, [category.id])
|
149
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
150
|
+
assert_raises(MockExpectationError) { mock.verify }
|
151
|
+
end
|
152
|
+
|
153
|
+
test "re-builds the cache for belongs_to record changes when filter condition is met" do
|
154
|
+
mock = Minitest::Mock.new
|
155
|
+
category = categories(:baseball)
|
156
|
+
filter = ->(model) { model.ball? }
|
157
|
+
|
158
|
+
Thermos.fill(
|
159
|
+
key: "key",
|
160
|
+
model: Category,
|
161
|
+
deps: [:store],
|
162
|
+
filter: filter,
|
163
|
+
) { |id| mock.call(id) }
|
164
|
+
|
165
|
+
mock.expect(:call, 1, [category.id])
|
166
|
+
mock.expect(:call, 1, [category.id])
|
167
|
+
Store.create!(name: "foo", categories: [category])
|
168
|
+
mock.verify
|
169
|
+
|
170
|
+
category.update!(name: "hockey")
|
171
|
+
|
172
|
+
mock.expect(:call, 2, [category.id])
|
173
|
+
Store.create!(name: "bar", categories: [category])
|
174
|
+
assert_raises(MockExpectationError) { mock.verify }
|
175
|
+
end
|
176
|
+
|
177
|
+
test "rebuilds the cache on has_many through model change" do
|
178
|
+
mock = Minitest::Mock.new
|
179
|
+
category = categories(:baseball)
|
180
|
+
product = products(:glove)
|
181
|
+
|
182
|
+
Thermos.fill(key: "key", model: Category, deps: [:products]) do |id|
|
183
|
+
mock.call(id)
|
184
|
+
end
|
185
|
+
|
186
|
+
mock.expect(:call, 1, [category.id])
|
187
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
188
|
+
mock.verify
|
189
|
+
|
190
|
+
mock.expect(:call, 2, [category.id])
|
191
|
+
product.update!(name: "foo")
|
192
|
+
mock.verify
|
193
|
+
|
194
|
+
mock.expect(:call, 3, [category.id])
|
195
|
+
assert_equal 2, Thermos.drink(key: "key", id: category.id)
|
196
|
+
assert_raises(MockExpectationError) { mock.verify }
|
197
|
+
end
|
198
|
+
|
199
|
+
test "does not rebuild the cache for an unrelated has_many through model change" do
|
200
|
+
mock = Minitest::Mock.new
|
201
|
+
category = categories(:baseball)
|
202
|
+
product = Product.create!
|
203
|
+
|
204
|
+
Thermos.fill(key: "key", model: Category, deps: [:products]) do |id|
|
205
|
+
mock.call(id)
|
206
|
+
end
|
207
|
+
|
208
|
+
mock.expect(:call, 1, [category.id])
|
209
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
210
|
+
mock.verify
|
211
|
+
|
212
|
+
mock.expect(:call, 2, [category.id])
|
213
|
+
product.update!(name: "foo")
|
214
|
+
assert_raises(MockExpectationError) { mock.verify }
|
215
|
+
|
216
|
+
mock.expect(:call, 3, [category.id])
|
217
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
218
|
+
assert_raises(MockExpectationError) { mock.verify }
|
219
|
+
end
|
220
|
+
|
221
|
+
test "re-builds the cache for new has_many through records" do
|
222
|
+
mock = Minitest::Mock.new
|
223
|
+
category = categories(:baseball)
|
224
|
+
|
225
|
+
Thermos.fill(key: "key", model: Category, deps: [:products]) do |id|
|
226
|
+
mock.call(id)
|
227
|
+
end
|
228
|
+
|
229
|
+
mock.expect(:call, 1, [category.id])
|
230
|
+
Product.create!(categories: [category])
|
231
|
+
mock.verify
|
232
|
+
|
233
|
+
mock.expect(:call, 2, [category.id])
|
234
|
+
assert_equal 1, Thermos.drink(key: "key", id: category.id)
|
235
|
+
assert_raises(MockExpectationError) { mock.verify }
|
236
|
+
end
|
237
|
+
|
238
|
+
test "re-builds the cache for has_many through record changes when filter condition is met" do
|
239
|
+
mock = Minitest::Mock.new
|
240
|
+
category = categories(:baseball)
|
241
|
+
filter = ->(model) { model.ball? }
|
242
|
+
|
243
|
+
Thermos.fill(
|
244
|
+
key: "key",
|
245
|
+
model: Category,
|
246
|
+
deps: [:products],
|
247
|
+
filter: filter,
|
248
|
+
) { |id| mock.call(id) }
|
249
|
+
|
250
|
+
mock.expect(:call, 1, [category.id])
|
251
|
+
Product.create!(categories: [category])
|
252
|
+
mock.verify
|
253
|
+
|
254
|
+
category.update!(name: "hockey")
|
255
|
+
|
256
|
+
mock.expect(:call, 2, [category.id])
|
257
|
+
Product.create!(categories: [category])
|
258
|
+
assert_raises(MockExpectationError) { mock.verify }
|
259
|
+
end
|
260
|
+
|
261
|
+
test "handles indirect associations" do
|
262
|
+
mock = Minitest::Mock.new
|
263
|
+
category = categories(:baseball)
|
264
|
+
store = category.store
|
265
|
+
|
266
|
+
Thermos.fill(
|
267
|
+
key: "key",
|
268
|
+
model: Store,
|
269
|
+
deps: [categories: [:products]],
|
270
|
+
) { |id| mock.call(id) }
|
271
|
+
|
272
|
+
mock.expect(:call, 1, [store.id])
|
273
|
+
category.update!(name: "foo")
|
274
|
+
mock.verify
|
275
|
+
|
276
|
+
mock.expect(:call, 2, [store.id])
|
277
|
+
assert_equal 1, Thermos.drink(key: "key", id: store.id)
|
278
|
+
assert_raises(MockExpectationError) { mock.verify }
|
279
|
+
Product.create!(categories: [category])
|
280
|
+
mock.verify
|
281
|
+
|
282
|
+
mock.expect(:call, 3, [store.id])
|
283
|
+
assert_equal 2, Thermos.drink(key: "key", id: store.id)
|
284
|
+
assert_raises(MockExpectationError) { mock.verify }
|
285
|
+
end
|
286
|
+
|
287
|
+
test "only rebuilds cache for stated dependencies, even if another cache has an associated model of the primary" do
|
288
|
+
category_mock = Minitest::Mock.new
|
289
|
+
product_mock = Minitest::Mock.new
|
290
|
+
category = categories(:baseball)
|
291
|
+
product = products(:glove)
|
292
|
+
|
293
|
+
Thermos.fill(key: "category_key", model: Category) do |id|
|
294
|
+
category_mock.call(id)
|
295
|
+
end
|
296
|
+
|
297
|
+
Thermos.fill(key: "product_key", model: Product) do |id|
|
298
|
+
product_mock.call(id)
|
299
|
+
end
|
300
|
+
|
301
|
+
category_mock.expect(:call, 2, [category.id])
|
302
|
+
product_mock.expect(:call, 2, [product.id])
|
303
|
+
product.update!(name: "foo")
|
304
|
+
assert_raises(MockExpectationError) { category_mock.verify }
|
305
|
+
product_mock.verify
|
306
|
+
end
|
307
|
+
end
|
@@ -11,12 +11,10 @@ class Category < ActiveRecord::Base
|
|
11
11
|
{
|
12
12
|
name: name,
|
13
13
|
store_name: store.name,
|
14
|
-
category_items:
|
15
|
-
|
16
|
-
name: item.name,
|
17
|
-
|
18
|
-
}
|
19
|
-
end
|
14
|
+
category_items:
|
15
|
+
category_items.map do |item|
|
16
|
+
{ name: item.name, product_name: item.product.name }
|
17
|
+
end,
|
20
18
|
}
|
21
19
|
end
|
22
20
|
end
|
@@ -1,6 +1,6 @@
|
|
1
|
-
require File.expand_path(
|
1
|
+
require File.expand_path("../boot", __FILE__)
|
2
2
|
|
3
|
-
require
|
3
|
+
require "rails/all"
|
4
4
|
|
5
5
|
Bundler.require(*Rails.groups)
|
6
6
|
require "thermos"
|
@@ -10,14 +10,11 @@ module Dummy
|
|
10
10
|
# Settings in config/environments/* take precedence over those specified here.
|
11
11
|
# Application configuration should go into files in config/initializers
|
12
12
|
# -- all .rb files in that directory are automatically loaded.
|
13
|
-
|
14
13
|
# Set Time.zone default to the specified zone and make Active Record auto-convert to this zone.
|
15
14
|
# Run "rake -D time" for a list of tasks for finding time zone names. Default is UTC.
|
16
15
|
# config.time_zone = 'Central Time (US & Canada)'
|
17
|
-
|
18
16
|
# The default locale is :en and all translations from config/locales/*.rb,yml are auto loaded.
|
19
17
|
# config.i18n.load_path += Dir[Rails.root.join('my', 'locales', '*.{rb,yml}').to_s]
|
20
18
|
# config.i18n.default_locale = :de
|
21
19
|
end
|
22
20
|
end
|
23
|
-
|
data/test/dummy/config/boot.rb
CHANGED
@@ -1,5 +1,5 @@
|
|
1
1
|
# Set up gems listed in the Gemfile.
|
2
|
-
ENV[
|
2
|
+
ENV["BUNDLE_GEMFILE"] ||= File.expand_path("../../../../Gemfile", __FILE__)
|
3
3
|
|
4
|
-
require
|
5
|
-
$LOAD_PATH.unshift File.expand_path(
|
4
|
+
require "bundler/setup" if File.exist?(ENV["BUNDLE_GEMFILE"])
|
5
|
+
$LOAD_PATH.unshift File.expand_path("../../../../lib", __FILE__)
|
@@ -10,7 +10,7 @@ Rails.application.configure do
|
|
10
10
|
config.eager_load = false
|
11
11
|
|
12
12
|
# Show full error reports and disable caching.
|
13
|
-
config.consider_all_requests_local
|
13
|
+
config.consider_all_requests_local = true
|
14
14
|
config.action_controller.perform_caching = false
|
15
15
|
|
16
16
|
# Don't care if the mailer can't send.
|
@@ -25,16 +25,16 @@ Rails.application.configure do
|
|
25
25
|
# Debug mode disables concatenation and preprocessing of assets.
|
26
26
|
# This option may cause significant delays in view rendering with a large
|
27
27
|
# number of complex assets.
|
28
|
-
config.assets.debug = true
|
28
|
+
# config.assets.debug = true
|
29
29
|
|
30
30
|
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
31
31
|
# yet still be able to expire them through the digest params.
|
32
|
-
config.assets.digest = true
|
32
|
+
# config.assets.digest = true
|
33
33
|
|
34
34
|
# Adds additional error checking when serving assets at runtime.
|
35
35
|
# Checks for improperly declared sprockets dependencies.
|
36
36
|
# Raises helpful error messages.
|
37
|
-
config.assets.raise_runtime_errors = true
|
37
|
+
# config.assets.raise_runtime_errors = true
|
38
38
|
|
39
39
|
# Raises error for missing translations
|
40
40
|
# config.action_view.raise_on_missing_translations = true
|
@@ -11,7 +11,7 @@ Rails.application.configure do
|
|
11
11
|
config.eager_load = true
|
12
12
|
|
13
13
|
# Full error reports are disabled and caching is turned on.
|
14
|
-
config.consider_all_requests_local
|
14
|
+
config.consider_all_requests_local = false
|
15
15
|
config.action_controller.perform_caching = true
|
16
16
|
|
17
17
|
# Enable Rack::Cache to put a simple HTTP cache in front of your application
|
@@ -22,18 +22,19 @@ Rails.application.configure do
|
|
22
22
|
|
23
23
|
# Disable serving static files from the `/public` folder by default since
|
24
24
|
# Apache or NGINX already handles this.
|
25
|
-
config.serve_static_files = ENV[
|
25
|
+
config.serve_static_files = ENV["RAILS_SERVE_STATIC_FILES"].present?
|
26
26
|
|
27
27
|
# Compress JavaScripts and CSS.
|
28
|
-
config.assets.js_compressor = :uglifier
|
28
|
+
# config.assets.js_compressor = :uglifier
|
29
|
+
|
29
30
|
# config.assets.css_compressor = :sass
|
30
31
|
|
31
32
|
# Do not fallback to assets pipeline if a precompiled asset is missed.
|
32
|
-
config.assets.compile = false
|
33
|
+
# config.assets.compile = false
|
33
34
|
|
34
35
|
# Asset digests allow you to set far-future HTTP expiration dates on all assets,
|
35
36
|
# yet still be able to expire them through the digest params.
|
36
|
-
config.assets.digest = true
|
37
|
+
# config.assets.digest = true
|
37
38
|
|
38
39
|
# `config.assets.precompile` and `config.assets.version` have moved to config/initializers/assets.rb
|
39
40
|
|