trailblazer 1.1.1 → 2.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|
[![Gitter Chat](https://badges.gitter.im/trailblazer/chat.svg)](https://gitter.im/trailblazer/chat)
|
6
6
|
[![TRB Newsletter](https://img.shields.io/badge/TRB-newsletter-lightgrey.svg)](http://trailblazer.to/newsletter/)
|
7
7
|
[![Gem Version](https://badge.fury.io/rb/trailblazer.svg)](http://badge.fury.io/rb/trailblazer)
|
8
|
+
[![Open Source Helpers](https://www.codetriage.com/trailblazer/trailblazer/badges/users.svg)](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
|
-
![The Trailblazer stack.](https://raw.github.com/apotonick/trailblazer/master/doc/
|
77
|
+
![The Trailblazer stack.](https://raw.github.com/apotonick/trailblazer/master/doc/operation-2017.png)
|
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
|
-
![](https://raw.githubusercontent.com/apotonick/trailblazer/master/doc/trb.jpg)
|
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
|