much-rails 0.1.3 → 0.2.4
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/much-rails.rb +9 -0
- data/lib/much-rails/abstract_class.rb +38 -0
- data/lib/much-rails/action/base_router.rb +10 -10
- data/lib/much-rails/action/router.rb +10 -4
- data/lib/much-rails/assets.rb +33 -18
- data/lib/much-rails/destroy_service.rb +42 -5
- data/lib/much-rails/records/validate_destroy.rb +23 -13
- data/lib/much-rails/save_service.rb +44 -7
- data/lib/much-rails/service_validation_errors.rb +41 -0
- data/lib/much-rails/version.rb +1 -1
- data/much-rails.gemspec +1 -1
- data/test/unit/abstract_class_tests.rb +45 -0
- data/test/unit/action/base_router_tests.rb +10 -10
- data/test/unit/action/router_tests.rb +4 -4
- data/test/unit/assets_tests.rb +46 -14
- data/test/unit/destroy_service_tests.rb +165 -21
- data/test/unit/much-rails_tests.rb +42 -1
- data/test/unit/records/always_destroyable_tests.rb +1 -1
- data/test/unit/records/not_destroyable_tests.rb +1 -1
- data/test/unit/records/validate_destroy_tests.rb +84 -4
- data/test/unit/save_service_tests.rb +180 -20
- data/test/unit/service_validation_errors_tests.rb +107 -0
- metadata +10 -4
data/lib/much-rails/version.rb
CHANGED
data/much-rails.gemspec
CHANGED
@@ -29,7 +29,7 @@ Gem::Specification.new do |gem|
|
|
29
29
|
|
30
30
|
gem.add_dependency("activerecord", ["> 5.0", "< 7.0"])
|
31
31
|
gem.add_dependency("activesupport", ["> 5.0", "< 7.0"])
|
32
|
-
gem.add_dependency("dassets", ["~> 0.15.
|
32
|
+
gem.add_dependency("dassets", ["~> 0.15.2"])
|
33
33
|
gem.add_dependency("dassets-erubi", ["~> 0.1.1"])
|
34
34
|
gem.add_dependency("dassets-sass", ["~> 0.5.1"])
|
35
35
|
gem.add_dependency("much-boolean", ["~> 0.2.1"])
|
@@ -0,0 +1,45 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "assert"
|
4
|
+
require "much-rails/abstract_class"
|
5
|
+
|
6
|
+
module MuchRails::AbstractClassTest
|
7
|
+
class UnitTests < Assert::Context
|
8
|
+
desc "MuchRails::AbstractClass"
|
9
|
+
subject{ unit_class }
|
10
|
+
|
11
|
+
let(:unit_class){ MuchRails::AbstractClass }
|
12
|
+
|
13
|
+
should "include MuchRails::Mixin" do
|
14
|
+
assert_that(subject).includes(MuchRails::Mixin)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class ReceiverTests < UnitTests
|
19
|
+
desc "receiver"
|
20
|
+
subject{ receiver_class }
|
21
|
+
|
22
|
+
let(:receiver_class) do
|
23
|
+
Class.new.tap{ |c| c.include unit_class }
|
24
|
+
end
|
25
|
+
let(:receiver_subclass) do
|
26
|
+
Class.new(receiver_class)
|
27
|
+
end
|
28
|
+
|
29
|
+
should have_accessor :abstract_class
|
30
|
+
should have_imeths :new, :abstract_class?
|
31
|
+
|
32
|
+
should "know if it is an abstract class or not" do
|
33
|
+
assert_that(subject.abstract_class?).equals(true)
|
34
|
+
assert_that(receiver_subclass.abstract_class?).equals(false)
|
35
|
+
end
|
36
|
+
|
37
|
+
should "prevent calling .new on the receiver" do
|
38
|
+
assert_that{ subject.new }.raises(NotImplementedError)
|
39
|
+
end
|
40
|
+
|
41
|
+
should "allow calling .new on subclasses of the receiver" do
|
42
|
+
assert_that(receiver_subclass.new).is_a?(subject)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
@@ -80,13 +80,13 @@ class MuchRails::Action::BaseRouter
|
|
80
80
|
end
|
81
81
|
|
82
82
|
should "build path/URL strings for named URLs" do
|
83
|
-
path_string = subject.path_for(:url1,
|
83
|
+
path_string = subject.path_for(:url1, test: "args")
|
84
84
|
assert_that(path_string).equals("TEST PATH STRING")
|
85
|
-
assert_that(@url_set_path_for_call.args).equals([:url1,
|
85
|
+
assert_that(@url_set_path_for_call.args).equals([:url1, { test: "args" }])
|
86
86
|
|
87
|
-
url_string = subject.url_for(:url1,
|
87
|
+
url_string = subject.url_for(:url1, test: "args")
|
88
88
|
assert_that(url_string).equals("TEST URL STRING")
|
89
|
-
assert_that(@url_set_url_for_call.args).equals([:url1,
|
89
|
+
assert_that(@url_set_url_for_call.args).equals([:url1, { test: "args" }])
|
90
90
|
end
|
91
91
|
|
92
92
|
should "define request types" do
|
@@ -380,13 +380,13 @@ class MuchRails::Action::BaseRouter
|
|
380
380
|
|
381
381
|
subject.add(:url1, Factory.url)
|
382
382
|
|
383
|
-
path_string = subject.path_for(:url1,
|
383
|
+
path_string = subject.path_for(:url1, test: "args")
|
384
384
|
assert_that(path_string).equals("TEST PATH STRING")
|
385
|
-
assert_that(@url_path_for_call.args).equals([
|
385
|
+
assert_that(@url_path_for_call.args).equals([{ test: "args" }])
|
386
386
|
|
387
|
-
url_string = subject.url_for(:url1,
|
387
|
+
url_string = subject.url_for(:url1, test: "args")
|
388
388
|
assert_that(url_string).equals("TEST URL STRING")
|
389
|
-
assert_that(@url_url_for_call.args).equals([
|
389
|
+
assert_that(@url_url_for_call.args).equals([{ test: "args" }])
|
390
390
|
end
|
391
391
|
end
|
392
392
|
|
@@ -450,8 +450,8 @@ class MuchRails::Action::BaseRouter
|
|
450
450
|
assert_that(subject.path)
|
451
451
|
.equals(base_url_class.url_path(router1, url_path1))
|
452
452
|
|
453
|
-
assert_that{ subject.path_for(
|
454
|
-
assert_that{ subject.url_for(
|
453
|
+
assert_that{ subject.path_for(test: "args") }.raises(NotImplementedError)
|
454
|
+
assert_that{ subject.url_for(test: "args") }.raises(NotImplementedError)
|
455
455
|
end
|
456
456
|
end
|
457
457
|
|
@@ -206,15 +206,15 @@ class MuchRails::Action::Router
|
|
206
206
|
should have_imeths :path_for, :url_for
|
207
207
|
|
208
208
|
should "know its attributes" do
|
209
|
-
path_string = subject.path_for(
|
209
|
+
path_string = subject.path_for(test: "args")
|
210
210
|
assert_that(path_string).equals("TEST PATH OR URL STRING")
|
211
211
|
assert_that(@rails_routes_method_missing_call.args)
|
212
|
-
.equals(["#{url_name1}_path".to_sym,
|
212
|
+
.equals(["#{url_name1}_path".to_sym, { test: "args" }])
|
213
213
|
|
214
|
-
url_string = subject.url_for(
|
214
|
+
url_string = subject.url_for(test: "args")
|
215
215
|
assert_that(url_string).equals("TEST PATH OR URL STRING")
|
216
216
|
assert_that(@rails_routes_method_missing_call.args)
|
217
|
-
.equals(["#{url_name1}_url".to_sym,
|
217
|
+
.equals(["#{url_name1}_url".to_sym, { test: "args" }])
|
218
218
|
end
|
219
219
|
end
|
220
220
|
|
data/test/unit/assets_tests.rb
CHANGED
@@ -23,7 +23,7 @@ module MuchRails::Assets
|
|
23
23
|
setup do
|
24
24
|
subject.reset
|
25
25
|
|
26
|
-
in_development_env =
|
26
|
+
in_development_env = true
|
27
27
|
Assert.stub(FakeRails.env, :development?){ in_development_env }
|
28
28
|
Assert.stub(FakeRails.env, :test?){ !in_development_env }
|
29
29
|
|
@@ -34,14 +34,11 @@ module MuchRails::Assets
|
|
34
34
|
subject.configure_for_rails(FakeRails)
|
35
35
|
end
|
36
36
|
|
37
|
-
should "configure the fingerprint cache to use
|
37
|
+
should "configure the fingerprint/content cache to use no cache" do
|
38
38
|
assert_that(subject.config.fingerprint_cache)
|
39
|
-
.is_instance_of(subject::
|
40
|
-
end
|
41
|
-
|
42
|
-
should "configure the content cache to use a memory cache" do
|
39
|
+
.is_instance_of(subject::NoCache)
|
43
40
|
assert_that(subject.config.content_cache)
|
44
|
-
.is_instance_of(subject::
|
41
|
+
.is_instance_of(subject::NoCache)
|
45
42
|
end
|
46
43
|
|
47
44
|
should "not configure a file store" do
|
@@ -49,16 +46,14 @@ module MuchRails::Assets
|
|
49
46
|
.is_not_equal_to(FakeRails.root.join("public"))
|
50
47
|
end
|
51
48
|
|
52
|
-
should "configure the app's app/assets folder as a source" do
|
49
|
+
should "configure the app's app/assets/css folder as a source" do
|
53
50
|
source =
|
54
51
|
subject.config.sources.detect do |source|
|
55
|
-
source.path == FakeRails.root.join("app", "assets").to_s
|
52
|
+
source.path == FakeRails.root.join("app", "assets", "css").to_s
|
56
53
|
end
|
57
54
|
|
58
55
|
assert_that(source).is_not_nil
|
59
|
-
assert_that(source.
|
60
|
-
assert_that(source.engines["js"].first)
|
61
|
-
.is_instance_of(subject::Erubi::Engine)
|
56
|
+
assert_that(source.base_path).equals("css")
|
62
57
|
assert_that(source.engines["scss"].size).equals(2)
|
63
58
|
assert_that(source.engines["scss"].first)
|
64
59
|
.is_instance_of(subject::Erubi::Engine)
|
@@ -66,6 +61,41 @@ module MuchRails::Assets
|
|
66
61
|
.is_instance_of(subject::Sass::Engine)
|
67
62
|
end
|
68
63
|
|
64
|
+
should "configure the app's app/assets/img folder as a source" do
|
65
|
+
source =
|
66
|
+
subject.config.sources.detect do |source|
|
67
|
+
source.path == FakeRails.root.join("app", "assets", "img").to_s
|
68
|
+
end
|
69
|
+
|
70
|
+
assert_that(source).is_not_nil
|
71
|
+
assert_that(source.base_path).equals("img")
|
72
|
+
assert_that(source.engines.empty?).is_true
|
73
|
+
end
|
74
|
+
|
75
|
+
should "configure the app's app/assets/js folder as a source" do
|
76
|
+
source =
|
77
|
+
subject.config.sources.detect do |source|
|
78
|
+
source.path == FakeRails.root.join("app", "assets", "js").to_s
|
79
|
+
end
|
80
|
+
|
81
|
+
assert_that(source).is_not_nil
|
82
|
+
assert_that(source.base_path).equals("js")
|
83
|
+
assert_that(source.engines["js"].size).equals(1)
|
84
|
+
assert_that(source.engines["js"].first)
|
85
|
+
.is_instance_of(subject::Erubi::Engine)
|
86
|
+
end
|
87
|
+
|
88
|
+
should "configure the app's app/assets/vendor folder as a source" do
|
89
|
+
source =
|
90
|
+
subject.config.sources.detect do |source|
|
91
|
+
source.path == FakeRails.root.join("app", "assets", "vendor").to_s
|
92
|
+
end
|
93
|
+
|
94
|
+
assert_that(source).is_not_nil
|
95
|
+
assert_that(source.base_path).equals("vendor")
|
96
|
+
assert_that(source.engines.empty?).is_true
|
97
|
+
end
|
98
|
+
|
69
99
|
should "initialize itself" do
|
70
100
|
assert_that(@init_call).is_not_nil
|
71
101
|
end
|
@@ -84,9 +114,11 @@ module MuchRails::Assets
|
|
84
114
|
subject.configure_for_rails(FakeRails)
|
85
115
|
end
|
86
116
|
|
87
|
-
should "configure the content cache to use
|
117
|
+
should "configure the fingerprint/content cache to use a memory cache" do
|
118
|
+
assert_that(subject.config.fingerprint_cache)
|
119
|
+
.is_instance_of(subject::MemCache)
|
88
120
|
assert_that(subject.config.content_cache)
|
89
|
-
.is_instance_of(subject::
|
121
|
+
.is_instance_of(subject::MemCache)
|
90
122
|
end
|
91
123
|
|
92
124
|
should "configure a file store for the app's public folder" do
|
@@ -44,45 +44,189 @@ module MuchRails::DestroyService
|
|
44
44
|
end
|
45
45
|
end
|
46
46
|
|
47
|
-
class
|
48
|
-
desc "
|
47
|
+
class ReceiverInitTests < ReceiverTests
|
48
|
+
desc "when init"
|
49
|
+
subject{ receiver_class.new(exception: exception) }
|
50
|
+
|
51
|
+
let(:exception){ nil }
|
52
|
+
end
|
53
|
+
|
54
|
+
class ReceiverInitAroundCallCallbackTests < ReceiverInitTests
|
55
|
+
desc "around_call callback"
|
56
|
+
setup do
|
57
|
+
Assert.stub(
|
58
|
+
MuchRails::DestroyService::ValidationErrors,
|
59
|
+
:exception_classes,
|
60
|
+
){ exception_classes }
|
61
|
+
Assert.stub_on_call(
|
62
|
+
MuchRails::DestroyService::ValidationErrors,
|
63
|
+
:result_for,
|
64
|
+
) do |call|
|
65
|
+
@result_for_call = call
|
66
|
+
validation_error_result
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
let(:exception){ exceptions.sample }
|
71
|
+
let(:exceptions) do
|
72
|
+
[
|
73
|
+
RuntimeError.new(Factory.string),
|
74
|
+
ArgumentError.new(Factory.string),
|
75
|
+
MuchRails::Records::DestructionInvalid.new(FakeRecord.new),
|
76
|
+
]
|
77
|
+
end
|
78
|
+
let(:exception_classes){ exceptions.map(&:class) }
|
79
|
+
let(:validation_error_result) do
|
80
|
+
MuchResult.failure(error: result_error_message)
|
81
|
+
end
|
82
|
+
let(:result_error_message){ Factory.string }
|
83
|
+
|
84
|
+
should "rescue raised exceptions and "\
|
85
|
+
"use the ValidationErrors to build a result" do
|
86
|
+
result = subject.call
|
87
|
+
|
88
|
+
assert_that(result.failure?).is_true
|
89
|
+
assert_that(result.error).equals(result_error_message)
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
class ValidationErrorsTests < UnitTests
|
94
|
+
desc "ValidationErrors"
|
95
|
+
subject{ unit_class::ValidationErrors }
|
96
|
+
|
97
|
+
should have_imeths :add, :exception_classes, :result_for
|
98
|
+
should have_imeths :service_validation_errors
|
99
|
+
|
100
|
+
should "know its ServiceValidationErrors" do
|
101
|
+
assert_that(subject.service_validation_errors)
|
102
|
+
.is_an_instance_of(MuchRails::ServiceValidationErrors)
|
103
|
+
assert_that(subject.service_validation_errors.exception_classes)
|
104
|
+
.includes(MuchRails::Records::DestructionInvalid)
|
105
|
+
end
|
106
|
+
end
|
107
|
+
|
108
|
+
class ValidationErrorsAddTests < ValidationErrorsTests
|
109
|
+
desc ".add"
|
110
|
+
|
111
|
+
setup do
|
112
|
+
Assert.stub_on_call(subject.service_validation_errors, :add) do |call|
|
113
|
+
@add_call = call
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
let(:exception_class){ StandardError }
|
118
|
+
let(:block){ proc{ MuchResult.failure } }
|
119
|
+
|
120
|
+
should "call #add on its ServiceValidationErrors" do
|
121
|
+
subject.add(exception_class, &block)
|
122
|
+
assert_that(@add_call.args).equals([exception_class])
|
123
|
+
assert_that(@add_call.block).is(block)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
class ValidationErrorsExceptionClassesTests < ValidationErrorsTests
|
128
|
+
desc ".exception_classes"
|
129
|
+
|
49
130
|
setup do
|
50
|
-
Assert.stub(
|
131
|
+
Assert.stub(
|
132
|
+
subject.service_validation_errors,
|
133
|
+
:exception_classes,
|
134
|
+
){ exception_classes }
|
135
|
+
end
|
136
|
+
|
137
|
+
let(:exception_classes) do
|
138
|
+
[
|
139
|
+
StandardError,
|
140
|
+
ArgumentError,
|
141
|
+
]
|
51
142
|
end
|
52
143
|
|
53
|
-
|
54
|
-
|
144
|
+
should "call #exception_classes on its ServiceValidationErrors" do
|
145
|
+
assert_that(subject.exception_classes).is(exception_classes)
|
55
146
|
end
|
56
147
|
end
|
57
148
|
|
58
|
-
class
|
59
|
-
|
60
|
-
desc "with an exception record that has destruction_error_messages"
|
149
|
+
class ValidationErrorsResultForTests < ValidationErrorsTests
|
150
|
+
desc ".result_for"
|
61
151
|
|
62
|
-
|
152
|
+
setup do
|
153
|
+
Assert.stub_on_call(
|
154
|
+
subject.service_validation_errors,
|
155
|
+
:result_for,
|
156
|
+
) do |call|
|
157
|
+
@result_for_call = call
|
158
|
+
result_for_result
|
159
|
+
end
|
160
|
+
end
|
63
161
|
|
64
|
-
|
65
|
-
|
162
|
+
let(:exception){ StandardError.new(Factory.string) }
|
163
|
+
let(:result_for_result){ MuchResult.failure }
|
164
|
+
|
165
|
+
should "call #result_for on its ServiceValidationErrors" do
|
166
|
+
assert_that(subject.result_for(exception)).is(result_for_result)
|
167
|
+
assert_that(@result_for_call.args).equals([exception])
|
168
|
+
end
|
169
|
+
end
|
170
|
+
|
171
|
+
class ValidationErrorsResultForDestructionInvalidTests < ValidationErrorsTests
|
172
|
+
desc "when .result_for is passed an MuchRails::Records::DestructionInvalid"
|
173
|
+
|
174
|
+
let(:exception){ MuchRails::Records::DestructionInvalid.new(record) }
|
175
|
+
let(:record){ FakeRecord.new }
|
176
|
+
|
177
|
+
should "return a failure result with the record and validation errors" do
|
178
|
+
result = subject.result_for(exception)
|
66
179
|
|
67
180
|
assert_that(result.failure?).is_true
|
68
181
|
assert_that(result.exception).equals(exception)
|
69
|
-
assert_that(result.validation_errors).equals(exception.
|
182
|
+
assert_that(result.validation_errors).equals(exception.errors.to_h)
|
183
|
+
assert_that(result.validation_error_messages)
|
184
|
+
.equals(exception.error_full_messages.to_a)
|
70
185
|
end
|
71
186
|
end
|
72
187
|
|
73
|
-
class
|
74
|
-
|
75
|
-
|
188
|
+
class FailureResultTests < UnitTests
|
189
|
+
desc "FailureResult"
|
190
|
+
subject{ unit_class::FailureResult }
|
191
|
+
|
192
|
+
setup do
|
193
|
+
Assert.stub_tap_on_call(MuchResult, :failure) do |_, call|
|
194
|
+
@much_result_failure_call = call
|
195
|
+
end
|
196
|
+
end
|
76
197
|
|
77
|
-
let(:
|
198
|
+
let(:exception){ StandardError.new(Factory.string) }
|
199
|
+
let(:validation_errors){ { Factory.symbol => Factory.string } }
|
200
|
+
let(:custom_value){ Factory.string }
|
78
201
|
|
79
|
-
should
|
80
|
-
"validation_errors" do
|
81
|
-
result = subject.call(exception: exception)
|
202
|
+
should have_imeths :new
|
82
203
|
|
204
|
+
should "use MuchResult.failure to build a result" do
|
205
|
+
result =
|
206
|
+
subject.new(
|
207
|
+
exception: exception,
|
208
|
+
validation_errors: validation_errors,
|
209
|
+
custom: custom_value,
|
210
|
+
)
|
83
211
|
assert_that(result.failure?).is_true
|
84
|
-
assert_that(
|
85
|
-
|
212
|
+
assert_that(@much_result_failure_call.kargs)
|
213
|
+
.equals(
|
214
|
+
exception: exception,
|
215
|
+
validation_errors: validation_errors,
|
216
|
+
custom: custom_value,
|
217
|
+
)
|
218
|
+
end
|
219
|
+
|
220
|
+
should "raise an error without an exception or validation errors" do
|
221
|
+
assert_that{
|
222
|
+
subject.new(validation_errors: validation_errors)
|
223
|
+
}.raises(ArgumentError)
|
224
|
+
end
|
225
|
+
|
226
|
+
should "raise an error without an exception or validation errors" do
|
227
|
+
assert_that{
|
228
|
+
subject.new(exception: exception)
|
229
|
+
}.raises(ArgumentError)
|
86
230
|
end
|
87
231
|
end
|
88
232
|
|
@@ -23,10 +23,51 @@ module MuchRails
|
|
23
23
|
desc ".config"
|
24
24
|
subject{ unit_class.config }
|
25
25
|
|
26
|
-
should have_imeths :action
|
26
|
+
should have_imeths :action, :layout
|
27
|
+
should have_imeths :add_save_service_validation_error
|
28
|
+
should have_imeths :add_destroy_service_validation_error
|
27
29
|
|
28
30
|
should "be configured as expected" do
|
29
31
|
assert_that(subject.action).is_not_nil
|
32
|
+
assert_that(subject.layout).is_not_nil
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class ConfigServiceValidationErrorTests < ConfigTests
|
37
|
+
setup do
|
38
|
+
Assert.stub_on_call(
|
39
|
+
MuchRails::SaveService::ValidationErrors,
|
40
|
+
:add,
|
41
|
+
) do |call|
|
42
|
+
@save_service_validation_errors_add_call = call
|
43
|
+
end
|
44
|
+
Assert.stub_on_call(
|
45
|
+
MuchRails::DestroyService::ValidationErrors,
|
46
|
+
:add,
|
47
|
+
) do |call|
|
48
|
+
@destroy_service_validation_errors_add_call = call
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
let(:exception_class){ StandardError }
|
53
|
+
let(:block){ proc{ MuchResult.failure } }
|
54
|
+
|
55
|
+
should "know how to add an exception class "\
|
56
|
+
"to the save service validation errors" do
|
57
|
+
subject.add_save_service_validation_error(exception_class, &block)
|
58
|
+
assert_that(@save_service_validation_errors_add_call.args)
|
59
|
+
.equals([exception_class])
|
60
|
+
assert_that(@save_service_validation_errors_add_call.block)
|
61
|
+
.is(block)
|
62
|
+
end
|
63
|
+
|
64
|
+
should "know how to add an exception class "\
|
65
|
+
"to the destroy service validation errors" do
|
66
|
+
subject.add_destroy_service_validation_error(exception_class, &block)
|
67
|
+
assert_that(@destroy_service_validation_errors_add_call.args)
|
68
|
+
.equals([exception_class])
|
69
|
+
assert_that(@destroy_service_validation_errors_add_call.block)
|
70
|
+
.is(block)
|
30
71
|
end
|
31
72
|
end
|
32
73
|
|