trailblazer 1.1.1 → 2.1.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 +5 -5
- data/.gitignore +1 -0
- data/.rubocop-https---raw-githubusercontent-com-trailblazer-meta-master-rubocop-yml +101 -0
- data/.rubocop.yml +20 -0
- data/.rubocop_todo.yml +556 -0
- data/.travis.yml +6 -7
- data/CHANGES.md +224 -0
- data/COMM-LICENSE +62 -0
- data/CONTRIBUTING.md +179 -0
- data/Gemfile +0 -10
- data/LICENSE +9 -0
- data/README.md +68 -189
- data/Rakefile +3 -3
- data/lib/trailblazer/version.rb +3 -1
- data/lib/trailblazer.rb +3 -6
- data/test/test_helper.rb +32 -3
- data/trailblazer.gemspec +11 -15
- metadata +28 -132
- data/LICENSE.txt +0 -22
- data/TODO.md +0 -11
- data/doc/Trb-The-Stack.png +0 -0
- data/doc/trb.jpg +0 -0
- data/gemfiles/Gemfile.rails.lock +0 -130
- data/gemfiles/Gemfile.reform-2.0 +0 -6
- data/gemfiles/Gemfile.reform-2.1 +0 -7
- data/lib/trailblazer/autoloading.rb +0 -15
- data/lib/trailblazer/endpoint.rb +0 -31
- data/lib/trailblazer/operation/builder.rb +0 -26
- data/lib/trailblazer/operation/callback.rb +0 -53
- data/lib/trailblazer/operation/collection.rb +0 -6
- data/lib/trailblazer/operation/controller.rb +0 -72
- data/lib/trailblazer/operation/dispatch.rb +0 -3
- data/lib/trailblazer/operation/model/dsl.rb +0 -29
- data/lib/trailblazer/operation/model/external.rb +0 -34
- data/lib/trailblazer/operation/model.rb +0 -50
- data/lib/trailblazer/operation/module.rb +0 -29
- data/lib/trailblazer/operation/policy/guard.rb +0 -35
- data/lib/trailblazer/operation/policy.rb +0 -85
- data/lib/trailblazer/operation/representer.rb +0 -98
- data/lib/trailblazer/operation/resolver.rb +0 -30
- data/lib/trailblazer/operation/uploaded_file.rb +0 -77
- data/lib/trailblazer/operation.rb +0 -175
- data/test/callback_test.rb +0 -104
- data/test/collection_test.rb +0 -57
- data/test/model_test.rb +0 -148
- data/test/module_test.rb +0 -93
- data/test/operation/builder_test.rb +0 -41
- data/test/operation/contract_test.rb +0 -30
- data/test/operation/controller_test.rb +0 -111
- data/test/operation/dsl/callback_test.rb +0 -118
- data/test/operation/dsl/contract_test.rb +0 -104
- data/test/operation/dsl/representer_test.rb +0 -142
- data/test/operation/external_model_test.rb +0 -71
- data/test/operation/guard_test.rb +0 -152
- data/test/operation/policy_test.rb +0 -97
- data/test/operation/reject_test.rb +0 -34
- data/test/operation/resolver_test.rb +0 -83
- data/test/operation_test.rb +0 -275
- data/test/representer_test.rb +0 -238
- data/test/rollback_test.rb +0 -47
data/README.md
CHANGED
@@ -1,25 +1,34 @@
|
|
1
1
|
# Trailblazer
|
2
2
|
|
3
|
-
_Trailblazer
|
3
|
+
_Trailblazer provides new high-level abstractions for Ruby frameworks. It gently enforces encapsulation, an intuitive code structure and approaches the modeling of complex business workflows with a functional mind-set._
|
4
4
|
|
5
5
|
[](https://gitter.im/trailblazer/chat)
|
6
6
|
[](http://trailblazer.to/newsletter/)
|
7
7
|
[](http://badge.fury.io/rb/trailblazer)
|
8
|
+
[](https://www.codetriage.com/trailblazer/trailblazer)
|
8
9
|
|
10
|
+
## Documentation
|
11
|
+
|
12
|
+
**This document discusses Trailblazer 2.1.** An overview about the additions are [on our website](http://2019.trailblazer.to/2.1/docs/trailblazer.html#trailblazer-2-1-migration).
|
13
|
+
|
14
|
+
We're working on several new example applications!
|
15
|
+
|
16
|
+
* *Refactoring to Trailblazer* discusses how the cfp-app is converted into a TRB app.
|
17
|
+
* *BPMN and workflows* shows in-detail how the new 2.1 features in Trailblazer are used.
|
18
|
+
|
19
|
+
The [1.x documentation is here](http://trailblazer.to/gems/operation/1.1/).
|
9
20
|
|
10
21
|
## Trailblazer In A Nutshell
|
11
22
|
|
12
23
|
1. All business logic is encapsulated in [operations](#operation) (service objects).
|
13
|
-
* An optional Reform [form](#validations) object in the operation deserializes and validates input. The form object can also be used for rendering.
|
14
|
-
* An optional [policy](#policies) object blocks unauthorized users from running the operation.
|
15
|
-
* Optional [callback](#callbacks) objects allow declaring post-processing logic.
|
16
24
|
3. [Controllers](#controllers) instantly delegate to an operation. No business code in controllers, only HTTP-specific logic.
|
17
25
|
4. [Models](#models) are persistence-only and solely define associations and scopes. No business code is to be found here. No validations, no callbacks.
|
18
26
|
5. The presentation layer offers optional [view models](#views) (Cells) and [representers](#representers) for document APIs.
|
27
|
+
6. More complex business flows and life-cycles are modeled using workflows.
|
19
28
|
|
20
29
|
Trailblazer is designed to handle different contexts like user roles by applying [inheritance](#inheritance) between and [composing](#composing) of operations, form objects, policies, representers and callbacks.
|
21
30
|
|
22
|
-
|
31
|
+
Want code? Jump [right here](#controllers)!
|
23
32
|
|
24
33
|
## Mission
|
25
34
|
|
@@ -31,36 +40,33 @@ Again, you can pick which layers you want. Trailblazer doesn't impose technical
|
|
31
40
|
|
32
41
|
Trailblazer is no "complex web of objects and indirection". It solves many problems that have been around for years with a cleanly layered architecture. Only use what you like. And that's the bottom line.
|
33
42
|
|
34
|
-
##
|
35
|
-
|
36
|
-
Since Trailblazer decouples the High-Level Stack from the framework, it runs with virtually any Ruby framework. We are constantly working on documenting how to do that.
|
37
|
-
|
38
|
-
* Trailblazer with Rails [Book](http://trailblazer.to/books/trailblazer.html) | [Repository](https://github.com/apotonick/gemgem-trbrb)
|
39
|
-
* Trailblazer with Sinatra [Guide](http://trailblazer.to/guides/sinatra/getting-started.html) | [Repository](https://github.com/apotonick/gemgem-sinatra)
|
40
|
-
* Trailblazer with Hanami - coming soon!
|
41
|
-
* Trailblazer with Roda - coming soon!
|
42
|
-
* Trailblazer with Grape - coming _very_ soon!
|
43
|
+
## Concepts over Technology
|
43
44
|
|
44
|
-
|
45
|
-
## A Concept-Driven OOP Framework
|
46
|
-
|
47
|
-
Trailblazer offers you a new, more intuitive file layout in Rails apps where you structure files by *concepts*.
|
45
|
+
Trailblazer offers you a new, more intuitive file layout in applications.
|
48
46
|
|
49
47
|
```
|
50
48
|
app
|
51
49
|
├── concepts
|
52
|
-
│ ├──
|
53
|
-
│ │ ├──
|
54
|
-
│ │ ├──
|
50
|
+
│ ├── song
|
51
|
+
│ │ ├── operation
|
52
|
+
│ │ │ ├── create.rb
|
53
|
+
│ │ │ ├── update.rb
|
54
|
+
│ │ ├── contract
|
55
|
+
│ │ │ ├── create.rb
|
56
|
+
│ │ │ ├── update.rb
|
57
|
+
│ │ ├── cell
|
58
|
+
│ │ │ ├── show.rb
|
59
|
+
│ │ │ ├── index.rb
|
60
|
+
│ │ ├── view
|
55
61
|
│ │ │ ├── show.haml
|
56
|
-
│ │ │ ├──
|
57
|
-
│ │ ├──
|
58
|
-
│ │ │ ├── comment.css.sass
|
59
|
-
│ │ ├── operation.rb
|
60
|
-
│ │ ├── twin.rb
|
62
|
+
│ │ │ ├── index.rb
|
63
|
+
│ │ │ ├── song.css.sass
|
61
64
|
```
|
62
65
|
|
63
|
-
|
66
|
+
Instead of grouping by technology, classes and views are structured by *concept*, and then by technology. A concept can relate to a model, or can be a completely abstract concern such as `invoicing`.
|
67
|
+
|
68
|
+
Within a concept, you can have any level of nesting. For example, `invoicing/pdf/` could be one.
|
69
|
+
|
64
70
|
|
65
71
|
## Architecture
|
66
72
|
|
@@ -68,7 +74,7 @@ Trailblazer extends the conventional MVC stack in Rails. Keep in mind that addin
|
|
68
74
|
|
69
75
|
The opposite is the case: Controller, view and model become lean endpoints for HTTP, rendering and persistence. Redundant code gets eliminated by putting very little application code into the right layer.
|
70
76
|
|
71
|
-

|
72
78
|
|
73
79
|
## Routing
|
74
80
|
|
@@ -76,7 +82,7 @@ Trailblazer uses Rails routing to map URLs to controllers, because it works.
|
|
76
82
|
|
77
83
|
```ruby
|
78
84
|
Rails.application.routes.draw do
|
79
|
-
resources :
|
85
|
+
resources :songs
|
80
86
|
end
|
81
87
|
```
|
82
88
|
|
@@ -85,23 +91,25 @@ end
|
|
85
91
|
Controllers are lean endpoints for HTTP. They do not contain any business logic. Actions immediately dispatch to an operation.
|
86
92
|
|
87
93
|
```ruby
|
88
|
-
class
|
94
|
+
class SongsController < ApplicationController
|
89
95
|
def create
|
90
|
-
run
|
96
|
+
run Song::Create # Song::Create is an operation class.
|
91
97
|
end
|
98
|
+
end
|
92
99
|
```
|
93
100
|
|
94
101
|
The `#run` method invokes the operation. It allows you to run a conditional block of logic if the operation was successful.
|
95
102
|
|
96
103
|
```ruby
|
97
|
-
class
|
104
|
+
class SongsController < ApplicationController
|
98
105
|
def create
|
99
|
-
run
|
100
|
-
return redirect_to(
|
106
|
+
run Song::Create do |op|
|
107
|
+
return redirect_to(song_path op.model) # success!
|
101
108
|
end
|
102
109
|
|
103
110
|
render :new # invalid. re-render form.
|
104
111
|
end
|
112
|
+
end
|
105
113
|
```
|
106
114
|
|
107
115
|
Again, the controller only dispatchs to the operation and handles successful/invalid processing on the HTTP level. For instance by redirecting, setting flash messages, or signing in a user.
|
@@ -112,86 +120,39 @@ Again, the controller only dispatchs to the operation and handles successful/inv
|
|
112
120
|
|
113
121
|
Operations encapsulate business logic and are the heart of a Trailblazer architecture.
|
114
122
|
|
115
|
-
|
116
|
-
|
117
|
-
An operation is not just a monolithic replacement for your business code. It's a simple orchestrator between the form object, models and your business code.
|
118
|
-
|
119
|
-
```ruby
|
120
|
-
class Comment::Create < Trailblazer::Operation
|
121
|
-
def process(params)
|
122
|
-
# do whatever you feel like.
|
123
|
-
end
|
124
|
-
end
|
125
|
-
```
|
126
|
-
|
127
|
-
Operations only need to implement `#process` which receives the params from the caller.
|
128
|
-
|
129
|
-
[Learn more.](http://trailblazer.to/gems/operation)
|
123
|
+
The bare bones operation without any Trailblazery is implemented in [the `trailblazer-operation` gem](https://github.com/trailblazer/trailblazer-operation) and can be used without our stack.
|
130
124
|
|
131
|
-
|
125
|
+
Operations don't know about HTTP or the environment. You could use an operation in Rails, Hanami, or Roda, it wouldn't know.
|
132
126
|
|
133
|
-
|
134
|
-
|
135
|
-
The operation makes use of the form object using the `#validate` method.
|
127
|
+
An operation is not just a monolithic replacement for your business code. It's a simple orchestrator between the form objects, models, your business code and all other layers needed to get the job done.
|
136
128
|
|
137
129
|
```ruby
|
138
|
-
class
|
139
|
-
|
140
|
-
|
141
|
-
property :body, validates: {presence: true}
|
142
|
-
end
|
130
|
+
class Song::Create < Trailblazer::Operation
|
131
|
+
step :model
|
132
|
+
step :validate
|
143
133
|
|
144
|
-
def
|
145
|
-
|
134
|
+
def model(ctx, **)
|
135
|
+
# do whatever you feel like.
|
136
|
+
ctx[:model] = Song.new
|
137
|
+
end
|
146
138
|
|
147
|
-
|
148
|
-
|
149
|
-
end
|
139
|
+
def validate(ctx, params:, **)
|
140
|
+
# ..
|
150
141
|
end
|
151
142
|
end
|
152
143
|
```
|
153
144
|
|
154
|
-
|
155
|
-
|
156
|
-
In the `#process` method you can define your business logic.
|
145
|
+
Operations define the flow of their logic using the DSL and implement the particular steps with pure Ruby.
|
157
146
|
|
158
|
-
|
159
|
-
|
160
|
-
## Callbacks
|
161
|
-
|
162
|
-
Post-processing logic (also known as _callbacks_) is configured in operations.
|
163
|
-
|
164
|
-
Callbacks can be defined in groups. They use the form object's state tracking to find out whether they should be run.
|
147
|
+
You cannot instantiate them per design. The only way to invoke them is `call`.
|
165
148
|
|
166
149
|
```ruby
|
167
|
-
|
168
|
-
include Callback
|
169
|
-
callback(:after_save) do
|
170
|
-
on_change :markdownize_body! # this is only run when the form object has changed.
|
171
|
-
end
|
150
|
+
Song::Create.(params: {whatever: "goes", in: "here"})
|
172
151
|
```
|
173
152
|
|
174
|
-
|
153
|
+
Their high degree of encapsulation makes them a [replacement for test factories](#test), too.
|
175
154
|
|
176
|
-
|
177
|
-
class Comment::Create < Trailblazer::Operation
|
178
|
-
include Callback
|
179
|
-
def process(params)
|
180
|
-
validate(params) do
|
181
|
-
contract.save
|
182
|
-
callback!(:after_save) # run markdownize_body!, but only if form changed.
|
183
|
-
end
|
184
|
-
end
|
185
|
-
|
186
|
-
def markdownize_body!(comment)
|
187
|
-
comment.body = Markdownize.(comment.body)
|
188
|
-
end
|
189
|
-
end
|
190
|
-
```
|
191
|
-
|
192
|
-
No magical triggering of unwanted logic anymore, but explicit invocations where you want it.
|
193
|
-
|
194
|
-
[Learn more.](http://trailblazer.to/gems/operation/callback.html)
|
155
|
+
[Learn more.](http://trailblazer.to/gems/operation)
|
195
156
|
|
196
157
|
## Models
|
197
158
|
|
@@ -200,7 +161,7 @@ Models for persistence can be implemented using any ORM you fancy, for instance
|
|
200
161
|
In Trailblazer, models are completely empty. They solely contain associations and finders. No business logic is allowed in models.
|
201
162
|
|
202
163
|
```ruby
|
203
|
-
class
|
164
|
+
class Song < ActiveRecord::Base
|
204
165
|
belongs_to :thing
|
205
166
|
|
206
167
|
scope :latest, lambda { all.limit(9).order("id DESC") }
|
@@ -209,78 +170,6 @@ end
|
|
209
170
|
|
210
171
|
Only operations and views/cells can access models directly.
|
211
172
|
|
212
|
-
## Policies
|
213
|
-
|
214
|
-
You can abort running an operation using a policy. "[Pundit](https://github.com/elabs/pundit)-style" policy classes define the rules.
|
215
|
-
|
216
|
-
```ruby
|
217
|
-
class Comment::Policy
|
218
|
-
def initialize(user, comment)
|
219
|
-
@user, @comment = user, comment
|
220
|
-
end
|
221
|
-
|
222
|
-
def create?
|
223
|
-
@user.admin?
|
224
|
-
end
|
225
|
-
end
|
226
|
-
```
|
227
|
-
|
228
|
-
The rule is enabled via the `::policy` call.
|
229
|
-
|
230
|
-
```ruby
|
231
|
-
class Comment::Create < Trailblazer::Operation
|
232
|
-
include Policy
|
233
|
-
|
234
|
-
policy Comment::Policy, :create?
|
235
|
-
```
|
236
|
-
|
237
|
-
The policy is evaluated in `#setup!`, raises an exception if `false` and suppresses running `#process`.
|
238
|
-
|
239
|
-
[Learn more.](http://trailblazer.to/gems/operation/policy.html)
|
240
|
-
|
241
|
-
## Views
|
242
|
-
|
243
|
-
View rendering can happen using the controller as known from Rails. This is absolutely fine for simple views.
|
244
|
-
|
245
|
-
More complex UI logic happens in _View Models_ as found in [Cells](https://github.com/apotonick/cells). View models also replace helpers.
|
246
|
-
|
247
|
-
The operation's form object can be rendered in views, too.
|
248
|
-
|
249
|
-
```ruby
|
250
|
-
class CommentsController < ApplicationController
|
251
|
-
def new
|
252
|
-
form Comment::Create # will assign the form object to @form.
|
253
|
-
end
|
254
|
-
```
|
255
|
-
|
256
|
-
Since Reform objects can be passed to form builders, you can use the operation to render and process the form!
|
257
|
-
|
258
|
-
```haml
|
259
|
-
= simple_form_for @form do |f|
|
260
|
-
= f.input :body
|
261
|
-
```
|
262
|
-
|
263
|
-
|
264
|
-
## Representers
|
265
|
-
|
266
|
-
Operations can use representers from [Roar](https://github.com/apotonick/roar) to serialize and parse JSON and XML documents for APIs.
|
267
|
-
|
268
|
-
Representers can be inferred automatically from your contract, then may be refined, e.g. with hypermedia or a format like `JSON-API`.
|
269
|
-
|
270
|
-
```ruby
|
271
|
-
class Comment::Create < Trailblazer::Operation
|
272
|
-
representer do
|
273
|
-
# inherited :body
|
274
|
-
include Roar::JSON::HAL
|
275
|
-
|
276
|
-
link(:self) { comment_path(represented.id) }
|
277
|
-
end
|
278
|
-
```
|
279
|
-
|
280
|
-
The operation can then parse incoming JSON documents in `validate` and render a document via `to_json`.
|
281
|
-
|
282
|
-
[Learn more.](http://trailblazer.to/gems/operation/representer.html)
|
283
|
-
|
284
173
|
## Tests
|
285
174
|
|
286
175
|
In Trailblazer, you only have operation unit tests and integration smoke tests to test the operation/controller wiring.
|
@@ -288,19 +177,18 @@ In Trailblazer, you only have operation unit tests and integration smoke tests t
|
|
288
177
|
Operations completely replace the need for leaky factories.
|
289
178
|
|
290
179
|
```ruby
|
291
|
-
describe
|
292
|
-
let(:
|
180
|
+
describe Song::Update do
|
181
|
+
let(:song) { Song::Create.(song: {body: "[That](http://trailblazer.to)!"}) }
|
182
|
+
end
|
293
183
|
```
|
294
184
|
|
295
|
-
##
|
185
|
+
## Workflows
|
296
186
|
|
297
|
-
Trailblazer
|
187
|
+
Operations are a great way to clean up controllers and models. However, Trailblazer goes further and provides an approach to model entire life-cycles of business objects, such as "a song" or "the root user".
|
298
188
|
|
299
|
-
|
300
|
-
* Inheritance and composition support
|
301
|
-
* Polymorphic views
|
189
|
+
Those workflows dramatically reduce the usage of control flow logic in your code and allow for visually designing and discussing flows.
|
302
190
|
|
303
|
-
|
191
|
+
Learn more about BPMN and workflows [on our website](https://2019.trailblazer.to/docs/workflow).
|
304
192
|
|
305
193
|
## Installation
|
306
194
|
|
@@ -309,16 +197,7 @@ The obvious needs to be in your `Gemfile`.
|
|
309
197
|
```ruby
|
310
198
|
gem "trailblazer"
|
311
199
|
gem "trailblazer-rails" # if you are in rails.
|
312
|
-
gem "cells"
|
200
|
+
gem "trailblazer-cells"
|
313
201
|
```
|
314
202
|
|
315
203
|
Cells is _not_ required per default! Add it if you use it, which is highly recommended.
|
316
|
-
|
317
|
-
## The Book
|
318
|
-
|
319
|
-

|
320
|
-
|
321
|
-
Please buy it: [Trailblazer - A new architecture for Rails](https://leanpub.com/trailblazer).
|
322
|
-
|
323
|
-
The [demo application](https://github.com/apotonick/gemgem-trbrb) implements what we discuss in the book.
|
324
|
-
|
data/Rakefile
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
require "bundler/gem_tasks"
|
2
2
|
require "rake/testtask"
|
3
3
|
|
4
|
-
task :default => [
|
4
|
+
task :default => %i[test]
|
5
5
|
|
6
6
|
Rake::TestTask.new(:test) do |test|
|
7
7
|
test.libs << 'test'
|
8
|
-
test.test_files = FileList['test/**/*_test.rb']
|
8
|
+
test.test_files = FileList['test/**/*_test.rb'] - FileList["test/deprecation/*_test.rb"]
|
9
9
|
test.verbose = true
|
10
|
-
end
|
10
|
+
end
|
data/lib/trailblazer/version.rb
CHANGED
data/lib/trailblazer.rb
CHANGED
data/test/test_helper.rb
CHANGED
@@ -1,9 +1,38 @@
|
|
1
|
-
require
|
2
|
-
require
|
1
|
+
require "pp"
|
2
|
+
require "delegate"
|
3
|
+
require "trailblazer"
|
4
|
+
require "minitest/autorun"
|
3
5
|
|
6
|
+
# TODO: convert tests to non-rails.
|
7
|
+
require "reform"
|
4
8
|
require "reform/form/active_model/validations"
|
5
9
|
Reform::Form.class_eval do
|
6
10
|
include Reform::Form::ActiveModel::Validations
|
7
11
|
end
|
12
|
+
# require "trailblazer/deprecation/context.rb"
|
8
13
|
|
9
|
-
|
14
|
+
module Mock
|
15
|
+
class Result
|
16
|
+
def initialize(bool); @bool = bool end
|
17
|
+
def success?; @bool end
|
18
|
+
def errors; ["hihi"] end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
module Test
|
23
|
+
module ReturnCall
|
24
|
+
def self.included(includer)
|
25
|
+
includer._insert :_insert, ReturnResult, {replace: Trailblazer::Operation::Result::Build}, ReturnResult, ""
|
26
|
+
end
|
27
|
+
end
|
28
|
+
ReturnResult = ->(last, input, options) { input }
|
29
|
+
end
|
30
|
+
|
31
|
+
Minitest::Spec::Operation = Trailblazer::Operation
|
32
|
+
|
33
|
+
Memo = Struct.new(:id, :body) do
|
34
|
+
def self.find(id)
|
35
|
+
return new(id, "Yo!") if id
|
36
|
+
nil
|
37
|
+
end
|
38
|
+
end
|
data/trailblazer.gemspec
CHANGED
@@ -4,31 +4,27 @@ require 'trailblazer/version'
|
|
4
4
|
|
5
5
|
Gem::Specification.new do |spec|
|
6
6
|
spec.name = "trailblazer"
|
7
|
-
spec.version = Trailblazer::VERSION
|
7
|
+
spec.version = Trailblazer::Version::VERSION
|
8
8
|
spec.authors = ["Nick Sutterer"]
|
9
9
|
spec.email = ["apotonick@gmail.com"]
|
10
|
-
spec.description = %q{A high-level
|
10
|
+
spec.description = %q{A high-level architecture introducing new abstractions such as operations and control flow, form objects and policies.}
|
11
11
|
spec.summary = %q{A high-level architecture for Ruby and Rails.}
|
12
12
|
spec.homepage = "http://trailblazer.to"
|
13
|
-
spec.license = "
|
13
|
+
spec.license = "LGPL-3.0"
|
14
14
|
|
15
|
-
spec.files = `git ls-files`.split(
|
16
|
-
|
17
|
-
|
15
|
+
spec.files = `git ls-files -z`.split("\x0").reject do |f|
|
16
|
+
f.match(%r{^(test|doc)/})
|
17
|
+
end
|
18
|
+
spec.test_files = `git ls-files -z test`.split("\x0")
|
18
19
|
spec.require_paths = ["lib"]
|
19
20
|
|
20
|
-
|
21
|
-
spec.add_dependency "
|
22
|
-
spec.add_dependency "
|
23
|
-
spec.add_dependency "declarative"
|
24
|
-
|
25
|
-
spec.add_development_dependency "activemodel" # for Reform::AM::V
|
21
|
+
spec.add_dependency "trailblazer-macro", ">= 2.1.0", "< 2.2.0"
|
22
|
+
spec.add_dependency "trailblazer-macro-contract", ">= 2.1.0", "< 2.2.0"
|
23
|
+
spec.add_dependency "trailblazer-operation" # TODO: why do we need this here?
|
26
24
|
|
27
25
|
spec.add_development_dependency "bundler"
|
28
26
|
spec.add_development_dependency "rake"
|
29
27
|
spec.add_development_dependency "minitest"
|
30
|
-
spec.add_development_dependency "sqlite3"
|
31
|
-
spec.add_development_dependency "database_cleaner"
|
32
28
|
|
33
|
-
spec.
|
29
|
+
spec.required_ruby_version = '>= 2.1.0'
|
34
30
|
end
|