Giter Site home page Giter Site logo

invokr's Introduction

Invokr

Invoke methods with a consistent Hash interface. Useful for metaprogramming.

Basic Usage

Let's say you've got a method you want to call:

class BankAccount
  def add_transaction(amount, account_id:, description: '')
    # adds transaction
  end
end

You can invoke this method through the class interface with pure ruby. But sometimes you've got a Hash containing the parameters. This is where Invokr comes in:

bank_account = BankAccount.new
params = JSON.parse http_request.response_body
Invokr.invoke method: :add_transaction, on: bank_account, with: params

Behind the scenes, Invokr figured out how to translate that Hash into a method signature compatible with BankAccount#add_transaction.

You can also pass in procs to invokr:

my_proc = ->|a,b| { a + b }
Invokr.invoke proc: my_proc, with: { a: 2, b, 4 }

Using vs. With

If you supply arguments that the method doesn't know how to handle, an Invokr::ExtraArgumentsError is raised. This is because, in general, you can't supply extra arguments to a plain old ruby method. However, from time to time we want to be able to pass in extra arguments. You can use the using keyword in order to simulate the behavior of the splat (*) operator:

Invokr.invoke method: :add_transaction, on: bank_account, with: { amount: 12.34, account_id: 24, extra_arg: 'hey, there' }

Querying

Want to investigate the arguments of a method?

meth = Invokr.query_method bank_account.method(:add_transaction)

This will return an object that you can use to inspect the optional/required dependencies of a method:

meth.required_dependencies
=> [:amount, :account_id]
meth.optional_dependencies
=> [:description]

Limitations

Currently, more than one optional positional argument isn't supported. Consider:

def my_method arg1 = 'foo', arg2 = 'bar'
end

Without knowing how to parse the source code for #my_method, Invokr couldn't know what the default values are. And even if I brought in e.g. ruby_parser, I'd have to support lazy evaluation, for when you supply a method or constant as the default. This complexity is completely unneccessary when using keyword arguments, so I suggest using that approach for multiple defaults for now.

Pre-keyword argument hash defaults

Before ruby 2.x introduced keyword arguments, it was common to end your method signature with a default hash, e.g. def my_method args = {}. Invoker supports this by building a Hash out of all the unused arguments you passed in, and passing that into the optional argument.

Dependency injection

One of the use cases for Invokr is building abstract factories. In this case, you want to inspect the method signature of Object#initialize, but actually pass .new to the class to have it allocate memory and invoke the initializer for you. Check out test/dependency_injection_example_test.rb for how it is used. You can use a hash to serve as the registry of objects, or build your own custom resolver. Here's an example supplying a Hash as the registry:

class MyKlass
  attr :foo, :bar
  def initiailze foo, bar
    @foo, @bar = foo, bar
  end
end

Invokr.inject MyKlass, using: { foo: 'FOO', bar: 'BAR', baz: 'BAZ' }

Even though MyKlass doesn't depend on baz, because everything it did need was present in the using Hash, Invokr was able to instantiate an instance of MyKlass

Todo

  • Cleanup
  • Use the Invokr::Method object within the Invokr::Builder.

Contributing

  1. Fork it ( https://github.com/[my-github-username]/invokr/fork )
  2. Create your feature branch (git checkout -b my-new-feature)
  3. Commit your changes (git commit -am 'Add some feature')
  4. Push to the branch (git push origin my-new-feature)
  5. Create a new Pull Request

invokr's People

Contributors

ntl avatar thedrewbisset avatar

Stargazers

Ryan Rauh avatar  avatar Jeff Dickey avatar

Watchers

 avatar James Cloos avatar

invokr's Issues

Allowing extra arguments

First off, great gem! Thanks so much for open-sourcing this.

At the moment I'm having to run a forked version in order to support my use-case. I often need to invoke methods where I also provide extra arguments which are unused by the invoked method. It would be great if it was possible to specify at invoke-time whether or not an ExtraArgumentsError should be raised in this case.

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.