totalr 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in totalr.gemspec
4
+ gemspec
5
+ gem 'rspec'
6
+ gem 'active_support'
data/README ADDED
@@ -0,0 +1,24 @@
1
+ Totalr is a ruby library which gives a dsl that lets you do aggregations in your model declaratively.
2
+ It is inspired by the statistical capabilities of R. Currently it does not even do 1 % of what R does.
3
+
4
+ But it still lets you do aggregations like totaling, percentage, grouping in your model easily:
5
+
6
+ class Team
7
+ total :players, using: :goals, by: :age
8
+ end
9
+
10
+ This creates a dynamic method total_player_goals_by_age which takes an age param.
11
+
12
+ class Team
13
+ percentage :total_player_goals, of: :total_player_attempts, as: :goals_to_attempts
14
+ end
15
+
16
+ This creates a method which calculates percentage of goals:attempts for all players in the model.
17
+
18
+ Totalr does not serve to replace any aggregation mechanism already provided by ORM or Enumerable.
19
+ It only complements them by generating methods like this.
20
+
21
+ You can give custom names to generated methods using :as key
22
+ For documentation/features look at spec/totalr_spec.rb
23
+
24
+ More features like mean, variance are still under development.
data/Rakefile ADDED
@@ -0,0 +1,6 @@
1
+ require "bundler/gem_tasks"
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new('spec')
5
+
6
+ task :default => :spec
@@ -0,0 +1,3 @@
1
+ module Totalr
2
+ VERSION = "0.0.1"
3
+ end
data/lib/totalr.rb ADDED
@@ -0,0 +1,72 @@
1
+ require 'active_support/inflector'
2
+
3
+ module Totalr
4
+ def self.included(klass)
5
+ klass.extend(ClassMethods)
6
+ end
7
+
8
+ module ClassMethods
9
+ def total(coll_name, options = {})
10
+ attribute = options[:using]
11
+ group_by = options[:by]
12
+ method_name = options[:as]
13
+ method_name ||= "total_#{ActiveSupport::Inflector.singularize(coll_name.to_s)}_#{attribute}_for_#{group_by}" if attribute and group_by
14
+ method_name ||= "total_#{ActiveSupport::Inflector.singularize(coll_name.to_s)}_#{attribute}" if attribute
15
+ method_name ||= "total_#{coll_name}_for_#{group_by}" if group_by
16
+ method_name ||= "total_#{coll_name}"
17
+
18
+ method_body = if group_by
19
+ if attribute
20
+ lambda do |group_value|
21
+ coll = send(coll_name)
22
+ coll.select {|e| e.send(group_by) == group_value}.map {|e| e.send(attribute)}.inject(:+)
23
+ end
24
+ else
25
+ lambda do |group_value|
26
+ coll = send(coll_name)
27
+ coll.select {|e| e.send(group_by) == group_value}.length
28
+ end
29
+ end
30
+
31
+ else
32
+ if attribute
33
+ lambda do
34
+ coll = send(coll_name)
35
+ coll.map {|e| e.send(attribute)}.inject(:+)
36
+ end
37
+ else
38
+ lambda do
39
+ coll = send(coll_name)
40
+ coll.length
41
+ end
42
+ end
43
+ end
44
+ define_method method_name, method_body
45
+ end
46
+
47
+ def percentage(part_count_method, options = {})
48
+ total_count_method = options[:of]
49
+ part_by = options[:by]
50
+ total_by = options[:total_by]
51
+
52
+ method_name = options[:as]
53
+ method_name ||= "percentage_#{part_count_method}_in_#{total_by}" if total_by
54
+ method_name ||= "percentage_#{part_count_method}"
55
+
56
+ if total_by and total_by != part_by
57
+ define_method method_name do |part_by_value, total_by_value|
58
+ part_count = send(part_count_method, part_by_value)
59
+ total_count = total_by ? send(total_count_method, total_by_value) : send(total_count_method)
60
+ part_count * 100.00 / total_count
61
+ end
62
+
63
+ else
64
+ define_method method_name do |part_by_value|
65
+ part_count = send(part_count_method, part_by_value)
66
+ total_count = total_by ? send(total_count_method, part_by_value) : send(total_count_method)
67
+ part_count * 100.00 / total_count
68
+ end
69
+ end
70
+ end
71
+ end
72
+ end
@@ -0,0 +1,4 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'totalr'
@@ -0,0 +1,193 @@
1
+ require 'spec_helper'
2
+
3
+
4
+ describe Totalr do
5
+
6
+ class Team
7
+ include Totalr
8
+ attr_accessor :players
9
+
10
+ def initialize(params)
11
+ @name = params[:name]
12
+ @players = []
13
+ end
14
+ end
15
+
16
+ class Player
17
+ attr_reader :goals
18
+ attr_reader :attempts
19
+ attr_reader :age
20
+ attr_reader :region
21
+ def initialize(params)
22
+ @name = params[:name]
23
+ @goals = params[:goals]
24
+ @attempts = params[:attempts]
25
+ @age = params[:age]
26
+ @region = params[:region]
27
+ end
28
+
29
+ end
30
+
31
+ describe "total" do
32
+
33
+ class Team
34
+ total :players
35
+ end
36
+
37
+ it "should total collection" do
38
+ real_madrid = Team.new(name: 'Real Madrid')
39
+ real_madrid.players << Player.new(name: 'Ronaldo')
40
+ real_madrid.players << Player.new(name: 'Beckham')
41
+
42
+ real_madrid.total_players.should == 2
43
+ end
44
+
45
+ class Team
46
+ total :players, as: :player_count
47
+ end
48
+
49
+ it "should total collection with custom name" do
50
+ real_madrid = Team.new(name: 'Real Madrid')
51
+ real_madrid.players << Player.new(name: 'Ronaldo')
52
+ real_madrid.players << Player.new(name: 'Beckham')
53
+
54
+ real_madrid.player_count.should == 2
55
+ end
56
+
57
+ class Team
58
+ total :players, using: :goals
59
+ end
60
+
61
+ it "should total collection using attribute" do
62
+ real_madrid = Team.new(name: 'Real Madrid')
63
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 25)
64
+ real_madrid.players << Player.new(name: 'Beckham', goals: 15)
65
+
66
+ real_madrid.total_player_goals.should == 40
67
+ end
68
+
69
+ class Team
70
+ total :players, using: :goals, as: :number_of_goals
71
+ end
72
+
73
+ it "should total collection using attribute with custom name" do
74
+ real_madrid = Team.new(name: 'Real Madrid')
75
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 25)
76
+ real_madrid.players << Player.new(name: 'Beckham', goals: 15)
77
+
78
+ real_madrid.number_of_goals.should == 40
79
+ end
80
+
81
+ class Team
82
+ total :players, by: :age
83
+ end
84
+
85
+ it "should total collection grouping by attribute" do
86
+ real_madrid = Team.new(name: 'Real Madrid')
87
+ real_madrid.players << Player.new(name: 'Ronaldo', age: 25)
88
+ real_madrid.players << Player.new(name: 'Beckham', age: 25)
89
+ real_madrid.players << Player.new(name: 'Figo', age: 30)
90
+
91
+ real_madrid.total_players_for_age(25).should == 2
92
+ real_madrid.total_players_for_age(30).should == 1
93
+ end
94
+
95
+ class Team
96
+ total :players, using: :goals, by: :age
97
+ end
98
+
99
+ it "should total collection mapping by attribute and grouping by attribute" do
100
+ real_madrid = Team.new(name: 'Real Madrid')
101
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 25, age: 25)
102
+ real_madrid.players << Player.new(name: 'Beckham', goals: 15, age: 25)
103
+ real_madrid.players << Player.new(name: 'Figo', goals: 10, age: 30)
104
+
105
+ real_madrid.total_player_goals_for_age(25).should == 40
106
+ real_madrid.total_player_goals_for_age(30).should == 10
107
+ end
108
+
109
+ end
110
+
111
+ describe "percentage" do
112
+ class Team
113
+ total :players
114
+ total :players, by: :age
115
+ percentage :total_players_for_age, by: :age, of: :total_players
116
+ end
117
+
118
+ it "should calculate percentage of total" do
119
+ real_madrid = Team.new(name: 'Real Madrid')
120
+ real_madrid.players << Player.new(name: 'Ronaldo', age: 25)
121
+ real_madrid.players << Player.new(name: 'Beckham', age: 25)
122
+ real_madrid.players << Player.new(name: 'Figo', age: 30)
123
+
124
+ real_madrid.percentage_total_players_for_age(25).round(2).should == 66.67
125
+ real_madrid.percentage_total_players_for_age(30).round(2).should == 33.33
126
+ end
127
+
128
+ class Team
129
+ percentage :total_players_for_age, by: :age, of: :total_players, as: :distribution_by_age
130
+ end
131
+
132
+ it "should calculate percentage of total with custom name" do
133
+ real_madrid = Team.new(name: 'Real Madrid')
134
+ real_madrid.players << Player.new(name: 'Ronaldo', age: 25)
135
+ real_madrid.players << Player.new(name: 'Beckham', age: 25)
136
+ real_madrid.players << Player.new(name: 'Figo', age: 30)
137
+
138
+ real_madrid.distribution_by_age(25).round(2).should == 66.67
139
+ real_madrid.distribution_by_age(30).round(2).should == 33.33
140
+ end
141
+
142
+ class Team
143
+ percentage :total_player_goals_for_age, by: :age, of: :total_player_goals, as: :percentage_goals_by_age
144
+ end
145
+
146
+ it "should calculate percentage of total using attribute" do
147
+ real_madrid = Team.new(name: 'Real Madrid')
148
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 25, age: 25)
149
+ real_madrid.players << Player.new(name: 'Beckham', goals: 15, age: 25)
150
+ real_madrid.players << Player.new(name: 'Figo', goals: 10, age: 30)
151
+
152
+ real_madrid.percentage_goals_by_age(25).should == 80.00
153
+ real_madrid.percentage_goals_by_age(30).should == 20.00
154
+ end
155
+
156
+ class Team
157
+ total :players, using: :goals, by: :region
158
+ percentage :total_player_goals_for_age, by: :age,
159
+ of: :total_player_goals_for_region, total_by: :region
160
+ end
161
+
162
+ it "should calculate percentage totaling by attribute" do
163
+ real_madrid = Team.new(name: 'Real Madrid')
164
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 25, age: 28, region: 'southamerica')
165
+ real_madrid.players << Player.new(name: 'Beckham', goals: 20, age: 25, region: 'europe')
166
+ real_madrid.players << Player.new(name: 'Carlos', goals: 10, age: 28, region: 'southamerica')
167
+ real_madrid.players << Player.new(name: 'Figo', goals: 12, age: 30, region: 'europe')
168
+ real_madrid.players << Player.new(name: 'Zidane', goals: 18, age: 30, region: 'europe')
169
+
170
+ real_madrid.percentage_total_player_goals_for_age_in_region(30, 'europe').should == 60.00
171
+ real_madrid.percentage_total_player_goals_for_age_in_region(25, 'europe').should == 40.00
172
+ end
173
+
174
+ class Team
175
+ total :players, using: :goals, by: :age
176
+ total :players, using: :attempts, by: :age
177
+ percentage :total_player_goals_for_age, by: :age,
178
+ of: :total_player_attempts_for_age, total_by: :age,
179
+ as: :goal_to_attempts
180
+
181
+ end
182
+
183
+ it "should calculate percentage totaling by same attribute as percentage" do
184
+ real_madrid = Team.new(name: 'Real Madrid')
185
+ real_madrid.players << Player.new(name: 'Ronaldo', goals: 21, attempts: 30, age: 25)
186
+ real_madrid.players << Player.new(name: 'Beckham', goals: 15, attempts: 20, age: 25)
187
+ real_madrid.players << Player.new(name: 'Figo', goals: 10, attempts: 15, age: 30)
188
+
189
+ real_madrid.goal_to_attempts(25).should == 72.00
190
+ end
191
+ end
192
+
193
+ end
data/totalr.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "totalr/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "totalr"
7
+ s.version = Totalr::VERSION
8
+ s.authors = ["Sathish"]
9
+ s.email = ["sathish316@gmail.com"]
10
+ s.homepage = "http://www.github.com/sathish316/totalr"
11
+ s.summary = %q{Totalr is a lib which provides a simple dsl to do aggregation in models, like totals, percentage, grouping, mean, variance et
12
+ c}
13
+ s.description = %q{Totalr is a lib which provides a simple dsl to do aggregation in models, like totals, percentage, grouping, mean, variance et
14
+ c}
15
+ s.rubyforge_project = "totalr"
16
+
17
+ s.files = `git ls-files`.split("\n")
18
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
19
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
20
+ s.require_paths = ["lib"]
21
+
22
+ # specify any dependencies here; for example:
23
+ # s.add_development_dependency "rspec"
24
+ # s.add_runtime_dependency "rest-client"
25
+ end
metadata ADDED
@@ -0,0 +1,58 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: totalr
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Sathish
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2011-09-05 00:00:00.000000000Z
13
+ dependencies: []
14
+ description: ! 'Totalr is a lib which provides a simple dsl to do aggregation in models,
15
+ like totals, percentage, grouping, mean, variance et
16
+
17
+ c'
18
+ email:
19
+ - sathish316@gmail.com
20
+ executables: []
21
+ extensions: []
22
+ extra_rdoc_files: []
23
+ files:
24
+ - .gitignore
25
+ - Gemfile
26
+ - README
27
+ - Rakefile
28
+ - lib/totalr.rb
29
+ - lib/totalr/version.rb
30
+ - spec/spec_helper.rb
31
+ - spec/totalr_spec.rb
32
+ - totalr.gemspec
33
+ homepage: http://www.github.com/sathish316/totalr
34
+ licenses: []
35
+ post_install_message:
36
+ rdoc_options: []
37
+ require_paths:
38
+ - lib
39
+ required_ruby_version: !ruby/object:Gem::Requirement
40
+ none: false
41
+ requirements:
42
+ - - ! '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ none: false
47
+ requirements:
48
+ - - ! '>='
49
+ - !ruby/object:Gem::Version
50
+ version: '0'
51
+ requirements: []
52
+ rubyforge_project: totalr
53
+ rubygems_version: 1.8.6
54
+ signing_key:
55
+ specification_version: 3
56
+ summary: Totalr is a lib which provides a simple dsl to do aggregation in models,
57
+ like totals, percentage, grouping, mean, variance et c
58
+ test_files: []