Giter Club home page Giter Club logo

active_interaction's People

Contributors

aaronlasseigne avatar antulik avatar camdez avatar caseywebdev avatar croesnick avatar erickguan avatar heka1024 avatar imhide avatar ivdma avatar jonian avatar jonkgrimes avatar limeblast avatar lulalala avatar matiasasis avatar mdwagner avatar mfazekas avatar ngan avatar nilcolor avatar r4mbo7 avatar ramirovarandas avatar reona5 avatar skunkworker avatar spaghetticode avatar spencersteiner avatar techpeace avatar tfausak avatar tjwallace avatar tomasdundacek avatar unhappychoice 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  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

active_interaction's Issues

Can't list attributes in block

You can't list multiple attributes inside a block:

class Interaction < ActiveInteraction::Base
  hash :a do hash :b, :c end
  def execute; end
end
Interaction.run!(a: { b: {}, c: {} })
# => .../active_interaction/lib/active_interaction/filter_method.rb:10:in `dup': can't dup Symbol (TypeError)

Can't nest hashes

class HashInteraction < ActiveInteraction::Base
  hash :a do; hash :b end
end
HashInteraction.run(a: { b: {} })
# => in `hash': wrong number of arguments(1 for 0) (ArgumentError)

Local documentation is ugly

<span class="line-numbers"><a href="#n1" name="n1">1</a></span>gem 'active_interaction', '~> 0.1.0'

This is basically because we switched to kramdown (due to #9). Everything looks find on RubyDoc.info (which is weird), but locally it looks like garbage.

Build broken in JRuby in Rubinius

In a nutshell, they don't like the file filter.

  • JRuby: https://travis-ci.org/orgsync/active_interaction/jobs/8945563

    1) ActiveInteraction::FileFilter#prepare(key, value, options = {}) behaves like options includes :allow_nil options :allow_nil is true allows the options to be set to nil
       Failure/Error: expect(described_class.prepare(:key, nil, allow_nil: true)).to eq nil
       NoMethodError:
         undefined method `[]' for nil:NilClass
       Shared Example Group: "options includes :allow_nil" called from ./spec/active_interaction/filters/file_filter_spec.rb:5
       # ./lib/active_interaction/filter.rb:15:in `prepare'
       # ./lib/active_interaction/filters/file_filter.rb:9:in `prepare'
       # ./spec/support/filters.rb:6:in `(root)'
    2) ActiveInteraction::FileFilter#prepare(key, value, options = {}) behaves like options includes :allow_nil options :allow_nil is false throws an error
       Failure/Error: expect {
         expected ActiveInteraction::MissingValue, got #<NoMethodError: undefined method `[]' for nil:NilClass> with backtrace:
           # ./lib/active_interaction/filter.rb:15:in `prepare'
           # ./lib/active_interaction/filters/file_filter.rb:9:in `prepare'
           # ./spec/support/filters.rb:13:in `(root)'
           # ./spec/support/filters.rb:12:in `(root)'
       Shared Example Group: "options includes :allow_nil" called from ./spec/active_interaction/filters/file_filter_spec.rb:5
       # ./spec/support/filters.rb:12:in `(root)'
    3) FileInteraction behaves like an integration interaction with required option "a" returns the correct value
       Failure/Error: expect(response).to eq a
    
         expected: #<File:/home/travis/build/orgsync/active_interaction/spec/active_interaction/integration/file_interaction_spec.rb>
              got: nil
    
         (compared using ==)
       Shared Example Group: "an integration interaction" called from ./spec/active_interaction/integration/file_interaction_spec.rb:9
       # ./spec/support/interactions.rb:27:in `(root)'
    
  • Rubinius: https://travis-ci.org/orgsync/active_interaction/jobs/8945564

    1) ActiveInteraction::FileFilter#prepare(key, value, options = {}) behaves like options includes :allow_nil options :allow_nil is true allows the options to be set to nil
       Failure/Error: expect(described_class.prepare(:key, nil, allow_nil: true)).to eq nil
       Rubinius::InvalidBytecode:
         more arguments than local slots - method prepare
       Shared Example Group: "options includes :allow_nil" called from ./spec/active_interaction/filters/file_filter_spec.rb:5
       # ./spec/support/filters.rb:6:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    2) ActiveInteraction::FileFilter#prepare(key, value, options = {}) behaves like options includes :allow_nil options :allow_nil is false throws an error
       Failure/Error: expect {
         expected ActiveInteraction::MissingValue, got #<Rubinius::InvalidBytecode: more arguments than local slots> with backtrace:
           # ./spec/support/filters.rb:13:in `__script__'
           # kernel/bootstrap/proc.rb:22:in `call'
           # ./spec/support/filters.rb:12:in `__script__'
           # kernel/common/eval19.rb:45:in `instance_eval'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/proc.rb:22:in `call'
           # kernel/loader.rb:734:in `run_at_exits'
           # kernel/loader.rb:754:in `epilogue'
           # kernel/loader.rb:887:in `main'
       Shared Example Group: "options includes :allow_nil" called from ./spec/active_interaction/filters/file_filter_spec.rb:5
       # ./spec/support/filters.rb:12:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    3) ActiveInteraction::FileFilter#prepare(key, value, options = {}) value is a File passes it on through
       Failure/Error: let(:result) { described_class.prepare(key, value, options) }
       Rubinius::InvalidBytecode:
         more arguments than local slots - method prepare
       # ./spec/active_interaction/filters/file_filter_spec.rb:10:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/active_interaction/filters/file_filter_spec.rb:16:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    4) ActiveInteraction::FileFilter#prepare(key, value, options = {}) value is not nil throws an error
       Failure/Error: expect { result }.to raise_error ActiveInteraction::InvalidValue
         expected ActiveInteraction::InvalidValue, got #<Rubinius::InvalidBytecode: more arguments than local slots> with backtrace:
           # ./spec/active_interaction/filters/file_filter_spec.rb:10:in `__script__'
           # kernel/common/hash19.rb:256:in `fetch'
           # ./spec/active_interaction/filters/file_filter_spec.rb:24:in `__script__'
           # kernel/bootstrap/proc.rb:22:in `call'
           # ./spec/active_interaction/filters/file_filter_spec.rb:24:in `__script__'
           # kernel/common/eval19.rb:45:in `instance_eval'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/array19.rb:18:in `map'
           # kernel/bootstrap/proc.rb:22:in `call'
           # kernel/loader.rb:734:in `run_at_exits'
           # kernel/loader.rb:754:in `epilogue'
           # kernel/loader.rb:887:in `main'
       # ./spec/active_interaction/filters/file_filter_spec.rb:24:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    5) FileInteraction behaves like an integration interaction is invalid without required options
       Failure/Error: let(:outcome) { described_class.run(options) }
       Rubinius::InvalidBytecode:
         more arguments than local slots - method prepare
       Shared Example Group: "an integration interaction" called from ./spec/active_interaction/integration/file_interaction_spec.rb:9
       # ./lib/active_interaction/base.rb:231:in `method_missing'
       # ./lib/active_interaction/base.rb:63:in `run'
       # ./spec/support/interactions.rb:3:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/support/interactions.rb:20:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    6) FileInteraction behaves like an integration interaction with required option "a" returns the correct value
       Failure/Error: let(:outcome) { described_class.run(options) }
       Rubinius::InvalidBytecode:
         more arguments than local slots - method prepare
       Shared Example Group: "an integration interaction" called from ./spec/active_interaction/integration/file_interaction_spec.rb:9
       # ./lib/active_interaction/base.rb:231:in `method_missing'
       # ./lib/active_interaction/base.rb:63:in `run'
       # ./spec/support/interactions.rb:3:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/support/interactions.rb:4:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/support/interactions.rb:27:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    7) FileInteraction behaves like an integration interaction with required option "a" with optional option "b" returns the correct value
       Failure/Error: let(:outcome) { described_class.run(options) }
       Rubinius::InvalidBytecode:
         more arguments than local slots - method prepare
       Shared Example Group: "an integration interaction" called from ./spec/active_interaction/integration/file_interaction_spec.rb:9
       # ./lib/active_interaction/base.rb:231:in `method_missing'
       # ./lib/active_interaction/base.rb:63:in `run'
       # ./spec/support/interactions.rb:3:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/support/interactions.rb:4:in `__script__'
       # kernel/common/hash19.rb:256:in `fetch'
       # ./spec/support/interactions.rb:34:in `__script__'
       # kernel/common/eval19.rb:45:in `instance_eval'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/array19.rb:18:in `map'
       # kernel/bootstrap/proc.rb:22:in `call'
       # kernel/loader.rb:734:in `run_at_exits'
       # kernel/loader.rb:754:in `epilogue'
       # kernel/loader.rb:887:in `main'
    

Add documentation for custom filters?

It's possible to add your own filters, but that feature is not documented. For instance, if I wanted a filter that always set the value to 'x', it would look like this:

module ActiveInteraction
  class XFilter < Filter
    def self.prepare(key, value, options = {}, &block)
      'x'
    end
  end
end

Then I could use it in an interaction:

class Interaction < ActiveInteraction::Base
  x :a
  def execute; a end
end
p Interaction.run!(a: 'y?')
# => "x"

Assigning attributes can nil them out

This is distressing, to say the least:

class Interaction < ActiveInteraction::Base
  boolean :a
  def execute; a = a end
end
p Interaction.run!(a: true)
# => nil

Fail faster when defining invalidly nested defaults

For array and hash filters, it's invalid to set defaults on nested attributes. However, we don't catch that error until you call run. As noted in the specs, we should raise an error when the class is defined.

For instance, this code should raise an ArgumentError:

class InvalidInteraction < ActiveInteraction::Base
  array :a do
    array default: []
  end
end

As it is, you'd have to call InvalidInteraction.run(a: []) to get that to fail.

Add support for files uploaded through Rails params.

[2] pry> params[:file]
#<ActionDispatch::Http::UploadedFile:0x007fb0cfc68428 @content_type="text/plain", @original_filename="test.txt", @tempfile=#<File:/var/folders/r4/f5d85zsd007fnwjbspj2nbb80000gn/T/RackMultipart20130711-83548-djpvl6>, @headers="Content-Disposition: form-data; name=\"file\"; filename=\"test.txt\"\r\nContent-Type: text/plain\r\n">
[3] pry> params[:file].tempfile
#<File:/var/folders/r4/f5d85zsd007fnwjbspj2nbb80000gn/T/RackMultipart20130711-83548-djpvl6>
-rw-------  1 aaron  staff  4 Jul 11 14:42 /var/folders/r4/f5d85zsd007fnwjbspj2nbb80000gn/T/RackMultipart20130711-83548-djpvl6
[4] pry> params[:file].tempfile.class
Tempfile < #<Class:0x007fb0e3c835c0>

Hash filters don't work

class ExampleInteraction < ActiveInteraction::Base
  hash :h
  def execute; end
end
outcome = ExampleInteraction.run(h: {})
/Users/t/Documents/GitHub/orgsync/active_interaction/lib/active_interaction/filter.rb:7:in `factory': NoMethodError (NoMethodError)
    from /Users/t/Documents/GitHub/orgsync/active_interaction/lib/active_interaction/base.rb:208:in `method_missing'
    from /Users/t/Documents/GitHub/orgsync/active_interaction/lib/active_interaction/base.rb:162:in `hash'
    from example.rb:4:in `<class:ExampleInteraction>'
    from example.rb:3:in `<main>'

How do you compose interactions?

Composing interactions leaves a little to be desired.

class AlphaInteraction < ActiveInteraction::Base
  integer :alpha, default: 0
  validates :alpha, numericality: { odd: true }
  def execute; alpha end
end

class BetaInteraction < ActiveInteraction::Base
  model :outcome, class: ActiveInteraction::Base
  validate :validator
  def execute; outcome.result end
  def validator
    errors.add(:outcome, 'invalid') if outcome.invalid?
  end
end

p BetaInteraction.run!(outcome: AlphaInteraction.run(alpha: 1))
# => 1

p BetaInteraction.run!(outcome: AlphaInteraction.run)
# => Outcome invalid (ActiveInteraction::InteractionInvalid)

How should they behave when composed?

Possible to overwrite response

class Interaction < ActiveInteraction::Base
  boolean :response # can be any type
end

Interaction.run('response' => 0).response
# => 0
Interaction.run(response: 0)
# => ArgumentError

Strip keys from hashes?

Mutations removes keys that you didn't tell it to expect from hashes:

class Mutation < Mutations::Command
  required { hash :h }
  def execute; h end
end
p Mutation.run!(h: { b: true })
# => {}

We currently don't do that:

class Interaction < ActiveInteraction::Base
  hash :h
  def execute; h end
end
p Interaction.run!(h: { b: true })
# => {"b"=>true}

Should we?

explicitly sent nil values should be converted to a default if provided

class Foo < ActiveInteraction::Base
  string :query, default: ''

  def execute; end
end

Foo.run(query: nil).errors.full_messages
["Query is required"]

There are times where a parameter is not posted to the page and the interaction has a default for it. Does it make sense to view an explicitly provided nil as permission to use the default?

Support timezones

We should probably check to see if Time responds to zone and use that if it's available.

Add integration tests

We need end-to-end integration tests for the interactions. Although we have all the parts unit tested, we need to make sure they all play nice together.

Add errors instead of raising exceptions

class ExampleInteraction < ActiveInteraction::Base
  date :date
  def execute; end
end

That should add an error if the user inputs "2001" instead of raising an exception.

Add ability to document filters

Similar to #44, I'd love to be able to add programmatically-accessible documentation to individual attributes. This would require adding the ability to inspect an interaction's fitlers programmatically, too. Something like this:

class Interaction < ActiveInteraction::Base
  boolean :a, desc: "It's an attribute, alright!"
  def execute; end
end

Interaction.inputs[:a]
# => "It's an attribute, alright!"

Possible to manually set the result

It's possible to set the @result instance variable and then call outcome.result on an invalid outcome.

class Interaction < ActiveInteraction::Base
  boolean :attribute
  validate do
    @result = 'result'
    errors.add(:attribute, 'invalid')
  end
end
outcome = Interaction.run(attribute: true)
outcome.invalid?
# => true
outcome.result
# => "result"

Can't specify certain attribute types

class Interaction < ActiveInteraction::Base
  hash :x
end
Interaction.run
# => in `hash': wrong number of arguments (1 for 0) (ArgumentError)
class Interaction < ActiveInteraction::Base
  date_time :x
end
Interaction.run
# => lib/active_interaction/attr.rb:6:in `factory': NoMethodError (NoMethodError)

Error messages for nested attributes are misleading

If you don't supply a required nested attribute, you'll get a confusing error message.

class Interaction < ActiveInteraction::Base
  hash :h do; boolean :b end
end
p Interaction.run(h: {}).errors.messages
# => {:h=>["is required"]}

Add ability to document interaction

I'd love it if I could add programmatically-accessible documentation to an interaction. I'm not sure how it would look, but something like this wouldn't be too bad (stolen from Grape):

class Interaction < ActiveInteraction::Base
  desc "It's an interaction, alright!"
  def execute; end
end

Interaction.desc
# => "It's an interaction, alright!"

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.