Giter Club home page Giter Club logo

activeinteractor's Introduction

ActiveInteractor

Version Build Status Maintainability Test Coverage Yard Docs Inline docs License

An implementation of the command pattern for Ruby with ActiveModel::Validations inspired by the interactor gem. Rich support for attributes, callbacks, and validations, and thread safe performance methods.

Reduce controller bloat with procedural service objects. Checkout this Medium article for a crash course on how to use ActiveInteractors. Read the wiki for detailed usage information.

Features

Documentation

Be sure to read the wiki for detailed information on how to use ActiveInteractor.

For technical documentation please see the gem's ruby docs.

Install

Add this line to your application's Gemfile:

gem 'activeinteractor', require: 'active_interactor'

Or install it yourself as:

gem install activeinteractor

Contributing

Read our guidelines for Contributing.

Acknowledgements

ActiveInteractor is made possible by wonderful humans.

License

The gem is available as open source under the terms of the MIT License.

activeinteractor's People

Contributors

aaronmallen avatar aka-momo avatar dependabot[bot] avatar depfu[bot] avatar matsuokashuhei avatar mjonas87 avatar nhorton avatar ruslan-oliinyk avatar templeman15 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

activeinteractor's Issues

Interface Pattern

Elevator pitch, describe and sell us your feature request

As a developer
I want to see an implementation of the pattern discussed in #84
so that I can implement interactors using that pattern.

TODO:

  • write stories for this epic to implement the interface pattern

NameError (uninitialized constant ActiveInteractor::Organizer)

Current Behavior

When referencing ActiveInteractor::Organizer gem raises NameError

Expected Behavior

ActiveInteractor::Organizer should be able to be referenced and inherited from.

Steps to Reproduce

  1. Create a class that inherits from ActiveInteractor::Organizer

Additional Comments

This is caused by Organizer not being included in the autoload in lib/active_interactor.rb

Add support for Dynamoid ORM

Elevator pitch, describe and sell us your feature request

As a developer,
I want acts_as_context available on my Dynamoid::Document classes
so that I can use ActiveInteractor with Dynamoid

Is your feature request related to a problem

Have you considered any alternatives

Additional Comments

Dynamoid does not use ActiveSupport.run_load_hooks

acts_as_context not working

Current Behavior

calling acts_as_context on an ActiveRecord model raises NameError

Expected Behavior

calling acts_as_context on an ActiveRecord model should not raise NameError and should include the appropriate context methods on the model.

Steps to Reproduce

  1. Create an ActiveRecord class
  2. Call acts_as_context on that class
class Model < ApplicationRecord
  acts_as_context
end
  1. go into rails console rails c
  2. try Model.new

Additional Comments

It would appear this initializer is either never invoked or is invoked after ActiveSupport.run_load_hooks is called for ActiveRecord. This could be an issue with the gem name not properly loading things in the path when rails is looking for Railties.

It should also be noted that if you go into rails console and run:

ActiveSupport.run_load_hooks(:active_record_base, ActiveRecord::Base)

acts_as_context works as expected.

Add the interactor directory to `autoload_paths`

Elevator pitch, describe and sell us your feature request

As a developer,
I want the interactor directory to be autoloaded
so that I can use my interactors

Is your feature request related to a problem

Currently interactors are not autoloaded in a given rails application unless I add the directory to the autoload_paths in config/application.rb

Have you considered any alternatives

Additional Comments

[AI-1] Context attributes assigned in interactor not accessible as element within interactor

class InteractorA < ActiveInteractor::Base
  def perform
    context.foo = 'hello'
    context.bar = 'world'
    context.baz = '!!!!!'

    puts "InteractorA"
    puts "foo => #{context.foo}"
    puts "bar => #{context.bar}"
    puts "baz => #{context.baz}"
    puts "foo => #{context[:foo]}"
    puts "bar => #{context[:bar]}"
    puts "baz => #{context[:baz]}"
  end
end

class InteractorA::Context < ActiveInteractor::Context::Base
  attribute :foo
end

InteractorA.perform

# outputs
# foo => hello
# bar => world
# baz => !!!!!
# foo =>
# bar => world
# baz => !!!!!

The use of classify is not documented which produces unexpected singularization of class names in organizers

Question

If I want to have multiple organizers but I want them in separate modules, let's say I have an organizer in module Order (app/interactors/order)

app/interactors/order
├── generate_invoice.rb
├── place.rb
├── prepare_data.rb
├── redeem_coupon.rb
└── send_order_email.rb
module Order
  class Place < ApplicationOrganizer
    organize do
      add Order::PrepareData
      add Order::GenerateInvoice
      add Order::RedeemCoupon
      add Order::SendOrderEmail
    end
  end
end

This kinda works, but for an unknown reason, some interactors are skipped and I'm not sure why (in my case Order::PrepareData)

[1] pry(main)> Order::Place.organize
=> #<ActiveInteractor::Organizer::InteractorInterfaceCollection:0x00007fbc280220d8
 @collection=
  [#<ActiveInteractor::Organizer::InteractorInterface:0x00007fbc28030c50 @filters={}, @interactor_class=Order::GenerateInvoice, @perform_options={}>,
   #<ActiveInteractor::Organizer::InteractorInterface:0x00007fbc28030020 @filters={}, @interactor_class=Order::RedeemCoupon, @perform_options={}>,
   #<ActiveInteractor::Organizer::InteractorInterface:0x00007fbc26cc3398 @filters={}, @interactor_class=Order::SendOrderEmail, @perform_options={}>]>

If I rename class to PrepareStuff it works fine.

P.S. I'm new to Ruby, so I might be doing something wrong.

Allow for context class definition

Elevator pitch, describe and sell us your feature request

As a Developer,
I want to be able to define custom context classes in my interactors
so that I can have greater control and extendibility over my interactors.

Is your feature request related to a problem

See discussion on #74

Have you considered any alternatives

Additional Comments

If some of the interactors of the organizer fail error message is not persisted.

If some of the interactors of the organizer fail context.fail!('Error Message') error message is not persisted.

[10] pry(main)> stripe = StripeCustomer::UpdateCustomer.perform(user: user, params: params)
stripe.success?
=> false

[10] pry(main)> stripe.errors
=> #<ActiveModel::Errors:0x00007fa730422528
 @base=
  #<StripeCustomer::UpdateCustomer::Context user=#<User id: 104..>, params={...}>,
 @details={},
 @messages={}>

Initially reported in #167

Deprecation Logging

Elevator pitch, describe and sell us your feature request

As a developer,
I want an easy way to notify other developers about deprecations
so that I can warn developers of deprecated methods.

Is your feature request related to a problem

In order to refactor status outside the responsibilities of the context object for #135 in a backwards compatible fashion we are going to need to deprecate methods that currently live in ActiveInteractor::Context::Status

Have you considered any alternatives

We could use ActiveSupport::Deprecation for this.

Additional Comments

It is possible ActiveSupport::Deprecation might not be enough to achieve what we want as some of the methods won't have replacement methods. Release horizion should be set to 2.0

AI-10

Configurable directory name

Elevator pitch, describe and sell us your feature request

As a developer I would like the directory interactors generate in to be configurable.

Is your feature request related to a problem?

The ActiveInteractor gem is opinionated on where interactors should live within my application. As a developer I should be able to dictate where what directory interactors are generated in.

Parallel interactor performance in organizers

Elevator pitch, describe and sell us your feature request

I would like to write parallel processing using Interactor.
At that time, I would like to have an Organizer that manages parallel processing like Organizer::Parallel

Is your feature request related to a problem?

Have you considered any alternatives?

Additional Comments

see collectiveidea/interactor#164

Add argument to install generator

Elevator pitch, describe and sell us your feature request

As a developer I would like to provide an argument to the install generator to specify what directory interactors should live in.

Is your feature request related to a problem?

The current expectation is to run rails g active_interactor:install and if I wish to have my interactors live in a directory other than app/interactors I need to edit the generated initializer, remove the autoload line from config/application.rb, delete the created directory, and re-run the generator. This is awkward at best, and can be easily cleaned up by providing an optional argument to the install generator.

Have you considered any alternatives?

Additional Comments

Exclude config files from codeclimate

Add the following files to the .codeclimate.yml exclude patterns:

  • .codeclimate.yml
  • .dockerignore
  • .gitignore
  • .mdlrc
  • .rubocop.yml
  • .travis.yml
  • .yardopts
  • Dockerfile
  • Gemfile
  • Gemfile.lock
  • Rakefile
  • activeinteractor.gemspec
  • bin/*
  • docker-compose.yml
  • mdl_style.rb

Fix opinionated initializer in ActiveInteractor::Models

The ActiveInteractor::Models initializer introduced in #127 is somewhat opinionated in that it expects the object to respond to either to_h or attributes this somewhat couples the initializer with ActiveRecord which would hinder us from being able support other orms should we choose to do so at a later time. Find a way to make this initializer less opinionated and refactor it.

Proposal for new Context pattern

Problem

Currently when a class inherits from ActiveInteractor::Base a context class is created and validation and attribute methods are delegated from the interactor to the context class. I wonder if this method of delegation is too "magic" or too confusing.

Proposal

I propose a new pattern for handling context. I would like to expect a context class be created in addition to the interactor class with a given naming convention. For example given an interactor named MyInteractor the gem could expect a second class MyInteractorContext to exist and if it cannot find that class it would fallback to a generic context class with no validation or attribute methods. The expectation would be instead of going the route of delegation through the interactor with methods like context_validates all validation and attribute methods would be called on the context class directly. The generators in the gem could make this easy when developing with rails.

so instead of the current pattern:

class MyInteractor < ActiveInteractor::Base
  context_attributes :first_name, :last_name, :email
  context_validates :email, presence: true

  def perform
    ...
  end
end

context = MyInteractor.perform(email: '[email protected]', first_name: 'foo', last_name: 'bar')
#=> <# MyInteractor::Context ...>

the pattern could be:

class MyInteractorContext < ActiveInteractor::Context::Base
  attributes :first_name, :last_name, :email
  validates :email, presence: true
end

class MyInteractor < ActiveInteractor::Base
  def perform
    ...
  end
end

context = MyInteractor.perform(email: '[email protected]', first_name: 'foo', last_name: 'bar')
#=> <# MyInteractorContext ...>

The goal here is to provide clarity on where these validations occur.

Things to consider before answering

  • What are your thoughts on this proposed pattern?
  • What are your thoughts on appropriate naming conventions (currently MyInteractor::Context is what is created)?
  • Would having the context class as an actual class make the validation and attribute methods less confusing?

Support Other ORMs

Elevator pitch, describe and sell us your feature request

As a rails developer,
I want support for other ORMs.
so that I can experience the same magic provided to ActiveRecord without using ActiveRecord.

User Stories

  • #156 Add support for Mongoid ORM
  • #158 Add support for Dynamoid ORM

Organizer before_each_interactor callback

Elevator pitch, describe and sell us your feature request

As a developer I would like a callback method to provide callbacks that need to be performed, before, after, and around each interactor perform in an organizer.

ActiveInteractor::Railtie

Elevator pitch, describe and sell us your feature request

As a developer of ActiveInteractor,
I want A railtie
so that developers of the gem can configure ActiveInteractor to their liking.

Rolling back previous interactors does not update organizer context

class FooInteractor < ActiveInteractor::Base
  def perform
    context.foo = "hello"
  end

  def rollback
    puts 'Rolling Back FooInteractor'
    context.foo = "Hi"
    puts "FooInteractor foo => #{context.foo}"
  end
end

class BarInteractor < ActiveInteractor::Base
  def perform
    context.bar = 'earth'
    context.fail!
  end

  def rollback
    puts 'Rolling Back BarInteractor'
    context.bar = 'world'
    puts "BarInteractor bar => #{context.bar}"
  end
end

class TestOrganizer < ActiveInteractor::Organizer::Base
  organize do
    add :foo_interactor
    add :bar_interactor
  end
end

Current Behavior

result = TestOrganizer.perform
# Rolling Back BarInteractor
# BarInteractor bar => world
# Rolling Back FooInteractor
# FooInteractor foo => Hi

puts result
# #<TestOrganizer::Context foo="hello", bar="world">

Expected Behavior

result = TestOrganizer.perform
# Rolling Back BarInteractor
# BarInteractor bar => world
# Rolling Back FooInteractor
# FooInteractor foo => Hi

puts result
# #<TestOrganizer::Context foo="Hi", bar="world">

Additional Comments

Rolling back BarInteractor changes TestOrganizer::Context.bar from earth to world while rolling back FooInteractor does not change TestOrganizer::Context.foo from Hello to Hi

classify is called on const arguments

Current Behavior

When passing a Class or Module to ActiveInteractor::Organizer::Base.organize or ActiveInteractor::Base.contextualize_with the class name is mutated by String#classify.

Expected Behavior

When I pass a Class or Module to a method I expect the class or module to be returned correctly without mutation.

Steps to Reproduce

  1. Create an interactor named PlaceData
  2. Create an organizer that organizes PlaceData
  3. inspect the organizer's organized interfaces
  4. Notice PlaceData is missing from the collection.

Additional Comments

In the reproduction steps PlaceData is missing because classify forces the InteractorInterface to search for PlaceDatum. Calling classify on a passed const will convert the const to a string and then singularize that string. If a class or module is passed as an argument we should rely on NameError to protect us from invalid constants and not run any mutation on the passed class or module.

see #167

Audit documentation

Audit all documentation and ensure:

  • Documentation is accurate
  • All public methods and modules are documented with examples

[Research] Railtie

I've found the documentation for Railtie surprisingly lack luster. I would rather add railties as an explicit dependency for the gem but have been unable to get the railtie to do the things I want it to do.

A few things I'd like to accomplish:

  • #121 Rails related configuration (i.e. directory, and context generation) as part of the railtie not a separate config class. (see: ActiveInteractor::Rails::Config)
  • #120 app.config.autoload_paths in a railtie initializer (to autoload the chosen interactor directory)
  • #101 & #119 helper method injection for ActionController and ActiveRecord

Problems I'm having:

  • part of the problem is the gem name is activeinteractor but we need to require active_interactor, I've gotten around this with the install generator creating an initializer that requires active_interactor however I'm not 100% sure when this gets loaded during boot.

Research and create a POC Railtie class that accomplishes all these things.

Attribute changes cause values from incoming context to be missed on merge

Current Behavior

Attributes are missed when merging an incoming context into another context. This was discovered when using an organizer.

Expected Behavior

Either all values should be copied into the context or only explicitly named attributes, depending on design goals.

Steps to Reproduce

I've discovered a bug in this PR that isn't covered by a spec: when you are using an organizer, the context values in the organizer's steps don't get initialized properly. Basic case:

class TestInteractor < ApplicationInteractor
  def perform
    p context
    p context['user']
    p context.user
  end
end

class TestInteractorContext < ApplicationContext
  attributes :user
end

class TestOrganizer < ApplicationInteractorOrganizer
  organize :test_interactor
end

TestOrganizer.perform(user: 'foo')

Output before change:

#<TestInteractorContext user="foo">
"foo"
"foo"
TestOrganizer::Context {
    :user => "foo"
}

Output after change:

#<TestInteractorContext user="foo">
"foo"
nil
TestOrganizer::Context {
    :user => "foo"
}

Additional Comments

A branch with modified attributes code that only copies over named attributes is available at https://github.com/dark-panda/activeinteractor/tree/attribute-merging-fixes, but it is known to be incomplete pending some design decisions.

Move rails related configuration to Railtie

Elevator pitch, describe and sell us your feature request

As a developer,
I want rails related configuration options in the Railtie
so that I don't have to have a completely separate configuration object for rails.

Is your feature request related to a problem

Have you considered any alternatives

Additional Comments

We should try to do this in a way that doesn't involve adding an explicit dependency on railties for the gem.

ActiveRecord helper methods

Elevator pitch, describe and sell us your feature request

As a developer,
I want to be able to use my ActiveRecord models as context classes
so that I don't need to create separate context classes for my interactors when the output is just going to be fed to a model anyway.

Is your feature request related to a problem

Have you considered any alternatives

Additional Comments

We should provide a helper method for ActiveRecord models, something like acts_as_context that would include ActiveInteractor::Context::Base status methods (i.e. #fail!, #called, etc...). This way we could call the contextualize_with method in a given interactor and set the value to one of our ActiveRecord model classes.

Refactor context alias attributes

Right now aliased attributes for a context will override an aliased key with the mapped key in attribute_aliases.

class MyInteractor < ActiveInteractor::Base
  context_attribute_aliases last_name: %i[sir_name sirname]
end

context = MyInteractor.perform(sir_name: 'Allen')
context.sir_name #=> nil
context.last_name #=> 'Allen'

this can prove to be problematic if the context was passed into a class expecting the attribute sir_name.

class User < ApplicationRecord
  validates :sir_name, presence: true
end

context = MyInteractor.perform(sir_name: 'Allen')
user = User.new(context)
user.valid? #=> false
user.errors[:sir_name] #=> "can't be blank"

This logic should be refactored to map the aliases used and revert back to them once the context has been completed. Additionally the private method aliased_key appears to smell.

Context.fail! error message gets pupulated 3 times with the same message

If interactor within organizer fails, messages and details get populated 3 items with the same message.

 @details={:context=>[{:error=>"Invalid value for eu_vat."}, {:error=>"Invalid value for eu_vat."}, {:error=>"Invalid value for eu_vat."}]},
 @messages={:context=>["Invalid value for eu_vat.", "Invalid value for eu_vat.", "Invalid value for eu_vat."]}

You can use code from #169 to reproduce the issue.

Thanks,

Proposal For New Interactor Pattern

Problem

During the discussion in #74 it occurred to me that there maybe an unnecessary fragmentation or friction with the way interactors and their contexts are currently defined.

Proposal

I propose a whole new pattern for interactor definition that would be some what similar to how rake tasks are written in a given project. The idea would be you would define an interactor namespace like :user and within that namespace you would define a set of contexts and a set of interactors like this:

# interactors/user.rb

ActiveInteractor::InteractorNamespace.new(:user) do
  
  # we define a default interactor context
  # this context would be used by all interactors in this namespace
  # unless the interactor specifically specifies otherwise  
  context do
    attributes :first_name, :last_name, :email, :user
  end
 
  context :user_and_account do
    attributes :account, :user
    validates :account, on: :called
  end

  context :create_account do
    attributes :account, :user
    validates :user, presence: true, on: :calling 
  end
  
  # defining an interactor would be the equivalent of defining the #perform
  # method in current interactor classes. 
  # this interactor would use the default context as it doesn't
  # specify one nor is there a context with a matching name
  interactor :finder do |context|
    context.user = User.find_by(
      email: context.email,
      first_name: context.first_name, 
      last_name: context.last_name
     )
  end
  
  # this interactor would use the default context as it doesn't
  # specify one nor is there a context with a matching name
  interactor :downcase_email do |context|
    context.email = context.email&.downcase
  end
  
  # this interactor has a dependency on another interactor
  interactor creator: %i[downcase_email] do |context|
    context.user ||= User.create(
      email: context.email,
      first_name: context.first_name, 
      last_name: context.last_name
    )
  end

  # we don't need to specify a context here it will
  # use the :create_account context by default
  interactor :create_account do |context|
    context.account = context.user.generate_account!
  end

  # we can define an organizer that specifies a context
  organizer :create_with_account, contextualize_with: :user_and_account do
    organize :finder, :creator, :create_account
  end
end

given this pattern we can then just call a single simple api to invoke the interaction like this:

context = ActiveInteractor.perform(
  :'user:create_with_account', 
  email: '[email protected]', 
  first_name: 'Aaron', 
  last_name: 'Allen'
)

context.success? #=> true
context #=> <# Interactor::User::UserAndAccountContext ...>

additionally we can call a different interactor within that namespace

context = ActiveInteractor.perform(
  :'user:finder', 
  email: '[email protected]', 
  first_name: 'Aaron', 
  last_name: 'Allen'
)

context.success? #=> true
context #=> <# Interactor::User::DefaultContext ...>

Additionally we could even provide helper methods for rails ActionController::Base so that this:

# user_controller.rb
def create
  result = ActiveInteractor.perform(:'user:create_with_account', user_params)
  if result.success?
    render json: result.user, status: :created
  else
    render json: { errors: result.user.errors }, status: :unprocessable_entity
  end
end

could be refactored to this:

# user_controller.rb
def create
  render_interactor_result_json(:'user:create_with_account', user_params)
end

The goal here would be to provide a single api for every interactor in your project something like:

ActiveInteractor.perform(interactor_name, context_attributes = {})

Things to consider before answering

  1. Do you think this pattern would be overall a better approach for the interactor pattern?
  2. Would you find value in being able to call one method to run all of your interactors?

Use ActiveModel::Attributes instead of custom implementation

Elevator pitch, describe and sell us your feature request

As a rails developer,
I want to be able to expect a similar api as ActiveModel::Attributes for Context::Base
so that I can utilize common testing libraries like shoulda-matchers

Is your feature request related to a problem

This was originally requested by @dark-panda on reddit: https://www.reddit.com/r/rails/comments/eu4z1b/activeinteractor_v100_release/ffnzmy3?utm_source=share&utm_medium=web2x

Have you considered any alternatives

Additional Comments

This should be done in a backwards compatible manor. I don't want to have to bump the major version for this functionality at this time.

The reason for the custom functionality is that Context::Base inherits from OpenStruct and the overall goal of the Context::Attributes was to provide a mechanism for explicitly returning the desired attributes on the context object instead of all the actual attributes defined on the object.

class Context < ActiveInteractor::Context::Base
  attributes :foo
end

context = Context.new(foo: 'foo', bar: 'bar')
context.attributes
#=> { foo: 'foo' }

context.bar
#=> 'bar'

Attribute Default Value

Elevator pitch, describe and sell us your feature request

As a rails developer,
I want to be able to define default value to a specific attribute
so that I can have a dry code for default usage

Is your feature request related to a problem

I'm always frustrated when I pass variables every time to make the command dynamic, when most of the time these variables can fall back to defaults.

class MyInteractorContext < ActiveInteractor::Context::Base
  attribute :locale, default: -> { I18n.locale }
  attribute :year, default: -> { Date.today.year }
  attribute :format, default: :json
end

Have you considered any alternatives

Additional Comments

Following active model practices active_model/attributes.rb#L25

Generally being able to define a specific attribute can enable more functionality like: adding type_cast. Example: Typecasting a checkbox parameter to boolean

Test helpers/matchers

Elevator pitch, describe and sell us your feature request

As a developer I would like some test helper methods and matchers for the ActiveInteractor gem.

Additional Comments

Proposed Helpers:
  • stub_successful_context - mock a successful context for a given interactor.
  • stub_failed_context - mock a failed context for a given interactor.
Proposed Matchers:
  • shoulda-matchers for context.
  • match_context_schema - validate context has matching properties

Reduce the responsibility of Context

Elevator pitch, describe and sell us your feature request

Based on this comment left on reddit by janko-m.

I haven't used the Interactor gem before (my eyes are only on dry-rb now), but reading its source code I'm not convinced it has a good foundation.

The Interactor::Context object seems to have three responsibilities: receiving input, writing input, and marking failure. Moreover, it subclasses OpenStruct, which means I can say goodbye to typo detection.

Taking the example from the readme, I would write it as follows with dry-monads and dry-matcher:

require "dry/monads"
require "dry/matcher"
require "dry/matcher/result_matcher"

class AuthenticateUser
  include Dry::Monads[:result]
  include Dry::Matcher.for(:call, with: Dry::Matcher::ResultMatcher)

  def self.call(*args, &block)
    new.call(*args, &block)
  end

  def call(email:, password:)
    user = User.authenticate(email, password)

    if user
      Success(user: "user", token: "token")
    else
      Failure(message: "authenticate_user.failure")
    end
  end
end

AuthenticateUser.call(email: "[email protected]", password: "secret") do |m|
  m.success do |user:, token:|
    session[:user_token] = token
    redirect_to user
  end

  m.failure do |message:|
    flash.now[:message] = message
    render :new
  end
end

I don't think we need another implementation of result objects.

Is your feature request related to a problem

While they seem to be referencing the interactor gem; Janko brings up a valid point in that Context currently carries too many responsibilities. We could reduce these responsibilities by moving the called!, fail! and rollback! functionality out of the context object. This could instead potentially be handled by the interactors themselves or some sort of state object.

Have you considered any alternatives

Additional Comments

Issues in this epic

Increase test coverage

Increase project test coverage to at least 95%

  • #4 Increase test coverage of lib/active_interactor/context.rb
  • #5 Increase test coverage of lib/active_interactor/interactor/worker.rb
  • #6 Increase test coverage of lib/active_interactor/organizer.rb
  • #8 Test lib/rails/generators
  • #9 Exclude config files from codeclimate

Attribute arguments for context generators

Elevator pitch, describe and sell us your feature request

As a developer,
I want to be able to give the Context generator attribute arguments
so that attributes are automatically defined on my context class when it is generated.

Is your feature request related to a problem

It would be nice to be able to generate an interactor with a given set of attributes and have the generator automatically populate those attributes:

rails generate interactor MyInteractor first_name last_name
# app/interactors/my_interactor_context.rb
class MyInteractorContext < ApplicationContext
  attributes :first_name, :last_name
end

# app/interactors/my_interactor.rb
class MyInteractor
  def perform
    # TODO implement MyInteractor call
  end
  
  def rollback
    # TODO implement MyInteractor rollback
  end
end

Configurable context pattern

Elevator pitch, describe and sell us your feature request

As a developer,
I want to be able to configure which context pattern I want to use
so that Rails generators don't generate unnecessary classes if I don't want to use them.

Is your feature request related to a problem

It's frustrating that the generators automatically create context classes for me when I wish to use the interactor only pattern i.e.:

class MyInteractor < ApplicationInteractor
  context_attributes ...
  context_validates ...
end

Update README after v1.0.0 release

#112 update the README with instructions on how to install the beta and linked to the current stable version's documentation. Remove the note linking to the current stable documentation and the --pre install instructions after the gem is out of beta.

Configurable directory name

Elevator pitch, describe and sell us your feature request

As a developer,
I want to be able to configure which directory interactors are generated in
so that I can choose where my interactors live

Organizers not returning false for success on context failure

Current Behavior

Organizers are not accurately returning context success status

Expected Behavior

Organizers should not be successful on context failure

Steps to Reproduce

  1. Create an organizer
  2. Fail the context in the first interactor

Additional Comments

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.