Project

smelter

0.0
No commit activity in last 3 years
No release in over 3 years
This is the code that stretched.io uses for dynamic scripting. As with anything that calls instance_eval on code from a data store, use cautiously.
2005
2006
2007
2008
2009
2010
2011
2012
2013
2014
2015
2016
2017
2018
2019
2020
2021
2022
2023
2024
 Dependencies

Development

~> 1.10
~> 10.0
>= 0

Runtime

 Project Readme

Smelter

Smelter is a small gem that has a pretty specific use case. You can store scripts and extensions in a data store (redis, postgres, or anything else) and then use that stored code to dynamically mutate a shared context.

All of the caveats around context_evaling some code from a data store apply.

Installation

Add this line to your application's Gemfile:

gem 'smelter'

And then execute:

$ bundle

Or install it yourself as:

$ gem install smelter

Usage

The classes in spec/support/test_classes.rb and the specs will tell you all you need to know about how this works. But here's an overview, with code from the specs.

Consider the following extension and script:

  Test::Extension.define "test/my_extension" do
    extension do
      def subtract(a, b)
        a - b
      end
    end
  end

  Test::Script.define "test/my_script" do
    extensions 'test/*'

    script do
      number do |context|
        context['number'] * 10
      end

      subtraction_result do |context|
        subtract(context['number'], 1)
      end
    end
  end

Now imagine that the extension and script above are stored in some data store, like redis or postgres. You then can do something like the following:

  # Find the script by name in the database, and get a ScriptRunner
  # object that has the script's extensions defined on it.
  runner = Test::Script.runner("test/my_script")

  # Prepare a context Hash (or Struct) that the script can mutate
  # by running the Procs associated with each context attribute from
  # top to bottom.
  context = { 'number' => 5 }

  # Mutate the context by running the script on it.
  runner.run(context)

  # Results!
  context
  #=> { 'number' => 50, 'subtraction_result' => 49 }

Like I said, a pretty specific use case.

Stretched.io uses uses this code to prepare JSON objects from web pages by extracting different attributes using Nokogiri and the Buzzsaw DSL.

Here's some actual code that I use with Stretched:

Stretched::Script.define "globals/scripts/product_page" do
  extensions 'globals/extensions/*'

  script do
    title do |context|
      next unless context['title'].present?
      context['title'].squeeze(' ')
    end

    availability do |context|
      if %w(AuctionListing ClassifiedListing).include?(context['type'])
        "in_stock"
      else
        context['availability'].try(:downcase)
      end
    end

    image do |context|
      if context['image']
        clean_up_image_url(context['image'])
      end
    end

    price_in_cents do |context|
      convert_dollars_to_cents(context['price_in_cents'])
    end
  end
end

For the above, I populate the context hash with values extracted from a product web page using buzzsaw and nokogiri. Then I go back over with the script and clean up the data in the context hash, which eventually becomes a JSON object that the platform enqueues for a user to be able to get the results of a web scrape.

The methods convert_dollars_to_cents and clean_up_image_url are defined in one of the extensions that the script loads under globals/extensions/*. Notice that the gem uses globbing to find extensions in the total namespace of extensions.

Development

After checking out the repo, run bin/setup to install dependencies. Then, run rake rspec to run the tests. You can also run bin/console for an interactive prompt that will allow you to experiment.

To install this gem onto your local machine, run bundle exec rake install. To release a new version, update the version number in version.rb, and then run bundle exec rake release, which will create a git tag for the version, push git commits and tags, and push the .gem file to rubygems.org.

Contributing

Bug reports and pull requests are welcome on GitHub at https://github.com/[USERNAME]/smelter.

License

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