much-rails 0.0.1 → 0.2.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.
Files changed (101) hide show
  1. checksums.yaml +4 -4
  2. data/Gemfile +3 -1
  3. data/lib/much-rails.rb +85 -0
  4. data/lib/much-rails/action.rb +415 -0
  5. data/lib/much-rails/action/base_command_result.rb +22 -0
  6. data/lib/much-rails/action/base_result.rb +14 -0
  7. data/lib/much-rails/action/base_router.rb +474 -0
  8. data/lib/much-rails/action/controller.rb +100 -0
  9. data/lib/much-rails/action/head_result.rb +18 -0
  10. data/lib/much-rails/action/redirect_to_result.rb +18 -0
  11. data/lib/much-rails/action/render_result.rb +25 -0
  12. data/lib/much-rails/action/router.rb +101 -0
  13. data/lib/much-rails/action/send_data_result.rb +18 -0
  14. data/lib/much-rails/action/send_file_result.rb +18 -0
  15. data/lib/much-rails/action/unprocessable_entity_result.rb +37 -0
  16. data/lib/much-rails/assets.rb +54 -0
  17. data/lib/much-rails/boolean.rb +7 -0
  18. data/lib/much-rails/call_method.rb +27 -0
  19. data/lib/much-rails/call_method_callbacks.rb +122 -0
  20. data/lib/much-rails/change_action.rb +83 -0
  21. data/lib/much-rails/change_action_result.rb +59 -0
  22. data/lib/much-rails/config.rb +55 -0
  23. data/lib/much-rails/date.rb +50 -0
  24. data/lib/much-rails/decimal.rb +7 -0
  25. data/lib/much-rails/destroy_action.rb +32 -0
  26. data/lib/much-rails/destroy_service.rb +67 -0
  27. data/lib/much-rails/has_slug.rb +7 -0
  28. data/lib/much-rails/input_value.rb +19 -0
  29. data/lib/much-rails/json.rb +29 -0
  30. data/lib/much-rails/layout.rb +142 -0
  31. data/lib/much-rails/layout/helper.rb +25 -0
  32. data/lib/much-rails/mixin.rb +7 -0
  33. data/lib/much-rails/not_given.rb +7 -0
  34. data/lib/much-rails/rails_routes.rb +29 -0
  35. data/lib/much-rails/railtie.rb +39 -0
  36. data/lib/much-rails/records.rb +5 -0
  37. data/lib/much-rails/records/always_destroyable.rb +30 -0
  38. data/lib/much-rails/records/not_destroyable.rb +30 -0
  39. data/lib/much-rails/records/validate_destroy.rb +92 -0
  40. data/lib/much-rails/result.rb +7 -0
  41. data/lib/much-rails/save_action.rb +32 -0
  42. data/lib/much-rails/save_service.rb +68 -0
  43. data/lib/much-rails/service.rb +18 -0
  44. data/lib/much-rails/service_validation_errors.rb +41 -0
  45. data/lib/much-rails/time.rb +28 -0
  46. data/lib/much-rails/version.rb +3 -1
  47. data/lib/much-rails/view_models.rb +3 -0
  48. data/lib/much-rails/view_models/breadcrumb.rb +11 -0
  49. data/lib/much-rails/wrap_and_call_method.rb +41 -0
  50. data/lib/much-rails/wrap_method.rb +45 -0
  51. data/much-rails.gemspec +20 -4
  52. data/test/helper.rb +20 -2
  53. data/test/support/actions/show.rb +11 -0
  54. data/test/support/config/routes/test.rb +3 -0
  55. data/test/support/factory.rb +2 -0
  56. data/test/support/fake_action_controller.rb +63 -0
  57. data/test/unit/action/base_command_result_tests.rb +43 -0
  58. data/test/unit/action/base_result_tests.rb +22 -0
  59. data/test/unit/action/base_router_tests.rb +530 -0
  60. data/test/unit/action/controller_tests.rb +110 -0
  61. data/test/unit/action/head_result_tests.rb +24 -0
  62. data/test/unit/action/redirect_to_result_tests.rb +24 -0
  63. data/test/unit/action/render_result_tests.rb +43 -0
  64. data/test/unit/action/router_tests.rb +252 -0
  65. data/test/unit/action/send_data_result_tests.rb +24 -0
  66. data/test/unit/action/send_file_result_tests.rb +24 -0
  67. data/test/unit/action/unprocessable_entity_result_tests.rb +51 -0
  68. data/test/unit/action_tests.rb +400 -0
  69. data/test/unit/assets_tests.rb +127 -0
  70. data/test/unit/boolean_tests.rb +17 -0
  71. data/test/unit/call_method_callbacks_tests.rb +176 -0
  72. data/test/unit/call_method_tests.rb +62 -0
  73. data/test/unit/change_action_result_tests.rb +113 -0
  74. data/test/unit/change_action_tests.rb +260 -0
  75. data/test/unit/config_tests.rb +68 -0
  76. data/test/unit/date_tests.rb +55 -0
  77. data/test/unit/decimal_tests.rb +17 -0
  78. data/test/unit/destroy_action_tests.rb +83 -0
  79. data/test/unit/destroy_service_tests.rb +238 -0
  80. data/test/unit/has_slug_tests.rb +17 -0
  81. data/test/unit/input_value_tests.rb +34 -0
  82. data/test/unit/json_tests.rb +55 -0
  83. data/test/unit/layout_tests.rb +155 -0
  84. data/test/unit/mixin_tests.rb +17 -0
  85. data/test/unit/much-rails_tests.rb +82 -4
  86. data/test/unit/not_given_tests.rb +17 -0
  87. data/test/unit/rails_routes_tests.rb +28 -0
  88. data/test/unit/records/always_destroyable_tests.rb +43 -0
  89. data/test/unit/records/not_destroyable_tests.rb +40 -0
  90. data/test/unit/records/validate_destroy_tests.rb +252 -0
  91. data/test/unit/result_tests.rb +17 -0
  92. data/test/unit/save_action_tests.rb +83 -0
  93. data/test/unit/save_service_tests.rb +264 -0
  94. data/test/unit/service_tests.rb +33 -0
  95. data/test/unit/service_validation_errors_tests.rb +107 -0
  96. data/test/unit/time_tests.rb +58 -0
  97. data/test/unit/view_models/breadcrumb_tests.rb +53 -0
  98. data/test/unit/wrap_and_call_method_tests.rb +163 -0
  99. data/test/unit/wrap_method_tests.rb +112 -0
  100. metadata +356 -7
  101. data/test/unit/.keep +0 -0
@@ -0,0 +1,260 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "assert"
4
+ require "much-rails/change_action"
5
+
6
+ module MuchRails::ChangeAction
7
+ class UnitTests < Assert::Context
8
+ desc "MuchRails::ChangeAction"
9
+ subject{ unit_class }
10
+
11
+ let(:unit_class){ MuchRails::ChangeAction }
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 do
24
+ include MuchRails::ChangeAction
25
+
26
+ change_result{ MuchRails::Result.success(something: something_value) }
27
+
28
+ on_call{}
29
+
30
+ def something_value
31
+ "SOMETHING VALUE"
32
+ end
33
+
34
+ private
35
+
36
+ def undefined_change_result_block_error_message
37
+ "UNDEFINED CHANGE RESULT BLOCK"
38
+ end
39
+ end
40
+ end
41
+
42
+ should have_imeths :change_result
43
+
44
+ should "be configured as expected" do
45
+ assert_that(subject).includes(MuchRails::Config)
46
+ assert_that(subject).includes(MuchRails::Action)
47
+
48
+ assert_that(subject.much_rails_change_action_config)
49
+ .is_instance_of(
50
+ MuchRails::ChangeAction::MuchRailsChangeActionConfig,
51
+ )
52
+ assert_that(
53
+ subject.much_rails_change_action_config.change_result_block,
54
+ ).is_not_nil
55
+ end
56
+ end
57
+
58
+ class InitTests < ReceiverTests
59
+ desc "when init"
60
+ subject{ receiver_class.new(params: {}) }
61
+ subject do
62
+ receiver_class.new(
63
+ params: {},
64
+ current_user: nil,
65
+ request: nil,
66
+ )
67
+ end
68
+
69
+ setup do
70
+ Assert.stub(subject, :any_unextracted_change_result_validation_errors?) do
71
+ false
72
+ end
73
+ end
74
+
75
+ should have_imeths :change_result
76
+
77
+ should "render the default response" do
78
+ result = subject.call
79
+
80
+ assert_that(result.command_name).equals(:head)
81
+ assert_that(result.command_args).equals([:ok])
82
+ end
83
+ end
84
+
85
+ class RecordErrorsWithResultExceptionTests < InitTests
86
+ desc "with record errors and a result exception"
87
+ subject do
88
+ receiver_class.new(
89
+ params: {},
90
+ current_user: nil,
91
+ request: nil,
92
+ )
93
+ end
94
+
95
+ setup do
96
+ Assert.stub(subject, :any_unextracted_change_result_validation_errors?) do
97
+ true
98
+ end
99
+ Assert.stub(result_exception, :message){ "ERROR MESSAGE" }
100
+ Assert.stub(result_exception, :backtrace){ ["BACKTRACE LINE1"] }
101
+
102
+ Assert.stub(subject, :change_result){ change_result1 }
103
+ end
104
+
105
+ let(:result_exception){ RuntimeError.new }
106
+ let(:change_result1) do
107
+ MuchRails::Result.failure(exception: result_exception)
108
+ end
109
+
110
+ should "raise a MuchRails::Action::ActionError" do
111
+ exception =
112
+ assert_that{ subject.call }.raises(MuchRails::Action::ActionError)
113
+
114
+ assert_that(exception.message).equals("ERROR MESSAGE")
115
+ assert_that(exception.backtrace).equals(["BACKTRACE LINE1"])
116
+ end
117
+ end
118
+
119
+ class RecordErrorsWithNoResultExceptionTests < InitTests
120
+ desc "with record errors and no result exception"
121
+ subject do
122
+ receiver_class.new(
123
+ params: {},
124
+ current_user: nil,
125
+ request: nil,
126
+ )
127
+ end
128
+
129
+ setup do
130
+ Assert.stub(subject, :any_unextracted_change_result_validation_errors?) do
131
+ true
132
+ end
133
+ Assert.stub(subject, :change_result){ change_result1 }
134
+ end
135
+
136
+ let(:change_result1){ MuchRails::Result.failure }
137
+
138
+ should "raise a MuchRails::Action::ActionError" do
139
+ exception =
140
+ assert_that{ subject.call }.raises(MuchRails::Action::ActionError)
141
+
142
+ assert_that(exception.message)
143
+ .equals(
144
+ "#{change_result1.inspect} has validation errors that were not "\
145
+ "handled by the Action: #{change_result1.validation_errors.inspect}.",
146
+ )
147
+ end
148
+ end
149
+
150
+ class ChangeResultMethodTests < InitTests
151
+ desc "#change_result method"
152
+ subject do
153
+ receiver_class.new(
154
+ params: {},
155
+ current_user: nil,
156
+ request: nil,
157
+ )
158
+ end
159
+
160
+ should "memoize and return the expected Result" do
161
+ result = subject.change_result
162
+
163
+ assert_that(result.success?).is_true
164
+ assert_that(result.something).equals("SOMETHING VALUE")
165
+ assert_that(result).is(subject.change_result)
166
+ end
167
+
168
+ should "raise an error when a configured change_result block isn't given" do
169
+ Assert.stub(
170
+ receiver_class.much_rails_change_action_config,
171
+ :change_result_block,
172
+ ){ nil }
173
+ exception =
174
+ assert_that{ subject.change_result }.raises(unit_class::Error)
175
+ assert_that(exception.message).equals("UNDEFINED CHANGE RESULT BLOCK")
176
+ end
177
+ end
178
+
179
+ class AnyUnextractedChangeResultValidationErrorsMethodTests < ReceiverTests
180
+ desc "#any_unextracted_change_result_validation_errors? method"
181
+ subject do
182
+ receiver_class.new(
183
+ params: {},
184
+ current_user: nil,
185
+ request: nil,
186
+ )
187
+ end
188
+
189
+ let(:receiver_class) do
190
+ Class.new do
191
+ include MuchRails::ChangeAction
192
+
193
+ change_result{ MuchRails::Result.success }
194
+ end
195
+ end
196
+
197
+ should "return false" do
198
+ subject.change_result
199
+
200
+ assert_that(subject.any_unextracted_change_result_validation_errors?)
201
+ .is_false
202
+ end
203
+ end
204
+
205
+ class NoValidationErrorsTests <
206
+ AnyUnextractedChangeResultValidationErrorsMethodTests
207
+ desc "with no validation errors"
208
+ subject do
209
+ receiver_class.new(
210
+ params: {},
211
+ current_user: nil,
212
+ request: nil,
213
+ )
214
+ end
215
+
216
+ let(:receiver_class) do
217
+ Class.new do
218
+ include MuchRails::ChangeAction
219
+
220
+ change_result{ MuchRails::Result.failure(validation_errors: {}) }
221
+ end
222
+ end
223
+
224
+ should "return false" do
225
+ subject.change_result
226
+
227
+ assert_that(subject.any_unextracted_change_result_validation_errors?)
228
+ .is_false
229
+ end
230
+ end
231
+
232
+ class ValidationErrorsTests <
233
+ AnyUnextractedChangeResultValidationErrorsMethodTests
234
+ desc "with validation errors"
235
+ subject do
236
+ receiver_class.new(
237
+ params: {},
238
+ current_user: nil,
239
+ request: nil,
240
+ )
241
+ end
242
+
243
+ let(:receiver_class) do
244
+ Class.new do
245
+ include MuchRails::ChangeAction
246
+
247
+ change_result do
248
+ MuchRails::Result.failure(validation_errors: { name: "TEST ERROR" })
249
+ end
250
+ end
251
+ end
252
+
253
+ should "return true" do
254
+ subject.change_result
255
+
256
+ assert_that(subject.any_unextracted_change_result_validation_errors?)
257
+ .is_true
258
+ end
259
+ end
260
+ end
@@ -0,0 +1,68 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "assert"
4
+ require "much-rails/config"
5
+
6
+ module MuchRails::Config
7
+ class UnitTests < Assert::Context
8
+ desc "MuchRails::Config"
9
+ subject{ unit_class }
10
+
11
+ let(:unit_class){ MuchRails::Config }
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
+ setup do
23
+ class receiver_class::Config
24
+ attr_accessor :value
25
+ end
26
+
27
+ class receiver_class::AnotherConfig
28
+ include MuchRails::Config
29
+
30
+ add_instance_config :sub, method_name: :sub
31
+
32
+ attr_accessor :another_value
33
+
34
+ class SubConfig
35
+ attr_accessor :sub_value
36
+ end
37
+ end
38
+ end
39
+
40
+ let(:receiver_class) do
41
+ Class.new do
42
+ include MuchRails::Config
43
+
44
+ add_config
45
+ add_config :another
46
+ end
47
+ end
48
+
49
+ should have_imeths :config, :another_config
50
+
51
+ should "know its attributes" do
52
+ assert_that(subject.config).is_instance_of(subject::Config)
53
+ subject.configure{ |config| config.value = "VALUE 1" }
54
+ assert_that(subject.config.value).equals("VALUE 1")
55
+
56
+ assert_that(subject.another_config).is_instance_of(subject::AnotherConfig)
57
+ subject.configure_another{ |config| config.another_value = "VALUE 2" }
58
+ assert_that(subject.another_config.another_value).equals("VALUE 2")
59
+
60
+ assert_that(subject.another_config.sub)
61
+ .is_instance_of(subject::AnotherConfig::SubConfig)
62
+ subject.another_config.configure_sub do |sub|
63
+ sub.sub_value = "VALUE 3"
64
+ end
65
+ assert_that(subject.another_config.sub.sub_value).equals("VALUE 3")
66
+ end
67
+ end
68
+ end
@@ -0,0 +1,55 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "assert"
4
+ require "much-rails/date"
5
+
6
+ module MuchRails::Date
7
+ class UnitTests < Assert::Context
8
+ desc "MuchRails::Date"
9
+ subject{ unit_class }
10
+
11
+ let(:unit_class){ MuchRails::Date }
12
+
13
+ let(:time){ Time.current }
14
+ let(:date){ time.to_date }
15
+
16
+ should have_imeths :for, :parse, :parse_united_states, :parse8601
17
+
18
+ should "know how to convert date-like representations to Date" do
19
+ # nil, blank value(s)
20
+ # assert_that(subject.for(nil)).is_nil
21
+ ["", " "].each{ |object| assert_that(subject.for(object)).is_nil }
22
+
23
+ # Time, DateTime, or Date
24
+ objects =
25
+ [
26
+ Time.current,
27
+ DateTime.current, # rubocop:disable Style/DateTime
28
+ Date.today,
29
+ ]
30
+
31
+ objects.each do |object|
32
+ assert_that(subject.for(object)).equals(object.to_date)
33
+ end
34
+
35
+ # U.S.-formatted String
36
+ assert_that(subject.for(time.strftime("%m/%d/%Y"))).equals(date)
37
+ assert_that(subject.for(time.strftime("%m.%d.%Y"))).equals(date)
38
+ assert_that(subject.for(time.strftime("%m-%d-%Y %H:%M:%S"))).equals(date)
39
+ assert_that(subject.for(time.iso8601)).equals(date)
40
+
41
+ # iso8601-formatted String
42
+ assert_that(subject.for(time.strftime("%Y-%m-%d"))).equals(date)
43
+ assert_that(subject.for(time.strftime("%Y.%m.%d"))).equals(date)
44
+ assert_that(subject.for(time.strftime("%Y-%m-%d %H:%M:%S"))).equals(date)
45
+ assert_that(subject.for(time.iso8601)).equals(date)
46
+
47
+ # invalid values
48
+ invalid_objects = ["VALUE", 42, Class.new]
49
+ invalid_objects.each do |object|
50
+ assert_that(->{ subject.for(object) })
51
+ .raises(MuchRails::Date::InvalidError)
52
+ end
53
+ end
54
+ end
55
+ end
@@ -0,0 +1,17 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "assert"
4
+ require "much-rails/decimal"
5
+
6
+ module MuchRails::Decimal
7
+ class UnitTests < Assert::Context
8
+ desc "MuchRails::Decimal"
9
+ subject{ unit_class }
10
+
11
+ let(:unit_class){ MuchRails::Decimal }
12
+
13
+ should "be MuchDecimal" do
14
+ assert_that(unit_class).is(MuchDecimal)
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,83 @@
1
+ # frozen_string_literal: true
2
+
3
+ require "assert"
4
+ require "much-rails/destroy_action"
5
+
6
+ module MuchRails::DestroyAction
7
+ class UnitTests < Assert::Context
8
+ desc "MuchRails::DestroyAction"
9
+ subject{ unit_class }
10
+
11
+ let(:unit_class){ MuchRails::DestroyAction }
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
+ setup do
23
+ Assert.stub_on_call(receiver_class, :change_result) do |call|
24
+ @change_action_class_change_result_call = call
25
+ end
26
+ end
27
+
28
+ let(:receiver_class) do
29
+ Class.new do
30
+ include MuchRails::DestroyAction
31
+
32
+ destroy_result{ MuchRails::Result.success }
33
+
34
+ on_call{}
35
+ end
36
+ end
37
+
38
+ should have_imeths :destroy_result
39
+
40
+ should "be configured as expected" do
41
+ assert_that(subject).includes(MuchRails::ChangeAction)
42
+ end
43
+
44
+ should "call .change_result for its .destroy_result method" do
45
+ subject.destroy_result
46
+
47
+ assert_that(@change_action_class_change_result_call).is_not_nil
48
+ end
49
+ end
50
+
51
+ class InitTests < ReceiverTests
52
+ desc "when init"
53
+ subject do
54
+ receiver_class.new(
55
+ params: {},
56
+ current_user: nil,
57
+ request: nil,
58
+ )
59
+ end
60
+
61
+ should have_imeths :destroy_result
62
+
63
+ should "call #change_result for its #destroy_result method" do
64
+ Assert.stub_on_call(subject, :change_result) do |call|
65
+ @change_action_instance_change_result_call = call
66
+ end
67
+
68
+ subject.destroy_result
69
+ assert_that(@change_action_instance_change_result_call).is_not_nil
70
+ end
71
+
72
+ should "raise a custom error message if no destroy result block defined" do
73
+ Assert.stub(
74
+ receiver_class.much_rails_change_action_config,
75
+ :change_result_block,
76
+ ){ nil }
77
+
78
+ exception = assert_that{ subject.destroy_result }.raises
79
+ assert_that(exception.message)
80
+ .equals("A `destroy_result` block must be defined.")
81
+ end
82
+ end
83
+ end