enzymator 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: a2ec2a4060b6cda9e9556c05b4feb7f8188b91ed
4
+ data.tar.gz: 5c01a79eed612fc1c63a7a496695ef5898e7f38f
5
+ SHA512:
6
+ metadata.gz: 0d7e5533db3223a545e7c175f3ffe65fa33e3d3e18c7469b1d2dd129a604fd386db91666120d8ea19d14149b7636dcfbe76c57478513bcad707a0d8ad8dc4592
7
+ data.tar.gz: f7200cc635e0c058d54fa50d8d28593b366f7ea5e61439d4b9c8d81e264b04ffe3a2574c12f79b369af35725707c13643806e85ac9c2c82b47b42ca4a2e25967
data/Gemfile ADDED
@@ -0,0 +1,10 @@
1
+ source 'http://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in enzymator.gemspec
4
+ gemspec
5
+
6
+ group :development, :test do
7
+ gem "rake", "~> 11.2"
8
+ gem "minitest", "~> 5.9"
9
+ gem 'pry-byebug'
10
+ end
data/Gemfile.lock ADDED
@@ -0,0 +1,33 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ enzymator (0.0.1)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ byebug (9.0.5)
10
+ coderay (1.1.1)
11
+ method_source (0.8.2)
12
+ minitest (5.9.0)
13
+ pry (0.10.4)
14
+ coderay (~> 1.1.0)
15
+ method_source (~> 0.8.1)
16
+ slop (~> 3.4)
17
+ pry-byebug (3.4.0)
18
+ byebug (~> 9.0)
19
+ pry (~> 0.10)
20
+ rake (11.2.2)
21
+ slop (3.6.0)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ enzymator!
28
+ minitest (~> 5.9)
29
+ pry-byebug
30
+ rake (~> 11.2)
31
+
32
+ BUNDLED WITH
33
+ 1.12.5
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Enzymator
2
+
3
+ Enzimator is an extremely simple and powerful aggregation framework. Every ruby app can use it to unleash the infinite power of the MapReduce concept. If it could tame BigData, imagine what it can do with fewer data!
4
+
5
+ You should take two minutes to check out the test examples.
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'enzimator'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install enzimator
20
+
21
+ ## Usage
22
+
23
+ You set up a new Aggregation instance, tell it to run with your Enumerator, and get the result. The tests are self-explanatory.
24
+
25
+ ## Contributing
26
+
27
+ 1. Fork it
28
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
29
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
30
+ 4. Push to the branch (`git push origin my-new-feature`)
31
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ require 'rake/testtask'
2
+
3
+ Rake::TestTask.new do |t|
4
+ t.libs << 'test'
5
+ end
6
+
7
+ desc "Run tests"
8
+ task :default => :test
data/enzymator.gemspec ADDED
@@ -0,0 +1,22 @@
1
+ # -*- encoding: utf-8 -*-
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'enzymator/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'enzymator'
8
+ s.version = Enzymator::Version
9
+ s.date = '2016-07-17'
10
+ s.summary = "An extremely simple and powerful aggregation framework"
11
+ s.description = "A gem to perform any kind of calculation on any kind of data. The essence of MapReduce distilled in a few lines of code for the ruby community to enjoy."
12
+ s.authors = ["Eugenio Bruno"]
13
+ s.email = 'eugeniobruno@gmail.com'
14
+ s.homepage = 'http://rubygems.org/gems/enzymator'
15
+ s.license = 'MIT'
16
+
17
+ s.files = `git ls-files`.split($/)
18
+ s.executables = s.files.grep(%r{^bin/}).map { |f| File.basename(f) }
19
+ s.test_files = s.files.grep(%r{^(test|spec|features)/})
20
+ s.require_paths = ['lib']
21
+
22
+ end
data/lib/enzymator.rb ADDED
@@ -0,0 +1,2 @@
1
+ require 'enzymator/core_ext/enumerator'
2
+ require 'enzymator/aggregation'
@@ -0,0 +1,63 @@
1
+ module Enzymator
2
+ class Aggregation
3
+
4
+ @@single_cluster_config = {
5
+ initial_clusters: lambda { |n| n },
6
+ enumerator: lambda { |n| [n].each },
7
+ map_each: lambda { |n| :single_cluster },
8
+ reduce_each: lambda { |acum, n| :single_cluster },
9
+ }
10
+
11
+ attr_accessor :config, :results
12
+
13
+ def initialize(config, results = [])
14
+ @config = @@single_cluster_config.merge(config)
15
+ @results = results
16
+ end
17
+
18
+ def last_result
19
+ results.last
20
+ end
21
+ alias :result :last_result
22
+
23
+ def patch_config(config_patch)
24
+ self.config = config.merge(config_patch)
25
+ self
26
+ end
27
+
28
+ def run_on!(enumerable, options = {}, config = @config)
29
+ add_result(run_on(enumerable, options, config))
30
+ self
31
+ end
32
+
33
+ def run_on(enumerable, options = {}, config = @config)
34
+ config[:initial_clusters].call(enumerable).reduce(config[:null_result].call) do |acum, cluster|
35
+ group = config[:map].call(cluster)
36
+ config[:reduce].call( acum, group, aggregate(cluster, config, options) )
37
+ end
38
+ end
39
+
40
+ protected
41
+
42
+ def add_result(result)
43
+ @results.push(result)
44
+ self
45
+ end
46
+
47
+ def aggregate(cluster, config, options)
48
+ enum = config[:enumerator].call(cluster)
49
+ first_element = enum.peek
50
+ first_map_result = config[:map_each].call(first_element)
51
+
52
+ enum.skip(1).reduce(first_map_result) do |acum, e|
53
+ step(acum, e, config, options)
54
+ end
55
+ end
56
+
57
+ def step(previous_result, elem, config, options)
58
+ map_result = config[:map_each].call(elem)
59
+ config[:reduce_each].call(previous_result, map_result)
60
+ end
61
+
62
+ end
63
+ end
@@ -0,0 +1,20 @@
1
+ class Enumerator
2
+ #
3
+ # Skip the first n elements and return an Enumerator for the rest, or pass them
4
+ # in succession to the block, if given.
5
+ # Extracted from epitools: https://github.com/epitron/epitools
6
+ #
7
+ def skip(n)
8
+ if block_given?
9
+ each do |x|
10
+ if n > 0
11
+ n -= 1
12
+ else
13
+ yield x
14
+ end
15
+ end
16
+ else
17
+ to_enum(:skip, n)
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,18 @@
1
+ module Enzymator
2
+ class Version
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ PATCH = 1
6
+ PRE = nil
7
+
8
+ class << self
9
+
10
+ # @return [String]
11
+ def to_s
12
+ [MAJOR, MINOR, PATCH, PRE].compact.join('.')
13
+ end
14
+
15
+ end
16
+
17
+ end
18
+ end
@@ -0,0 +1,67 @@
1
+ require 'minitest/autorun'
2
+ require 'enzymator'
3
+
4
+ class AggregationTest < Minitest::Test
5
+
6
+ def test_sum_numbers
7
+ numbers = (1..1000).to_a
8
+ # to sum the numbers, you can just do
9
+ expected_sum = numbers.reduce(:+)
10
+
11
+ # but where's the fun in that...
12
+ actual_sum = Enzymator::Aggregation.new({
13
+ null_result: lambda { 0 },
14
+ map: lambda { |n| n },
15
+ reduce: lambda { |acum, n, _| acum + n },
16
+ }).run_on(numbers)
17
+
18
+ assert_equal expected_sum, actual_sum
19
+ end
20
+
21
+ def test_count_words
22
+ # Let's follow the herd of MapReduce preachers and count some words.
23
+ words = %w(Hey! Are you the horse from Horsing Around? The word is you got fat.)
24
+
25
+ # There is no built-in one-message-one-argument way this time...
26
+ expected_hash = {
27
+ 'Hey!' => 1,
28
+ 'Are' => 1,
29
+ 'you' => 2,
30
+ 'the' => 1,
31
+ 'horse' => 1,
32
+ 'from' => 1,
33
+ 'Horsing' => 1,
34
+ 'Around?' => 1,
35
+ 'The' => 1,
36
+ 'word' => 1,
37
+ 'is' => 1,
38
+ 'got' => 1,
39
+ 'fat.' => 1,
40
+ }
41
+
42
+ aggregation = Enzymator::Aggregation.new({
43
+ null_result: lambda { Hash.new(0) },
44
+ map: lambda { |w| w },
45
+ reduce: lambda { |acum, w, _| acum[w] += 1; acum }
46
+ }).run_on!(words)
47
+ # notice the bang
48
+
49
+ actual_hash = aggregation.result
50
+
51
+ assert_equal expected_hash, actual_hash
52
+
53
+ # I'm thinking 'the' and 'The' should count as one word. Total case-insensitivity
54
+ expected_hash['the'] = 2
55
+ expected_hash.delete('The')
56
+ expected_hash = expected_hash.map { |k, v| { k.downcase => v } }.reduce(&:merge)
57
+
58
+ aggregation.patch_config( map: lambda { |w| w.downcase } )
59
+ .run_on!(words)
60
+
61
+ actual_hash = aggregation.result
62
+
63
+ assert_equal expected_hash, actual_hash
64
+
65
+ end
66
+
67
+ end
metadata ADDED
@@ -0,0 +1,55 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: enzymator
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ platform: ruby
6
+ authors:
7
+ - Eugenio Bruno
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2016-07-17 00:00:00.000000000 Z
12
+ dependencies: []
13
+ description: A gem to perform any kind of calculation on any kind of data. The essence
14
+ of MapReduce distilled in a few lines of code for the ruby community to enjoy.
15
+ email: eugeniobruno@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - Gemfile
21
+ - Gemfile.lock
22
+ - README.md
23
+ - Rakefile
24
+ - enzymator.gemspec
25
+ - lib/enzymator.rb
26
+ - lib/enzymator/aggregation.rb
27
+ - lib/enzymator/core_ext/enumerator.rb
28
+ - lib/enzymator/version.rb
29
+ - test/test_aggregation.rb
30
+ homepage: http://rubygems.org/gems/enzymator
31
+ licenses:
32
+ - MIT
33
+ metadata: {}
34
+ post_install_message:
35
+ rdoc_options: []
36
+ require_paths:
37
+ - lib
38
+ required_ruby_version: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: '0'
43
+ required_rubygems_version: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ requirements: []
49
+ rubyforge_project:
50
+ rubygems_version: 2.5.1
51
+ signing_key:
52
+ specification_version: 4
53
+ summary: An extremely simple and powerful aggregation framework
54
+ test_files:
55
+ - test/test_aggregation.rb