interaktor 0.1.5 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 99cf1e62638c0d275243c18799d225ec5f6e44eb6e75ac0cb12418775f8d2ebe
4
- data.tar.gz: 8e53e5c94af31544e37222810b123bf7817db54a3667f94e01a10c64d9536ba3
3
+ metadata.gz: be48f704b8d52c81c07e9708d1e90230ead270e4da3ddf74e8e4e6251e677978
4
+ data.tar.gz: '09e99c6f8129b44ff287aa9e8a742327cac3a232f13d7596ece9b428a575bc28'
5
5
  SHA512:
6
- metadata.gz: 7fcd8dfeabdbacd828471bac5d80e57582e98f02c9ecf31188c2300aa24e19e2dde04453aeb82b439b8f048a4c10bb00147f2b7e9927d028aa4adbcfa22ebcf0
7
- data.tar.gz: 1ddb2a5b49de3269b02b1c1264991ae126385ed2c22fd7f9fb953361820d9f373620fee434be064310e3aaaabe394bf3cab2d2085a9c37ac43619b8f04f92313
6
+ metadata.gz: ea1fe86854da930c537f9fb69864accdf8cb1948d8dacae4b64685ff88508964e99eb968826a12e5653791f492c1e8af6426b734838c5ac152c581dfee6399ba
7
+ data.tar.gz: 0d8c4406b6d3ee81f39c6adc56118ce4e204465743eed6dc5f342f3b3b5a9a03722f9b04ed48dab265ef9bfbcb54e047476245fdf000295b150e2a835f8087e6
@@ -0,0 +1,30 @@
1
+ name: Publish
2
+
3
+ on:
4
+ push:
5
+ branches: [master]
6
+ tags:
7
+ - v*
8
+
9
+ jobs:
10
+ build:
11
+ name: Build and publish
12
+ runs-on: ubuntu-latest
13
+
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: Set up Ruby
17
+ uses: actions/setup-ruby@v1
18
+ with:
19
+ ruby-version: 2.5.x
20
+
21
+ - name: Publish to RubyGems
22
+ run: |
23
+ mkdir -p $HOME/.gem
24
+ touch $HOME/.gem/credentials
25
+ chmod 0600 $HOME/.gem/credentials
26
+ printf -- "---\n:rubygems_api_key: ${GEM_HOST_API_KEY}\n" > $HOME/.gem/credentials
27
+ gem build *.gemspec
28
+ gem push *.gem
29
+ env:
30
+ GEM_HOST_API_KEY: "${{secrets.RUBYGEMS_AUTH_TOKEN}}"
@@ -0,0 +1,24 @@
1
+ name: Tests
2
+
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ test:
7
+ strategy:
8
+ fail-fast: false
9
+ matrix:
10
+ os: [ubuntu, macos]
11
+ ruby: [2.5, 2.6, 2.7, head, debug]
12
+ runs-on: ${{ matrix.os }}-latest
13
+ continue-on-error: ${{ endsWith(matrix.ruby, 'head') || matrix.ruby == 'debug' }}
14
+ steps:
15
+ - uses: actions/checkout@v2
16
+ - name: Set up Ruby
17
+ uses: ruby/setup-ruby@v1
18
+ with:
19
+ ruby-version: ${{ matrix.ruby }}
20
+ bundler-cache: true
21
+ - name: Install dependencies
22
+ run: bundle install
23
+ - name: Run tests
24
+ run: bundle exec rspec
@@ -0,0 +1 @@
1
+ 2.5.8
@@ -1,25 +1,14 @@
1
- after_success:
2
- - bundle exec codeclimate-test-reporter
3
1
  before_install:
4
2
  - gem update bundler rake
5
- branches:
6
- only:
7
- - master
8
- - v4
9
3
  cache: bundler
10
4
  language: ruby
11
5
  matrix:
12
6
  allow_failures:
13
7
  - rvm: ruby-head
14
- notifications:
15
- webhooks:
16
- on_start: always
17
- urls:
18
- - http://buildlight.collectiveidea.com/
19
8
  rvm:
20
9
  - "2.5"
21
10
  - "2.6"
22
11
  - "2.7"
23
12
  - ruby-head
24
- script: bundle exec rake
13
+ script: bundle exec rspec
25
14
  sudo: false
data/Gemfile CHANGED
@@ -7,9 +7,10 @@ gem "rubocop-performance"
7
7
  gem "rubocop-rspec"
8
8
  gem "rufo", "~> 0.12.0"
9
9
  gem "solargraph"
10
+ gem "guard-rspec", require: false
10
11
 
11
12
  group :test do
12
- gem "codeclimate-test-reporter", "~> 1.0.9", require: false
13
- gem "pry-byebug"
13
+ gem "pry-byebug", platforms: [:mri]
14
14
  gem "rspec", "~> 3.9.0"
15
+ gem "simplecov"
15
16
  end
@@ -0,0 +1,42 @@
1
+ # A sample Guardfile
2
+ # More info at https://github.com/guard/guard#readme
3
+
4
+ ## Uncomment and set this to only include directories you want to watch
5
+ # directories %w(app lib config test spec features) \
6
+ # .select{|d| Dir.exist?(d) ? d : UI.warning("Directory #{d} does not exist")}
7
+
8
+ ## Note: if you are using the `directories` clause above and you are not
9
+ ## watching the project directory ('.'), then you will want to move
10
+ ## the Guardfile to a watched dir and symlink it back, e.g.
11
+ #
12
+ # $ mkdir config
13
+ # $ mv Guardfile config/
14
+ # $ ln -s config/Guardfile .
15
+ #
16
+ # and, you'll have to watch "config/Guardfile" instead of "Guardfile"
17
+
18
+ # Note: The cmd option is now required due to the increasing number of ways
19
+ # rspec may be run, below are examples of the most common uses.
20
+ # * bundler: 'bundle exec rspec'
21
+ # * bundler binstubs: 'bin/rspec'
22
+ # * spring: 'bin/rspec' (This will use spring if running and you have
23
+ # installed the spring binstubs per the docs)
24
+ # * zeus: 'zeus rspec' (requires the server to be started separately)
25
+ # * 'just' rspec: 'rspec'
26
+
27
+ guard :rspec, cmd: "bundle exec rspec" do
28
+ require "guard/rspec/dsl"
29
+ dsl = Guard::RSpec::Dsl.new(self)
30
+
31
+ # Feel free to open issues for suggestions and improvements
32
+
33
+ # RSpec files
34
+ rspec = dsl.rspec
35
+ watch(rspec.spec_helper) { rspec.spec_dir }
36
+ watch(rspec.spec_support) { rspec.spec_dir }
37
+ watch(rspec.spec_files)
38
+
39
+ # Ruby files
40
+ ruby = dsl.ruby
41
+ dsl.watch_spec_files_for(ruby.lib_files)
42
+ end
data/README.md CHANGED
@@ -3,21 +3,23 @@
3
3
  [![Gem Version](https://img.shields.io/gem/v/interaktor.svg)](http://rubygems.org/gems/interaktor)
4
4
  [![Build Status](https://img.shields.io/travis/collectiveidea/interaktor/master.svg)](https://travis-ci.org/taylorthurlow/interaktor)
5
5
 
6
- **Interaktor** is a fork of [Interaktor by collectiveidea](https://github.com/collectiveidea/interaktor). While Interaktor is still used by collectiveidea internally, communication and progress has been slow in adapting to pull requests and issues. This inactivity combined with my desire to dial back on the Interaktor's inherent permissivity led me to fork it and create Interaktor.
6
+ **DISCLAIMER: Interaktor is under active development. Feel free to use it, but until 1.0 is released, any update could break compatibility with an older version.**
7
7
 
8
- Fundamentally, Interaktor is the same as Interactor, but with a small DSL which is used to define attributes passed into the interaktor, such as:
8
+ **Interaktor** is a fork of [Interaktor by collectiveidea](https://github.com/collectiveidea/interaktor). While Interactor is still used by collectiveidea internally, communication and progress has been slow in adapting to pull requests and issues. This inactivity combined with my desire to dial back on the Interactor's inherent permissivity led me to fork it and create Interaktor.
9
9
 
10
- - Required attributes
11
- - Optional attributes
12
- - Attributes required on interaktor failure
13
- - Attributes required on interaktor success
10
+ Fundamentally, Interaktor is the same as Interactor, but with the following changes:
11
+
12
+ - Required explicit definition of interaktor "attributes" which replaces the concept of the interaktor context. Attributes can be required or optional, and support options like default values.
13
+ - The interaktor "context" is no longer a public-facing concept, all data/attribute accessors/setters are defined as attributes
14
+ - Attributes passed to `#fail!` must be defined in advance
15
+ - Interaktors support early-exit functionality through the use of `#success!`, which functions the same as `#fail!` in that you must define the required success attributes on the interaktor
14
16
 
15
17
  ## Getting started
16
18
 
17
19
  Add `interaktor` to your Gemfile and `bundle install`.
18
20
 
19
21
  ```ruby
20
- gem "interaktor", "~> 0.1"
22
+ gem "interaktor"
21
23
  ```
22
24
 
23
25
  ## What is an interaktor?
@@ -90,13 +92,11 @@ else
90
92
  end
91
93
  ```
92
94
 
93
- #### Dealing with sailure
94
-
95
- `context.fail!` always throws an exception of type `Interaktor::Failure`.
95
+ #### Dealing with failure
96
96
 
97
- Normally, however, these exceptions are not seen. In the recommended usage, the controller invokes the interaktor using the class method `.call`, then checks the `#success?` method of the context.
97
+ `#fail!` always throws an exception of type `Interaktor::Failure`.
98
98
 
99
- This works because the `call` class method swallows exceptions. When unit testing an interaktor, if calling custom business logic methods directly and bypassing `call`, be aware that `fail!` will generate such exceptions.
99
+ Normally, however, these exceptions are not seen. In the recommended usage, the caller invokes the interaktor using the class method `.call`, then checks the `#success?` method of the returned object. This works because the `call` class method swallows exceptions. When unit testing an interaktor, if calling custom business logic methods directly and bypassing `call`, be aware that `fail!` will generate such exceptions.
100
100
 
101
101
  See _Interaktors in the controller_, below, for the recommended usage of `call` and `success?`.
102
102
 
@@ -104,7 +104,7 @@ See _Interaktors in the controller_, below, for the recommended usage of `call`
104
104
 
105
105
  #### Before hooks
106
106
 
107
- Sometimes an interaktor needs to prepare its context before the interaktor is even run. This can be done with before hooks on the interaktor.
107
+ Sometimes an interaktor needs to prepare something before the interaktor is even run. This can be done with before hooks on the interaktor.
108
108
 
109
109
  ```ruby
110
110
  before do
@@ -124,12 +124,11 @@ end
124
124
 
125
125
  #### After hooks
126
126
 
127
- Interaktors can also perform teardown operations after the interaktor instance
128
- is run. They are only run on success.
127
+ Interaktors can also perform teardown operations after the interaktor instance is run. They are only run on success.
129
128
 
130
129
  ```ruby
131
130
  after do
132
- context.user.reload
131
+ user.reload
133
132
  end
134
133
  ```
135
134
 
@@ -161,9 +160,7 @@ If `#fail!` is called, any code defined in the hook after the call to the intera
161
160
 
162
161
  #### Hook sequence
163
162
 
164
- Before hooks are invoked in the order in which they were defined while after
165
- hooks are invoked in the opposite order. Around hooks are invoked outside of any
166
- defined before and after hooks. For example:
163
+ Before hooks are invoked in the order in which they were defined while after hooks are invoked in the opposite order. Around hooks are invoked outside of any defined before and after hooks. For example:
167
164
 
168
165
  ```ruby
169
166
  around do |interaktor|
@@ -210,8 +207,7 @@ around after 1
210
207
 
211
208
  #### Interaktor concerns
212
209
 
213
- An interaktor can define multiple before/after hooks, allowing common hooks to
214
- be extracted into interaktor concerns.
210
+ An interaktor can define multiple before/after hooks, allowing common hooks to be extracted into interaktor concerns.
215
211
 
216
212
  ```ruby
217
213
  module InteraktorDoStuff
@@ -227,12 +223,9 @@ module InteraktorDoStuff
227
223
  end
228
224
  ```
229
225
 
230
- # All documentation below this line has not been updated to reflect the fork from Interactor.
231
-
232
226
  ## Kinds of interaktors
233
227
 
234
- There are two kinds of interaktors built into the Interaktor library: basic
235
- interaktors and organizers.
228
+ There are two kinds of interaktors built into the Interaktor library: basic interaktors and organizers.
236
229
 
237
230
  ### Interaktors
238
231
 
@@ -242,35 +235,41 @@ A basic interaktor is a class that includes `Interaktor` and defines `call`.
242
235
  class AuthenticateUser
243
236
  include Interaktor
244
237
 
238
+ required :email
239
+ required :password
240
+
241
+ success :user
242
+ success :token
243
+
244
+ failure :message
245
+
245
246
  def call
246
- if user = User.authenticate(context.email, context.password)
247
- context.user = user
248
- context.token = user.secret_token
247
+ if user = User.authenticate(email, password)
248
+ success!(user: user, token: user.secret_token)
249
249
  else
250
- context.fail!(message: "authenticate_user.failure")
250
+ fail!(message: "authenticate_user.failure")
251
251
  end
252
252
  end
253
253
  end
254
254
  ```
255
255
 
256
- Basic interaktors are the building blocks. They are your application's
257
- single-purpose units of work.
256
+ Basic interaktors are the building blocks. They are your application's single-purpose units of work.
258
257
 
259
258
  ### Organizers
260
259
 
261
- An organizer is an important variation on the basic interaktor. Its single
262
- purpose is to run _other_ interaktors.
260
+ An organizer is an important variation on the basic interaktor. Its single purpose is to run _other_ interaktors.
263
261
 
264
262
  ```ruby
265
263
  class PlaceOrder
266
264
  include Interaktor::Organizer
267
265
 
266
+ required :order_params
267
+
268
268
  organize CreateOrder, ChargeCard, SendThankYou
269
269
  end
270
270
  ```
271
271
 
272
- In the controller, you can run the `PlaceOrder` organizer just like you would
273
- any other interaktor:
272
+ In the controller, you can run the `PlaceOrder` organizer just like you would any other interaktor:
274
273
 
275
274
  ```ruby
276
275
  class OrdersController < ApplicationController
@@ -293,69 +292,71 @@ class OrdersController < ApplicationController
293
292
  end
294
293
  ```
295
294
 
296
- The organizer passes its context to the interaktors that it organizes, one at a
297
- time and in order. Each interaktor may change that context before it's passed
298
- along to the next interaktor.
295
+ The organizer passes any of its own defined attributes into first interaktor that it organizes. That first interaktor is then called and executed using those attributes. For the following interaktors in the organize list, each interaktor receives its attributes from the previous interaktor (both input attributes and success attributes). Any attributes which are _not_ accepted by the next interaktor (listed as required or optional attributes) are dropped in the transition.
299
296
 
300
297
  #### Rollback
301
298
 
302
- If any one of the organized interaktors fails its context, the organizer stops.
303
- If the `ChargeCard` interaktor fails, `SendThankYou` is never called.
299
+ If any one of the organized interaktors fails, the organizer stops. If the `ChargeCard` interaktor fails, `SendThankYou` is never called.
304
300
 
305
- In addition, any interaktors that had already run are given the chance to undo
306
- themselves, in reverse order. Simply define the `rollback` method on your
307
- interaktors:
301
+ In addition, any interaktors that had already run are given the chance to undo themselves, in reverse order. Simply define the `rollback` method on your interaktors.
308
302
 
309
303
  ```ruby
310
304
  class CreateOrder
311
305
  include Interaktor
312
306
 
307
+ required :order_params
308
+
309
+ success :order
310
+
313
311
  def call
314
312
  order = Order.create(order_params)
315
313
 
316
314
  if order.persisted?
317
- context.order = order
315
+ success!(order: order)
318
316
  else
319
- context.fail!
317
+ fail!
320
318
  end
321
319
  end
322
320
 
323
321
  def rollback
324
- context.order.destroy
322
+ order.destroy
325
323
  end
326
324
  end
327
325
  ```
328
326
 
329
- **NOTE:** The interaktor that fails is _not_ rolled back. Because every
330
- interaktor should have a single purpose, there should be no need to clean up
331
- after any failed interaktor.
327
+ **NOTE:** The interaktor that fails is _not_ rolled back. Because every interaktor should have a single purpose, there should be no need to clean up after any failed interaktor. This is why the rollback method above can access the `order` success attribute - rollback is only called on successful interaktors.
332
328
 
333
329
  ## Testing interaktors
334
330
 
335
- When written correctly, an interaktor is easy to test because it only _does_ one
336
- thing. Take the following interaktor:
331
+ When written correctly, an interaktor is easy to test because it only _does_ one thing. Take the following interaktor:
337
332
 
338
333
  ```ruby
339
334
  class AuthenticateUser
340
335
  include Interaktor
341
336
 
337
+ required :email
338
+ required :password
339
+
340
+ success :user
341
+ success :token
342
+
343
+ failure :message
344
+
342
345
  def call
343
- if user = User.authenticate(context.email, context.password)
344
- context.user = user
345
- context.token = user.secret_token
346
+ if user = User.authenticate(email, password)
347
+ success!(user: user, token: user.secret_token)
346
348
  else
347
- context.fail!(message: "authenticate_user.failure")
349
+ fail!(message: "authenticate_user.failure")
348
350
  end
349
351
  end
350
352
  end
351
353
  ```
352
354
 
353
- You can test just this interaktor's single purpose and how it affects the
354
- context.
355
+ You can test just this interaktor's single purpose and how it affects the result.
355
356
 
356
357
  ```ruby
357
358
  describe AuthenticateUser do
358
- subject(:context) { AuthenticateUser.call(email: "john@example.com", password: "secret") }
359
+ subject(:result) { AuthenticateUser.call(email: "john@example.com", password: "secret") }
359
360
 
360
361
  describe ".call" do
361
362
  context "when given valid credentials" do
@@ -366,15 +367,15 @@ describe AuthenticateUser do
366
367
  end
367
368
 
368
369
  it "succeeds" do
369
- expect(context).to be_a_success
370
+ expect(result).to be_a_success
370
371
  end
371
372
 
372
373
  it "provides the user" do
373
- expect(context.user).to eq(user)
374
+ expect(result.user).to eq(user)
374
375
  end
375
376
 
376
377
  it "provides the user's secret token" do
377
- expect(context.token).to eq("token")
378
+ expect(result.token).to eq("token")
378
379
  end
379
380
  end
380
381
 
@@ -384,80 +385,62 @@ describe AuthenticateUser do
384
385
  end
385
386
 
386
387
  it "fails" do
387
- expect(context).to be_a_failure
388
+ expect(result).to be_a_failure
388
389
  end
389
390
 
390
391
  it "provides a failure message" do
391
- expect(context.message).to be_present
392
+ expect(result.message).to be_present
392
393
  end
393
394
  end
394
395
  end
395
396
  end
396
397
  ```
397
398
 
398
- [We](http://collectiveidea.com) use RSpec but the same approach applies to any
399
- testing framework.
400
-
401
399
  ### Isolation
402
400
 
403
- You may notice that we stub `User.authenticate` in our test rather than creating
404
- users in the database. That's because our purpose in
405
- `spec/interaktors/authenticate_user_spec.rb` is to test just the
406
- `AuthenticateUser` interaktor. The `User.authenticate` method is put through its
407
- own paces in `spec/models/user_spec.rb`.
401
+ You may notice that we stub `User.authenticate` in our test rather than creating users in the database. That's because our purpose in `spec/interaktors/authenticate_user_spec.rb` is to test just the `AuthenticateUser` interaktor. The `User.authenticate` method is put through its own paces in `spec/models/user_spec.rb`.
408
402
 
409
- It's a good idea to define your own interfaces to your models. Doing so makes it
410
- easy to draw a line between which responsibilities belong to the interaktor and
411
- which to the model. The `User.authenticate` method is a good, clear line.
412
- Imagine the interaktor otherwise:
403
+ It's a good idea to define your own interfaces to your models. Doing so makes it easy to draw a line between which responsibilities belong to the interaktor and which to the model. The `User.authenticate` method is a good, clear line. Imagine the interaktor otherwise:
413
404
 
414
405
  ```ruby
415
406
  class AuthenticateUser
416
407
  include Interaktor
417
408
 
409
+ required :email
410
+ required :password
411
+
412
+ success :user
413
+
414
+ failure :message
415
+
418
416
  def call
419
- user = User.where(email: context.email).first
417
+ user = User.find_by(email: email)
420
418
 
421
419
  # Yuck!
422
- if user && BCrypt::Password.new(user.password_digest) == context.password
423
- context.user = user
420
+ if user && BCrypt::Password.new(user.password_digest) == password
421
+ success!(user: user)
424
422
  else
425
- context.fail!(message: "authenticate_user.failure")
423
+ fail!(message: "authenticate_user.failure")
426
424
  end
427
425
  end
428
426
  end
429
427
  ```
430
428
 
431
- It would be very difficult to test this interaktor in isolation and even if you
432
- did, as soon as you change your ORM or your encryption algorithm (both model
433
- concerns), your interaktors (business concerns) break.
429
+ It would be very difficult to test this interaktor in isolation and even if you did, as soon as you change your ORM or your encryption algorithm (both model concerns), your interaktors (business concerns) break.
434
430
 
435
431
  _Draw clear lines._
436
432
 
437
433
  ### Integration
438
434
 
439
- While it's important to test your interaktors in isolation, it's just as
440
- important to write good integration or acceptance tests.
435
+ While it's important to test your interaktors in isolation, it's just as important to write good integration or acceptance tests.
441
436
 
442
- One of the pitfalls of testing in isolation is that when you stub a method, you
443
- could be hiding the fact that the method is broken, has changed or doesn't even
444
- exist.
437
+ One of the pitfalls of testing in isolation is that when you stub a method, you could be hiding the fact that the method is broken, has changed or doesn't even exist.
445
438
 
446
- When you write full-stack tests that tie all of the pieces together, you can be
447
- sure that your application's individual pieces are working together as expected.
448
- That becomes even more important when you add a new layer to your code like
449
- interaktors.
450
-
451
- **TIP:** If you track your test coverage, try for 100% coverage _before_
452
- integrations tests. Then keep writing integration tests until you sleep well at
453
- night.
439
+ When you write full-stack tests that tie all of the pieces together, you can be sure that your application's individual pieces are working together as expected. That becomes even more important when you add a new layer to your code like interaktors.
454
440
 
455
441
  ### Controllers
456
442
 
457
- One of the advantages of using interaktors is how much they simplify controllers
458
- and their tests. Because you're testing your interaktors thoroughly in isolation
459
- as well as in integration tests (right?), you can remove your business logic
460
- from your controller tests.
443
+ One of the advantages of using interaktors is how much they simplify controllers and their tests. Because you're testing your interaktors thoroughly in isolation as well as in integration tests (right?), you can remove your business logic from your controller tests.
461
444
 
462
445
  ```ruby
463
446
  class SessionsController < ApplicationController
@@ -485,12 +468,12 @@ end
485
468
  describe SessionsController do
486
469
  describe "#create" do
487
470
  before do
488
- expect(AuthenticateUser).to receive(:call).once.with(email: "john@doe.com", password: "secret").and_return(context)
471
+ expect(AuthenticateUser).to receive(:call).once.with(email: "john@doe.com", password: "secret").and_return(result)
489
472
  end
490
473
 
491
474
  context "when successful" do
492
475
  let(:user) { double(:user, id: 1) }
493
- let(:context) { double(:context, success?: true, user: user, token: "token") }
476
+ let(:result) { double(:result, success?: true, user: user, token: "token") }
494
477
 
495
478
  it "saves the user's secret token in the session" do
496
479
  expect {
@@ -508,7 +491,7 @@ describe SessionsController do
508
491
  end
509
492
 
510
493
  context "when unsuccessful" do
511
- let(:context) { double(:context, success?: false, message: "message") }
494
+ let(:result) { double(:result, success?: false, message: "message") }
512
495
 
513
496
  it "sets a flash message" do
514
497
  expect {
@@ -528,36 +511,8 @@ describe SessionsController do
528
511
  end
529
512
  ```
530
513
 
531
- This controller test will have to change very little during the life of the
532
- application because all of the magic happens in the interaktor.
514
+ This controller test will have to change very little during the life of the application because all of the magic happens in the interaktor.
533
515
 
534
516
  ### Rails
535
517
 
536
- [We](http://collectiveidea.com) love Rails, and we use Interaktor with Rails. We
537
- put our interaktors in `app/interaktors` and we name them as verbs:
538
-
539
- - `AddProductToCart`
540
- - `AuthenticateUser`
541
- - `PlaceOrder`
542
- - `RegisterUser`
543
- - `RemoveProductFromCart`
544
-
545
- See: [Interaktor Rails](https://github.com/collectiveidea/interaktor-rails)
546
-
547
- ## Contributions
548
-
549
- Interaktor is open source and contributions from the community are encouraged!
550
- No contribution is too small.
551
-
552
- See Interaktor's
553
- [contribution guidelines](CONTRIBUTING.md) for more information.
554
-
555
- ## Thank You
556
-
557
- A very special thank you to [Attila Domokos](https://github.com/adomokos) for
558
- his fantastic work on [LightService](https://github.com/adomokos/light-service).
559
- Interaktor is inspired heavily by the concepts put to code by Attila.
560
-
561
- Interaktor was born from a desire for a slightly simplified interface. We
562
- understand that this is a matter of personal preference, so please take a look
563
- at LightService as well!
518
+ Interactor provided [interactor-rails](https://github.com/collectiveidea/interactor-rails), which ensures `app/interactors` is included in your autoload paths, and provides generators for new interactors. I have no intention of maintaining generators but if someone feels strongly enough to submit a pull request to include the functionality in _this_ gem (not a separate Rails one) then I will be happy to take a look. Making sure `app/interactors` is included in your autoload paths is something I would like to do soon.