madvertise-ext 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use --create ruby-1.9.3-p125@madvertise-ext
data/.travis.yml ADDED
@@ -0,0 +1,5 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.8.7
4
+ - 1.9.2
5
+ - 1.9.3
data/.yardopts ADDED
@@ -0,0 +1 @@
1
+ --protected --no-private
data/Gemfile ADDED
@@ -0,0 +1,16 @@
1
+ source :rubygems
2
+
3
+ gemspec
4
+
5
+ group :development, :test do
6
+ gem 'bundler'
7
+ gem 'pry'
8
+ gem 'pry-doc'
9
+ gem 'rake'
10
+ gem 'redcarpet'
11
+ gem 'reek'
12
+ gem 'rspec'
13
+ gem 'ruby2ruby', '=1.3.0' # 1.3.1 is broken :(
14
+ gem 'simplecov'
15
+ gem 'yard'
16
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 madvertise Mobile Advertising GmbH
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,31 @@
1
+ # Madvertise::Ext
2
+
3
+ The madvertise-ext gem provides a bunch of ruby extensions.
4
+
5
+ [![Build Status](https://secure.travis-ci.org/madvertise/ext.png)](http://travis-ci.org/madvertise/ext)
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'madvertise-ext'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install madvertise-ext
20
+
21
+ ## Usage
22
+
23
+ Please refer to the [API documentation](http://rubydoc.info/gems/madvertise-ext/frames).
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 'Added 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
+ #!/usr/bin/env rake
2
+
3
+ require "bundler/setup"
4
+ require "bundler/gem_tasks"
5
+
6
+ Dir['tasks/**/*.rake'].each { |t| load t }
7
+
8
+ task :default => [:spec]
@@ -0,0 +1,174 @@
1
+ require 'yaml'
2
+ require 'madvertise/ext/hash'
3
+
4
+ ##
5
+ # A {Configuration} consists of one or more Sections. A section is a hash-like
6
+ # object that responds to all keys in the hash as if they were methods:
7
+ #
8
+ # > s = Section.from_hash({:v1 => 2, :nested => {:v2 => 1}})
9
+ # > s.v1
10
+ # => 2
11
+ # > s.nested.v2
12
+ # => 1
13
+ #
14
+ class Section < Hash
15
+ class << self
16
+
17
+ # Create a new section from the given hash-like object.
18
+ #
19
+ # @param [Hash] hsh The hash to convert into a section.
20
+ # @return [Section] The new {Section} object.
21
+ def from_hash(hsh)
22
+ result = new.tap do |result|
23
+ hsh.each do |key, value|
24
+ result[key.to_sym] = from_value(value)
25
+ end
26
+ end
27
+ end
28
+
29
+ # Convert the given value into a Section, list of Sections or the pure
30
+ # value. Used to recursively build the Section hash.
31
+ #
32
+ # @private
33
+ def from_value(value)
34
+ case value
35
+ when Hash
36
+ from_hash(value)
37
+ when Array
38
+ value.map do |item|
39
+ from_hash(item)
40
+ end
41
+ else
42
+ value
43
+ end
44
+ end
45
+ end
46
+
47
+ # Mixin a configuration snippet into the current section.
48
+ #
49
+ # @param [Hash, String] value A hash to merge into the current
50
+ # configuration. If a string is given a filename
51
+ # is assumed and the given file is expected to
52
+ # contain a YAML hash.
53
+ # @return [void]
54
+ def mixin(value)
55
+ unless value.is_a?(Hash)
56
+ value = Section.from_hash(YAML.load(File.read(value)))
57
+ end
58
+
59
+ self.deep_merge!(value[:default]) if value.has_key?(:default)
60
+ self.deep_merge!(value[:generic]) if value.has_key?(:generic)
61
+
62
+ if value.has_key?(@mode)
63
+ self.deep_merge!(value[@mode])
64
+ else
65
+ self.deep_merge!(value)
66
+ end
67
+ end
68
+
69
+ # Build the call chain including NilSections.
70
+ #
71
+ # @private
72
+ def method_missing(name, *args)
73
+ if name.to_s =~ /(.*)=$/
74
+ self[$1.to_sym] = Section.from_value(args.first)
75
+ else
76
+ value = self[name]
77
+ value = value.call if value.is_a?(Proc)
78
+ value = NilSection.new if value.nil?
79
+ self[name] = value
80
+ end
81
+ end
82
+ end
83
+
84
+ ##
85
+ # The Configuration class provides a simple interface to configuration stored
86
+ # inside of YAML files.
87
+ #
88
+ class Configuration < Section
89
+
90
+ # Create a new {Configuration} object.
91
+ #
92
+ # @param [Symbol] mode The mode to load from the configurtion file
93
+ # (production, development, etc)
94
+ # @yield [config] The new configuration object.
95
+ def initialize(mode = :development)
96
+ @mode = mode
97
+ yield self if block_given?
98
+ end
99
+
100
+ # Load given mixins from +path+.
101
+ #
102
+ # @param [String] path The path to mixin files.
103
+ # @param [Array] mixins_to_use A list of mixins to load from +path+.
104
+ # @return [void]
105
+ def load_mixins(path, mixins_to_use)
106
+ mixins_to_use.map do |mixin_name|
107
+ File.join(path, "#{mixin_name}.yml")
108
+ end.each do |mixin_file|
109
+ mixin(mixin_file)
110
+ end
111
+ end
112
+
113
+ ##
114
+ # The {Helpers} module can be included in all classes that wish to load
115
+ # configuration file(s). In order to load custom configuration files the
116
+ # including class needs to set the +@config_file+ instance variable.
117
+ #
118
+ module Helpers
119
+
120
+ # Load the configuration. The default configuration is located at
121
+ # +lib/ganymed/config.yml+ inside the Ganymed source tree.
122
+ #
123
+ # @return [Configuration] The configuration object. See madvertise-ext gem
124
+ # for details.
125
+ def config
126
+ @config ||= Configuration.new(Env.mode) do |config|
127
+ config.mixin(@default_config_file) if @default_config_file
128
+ config.mixin(@config_file) if @config_file
129
+ end
130
+ end
131
+ end
132
+ end
133
+
134
+ ##
135
+ # A NilSection is returned for all missing/empty values in the config file. This
136
+ # allows for terse code when accessing values that have not been configured by
137
+ # the user.
138
+ #
139
+ # Consider code like this:
140
+ #
141
+ # config.server.listen.tap do |listen|
142
+ # open_socket(listen.host, listen.port)
143
+ # end
144
+ #
145
+ # Given that your server component is optional and does not appear in the
146
+ # configuration file at all, +config.server.listen+ will return a NilSection
147
+ # that does not call the block given to tap _at all_.
148
+ #
149
+ class NilSection
150
+ # @return true
151
+ def nil?
152
+ true
153
+ end
154
+
155
+ # @return true
156
+ def empty?
157
+ true
158
+ end
159
+
160
+ # @return false
161
+ def present?
162
+ false
163
+ end
164
+
165
+ # @return self
166
+ def tap
167
+ self
168
+ end
169
+
170
+ # @private
171
+ def method_missing(*args, &block)
172
+ self
173
+ end
174
+ end
@@ -0,0 +1,22 @@
1
+ module Enumerable
2
+ def sum
3
+ reduce(:+)
4
+ end
5
+
6
+ def mean
7
+ sum.to_f / length
8
+ end
9
+
10
+ def variance
11
+ m = mean
12
+ reduce(0) {|accum, item| accum + (item - m) ** 2}.to_f / (length - 1)
13
+ end
14
+
15
+ def stdev
16
+ Math.sqrt(variance)
17
+ end
18
+
19
+ def percentile(pc)
20
+ sort[(pc * length).ceil - 1]
21
+ end
22
+ end
@@ -0,0 +1,56 @@
1
+ ##
2
+ # A simple convenience class to support multiple environments in which a
3
+ # program can run (e.g. development, production, etc).
4
+ #
5
+ class Environment
6
+ attr_accessor :key
7
+
8
+ # Create a new Environment instance with the corresponding +key+ in the +ENV+
9
+ # hash.
10
+ #
11
+ # @param [String] key The key in +ENV+ to contain the current program
12
+ # environment.
13
+ #
14
+ def initialize(key=nil)
15
+ @key = key
16
+ end
17
+
18
+ # Retreive the current environment mode.
19
+ #
20
+ # @return [String] The current environment mode.
21
+ def mode
22
+ ENV[@key] || 'development'
23
+ end
24
+
25
+ # Retrieve the current environment mode and convert it to a symbol.
26
+ #
27
+ # @return [Symbol] The current environment mode.
28
+ def to_sym
29
+ mode.to_sym
30
+ end
31
+
32
+ # Return true if the current environment is +production+.
33
+ def prod?
34
+ to_sym == :production
35
+ end
36
+
37
+ # Return true if the current environment is +development+.
38
+ def dev?
39
+ to_sym == :development
40
+ end
41
+
42
+ # Return true if the current environment is +test+.
43
+ def test?
44
+ to_sym == :test
45
+ end
46
+
47
+ # Set the environment mode.
48
+ #
49
+ # @param [String] The new environment mode.
50
+ def set(value)
51
+ ENV[@key] = value.to_s
52
+ end
53
+ end
54
+
55
+ # Global instance of {Environment}.
56
+ Env = Environment.new
@@ -0,0 +1,20 @@
1
+ ##
2
+ # Various Hash extensions.
3
+ #
4
+ class Hash
5
+
6
+ # Recursively merge +other_hash+ into +self+ and return the new hash.
7
+ def deep_merge(other_hash)
8
+ self.merge(other_hash) do |key, oldval, newval|
9
+ oldval = oldval.to_hash if oldval.respond_to?(:to_hash)
10
+ newval = newval.to_hash if newval.respond_to?(:to_hash)
11
+ oldval.is_a?(Hash) && newval.is_a?(Hash) ? oldval.deep_merge(newval) : newval
12
+ end
13
+ end
14
+
15
+ # Recursively merge and replace +other_hash+ into +self.
16
+ def deep_merge!(other_hash)
17
+ replace(deep_merge(other_hash))
18
+ end
19
+
20
+ end
@@ -0,0 +1,38 @@
1
+ require 'active_support/core_ext/module/attribute_accessors'
2
+ require 'madvertise/ext/environment'
3
+ require 'madvertise-logging'
4
+
5
+ include Madvertise::Logging
6
+
7
+ ##
8
+ # The {Logging} module provides a global container for the logger object.
9
+ #
10
+ module Logging
11
+ mattr_accessor :logger
12
+ self.logger = nil
13
+
14
+ # @private
15
+ def self.create_logger
16
+ if Env.prod?
17
+ ImprovedLogger.new(:syslog, $0)
18
+ else
19
+ ImprovedLogger.new(STDERR, $0)
20
+ end.tap do |logger|
21
+ logger.level = :info
22
+ end
23
+ end
24
+
25
+ ##
26
+ # The {Logging::Helpers} module can be included in classes that wish to use
27
+ # the global logger.
28
+ #
29
+ module Helpers
30
+
31
+ # Retreive and possibly create the global logger object.
32
+ #
33
+ # @return [Logger] The logger object.
34
+ def log
35
+ Logging.logger ||= Logging.create_logger
36
+ end
37
+ end
38
+ end
@@ -0,0 +1,7 @@
1
+ ---
2
+ NestedIterators:
3
+ exclude:
4
+ - Section#from_hash
5
+ FeatureEnvy:
6
+ exclude:
7
+ - Hash#deep_merge
@@ -0,0 +1,6 @@
1
+ # @private
2
+ module Madvertise
3
+ module Ext
4
+ VERSION = "0.1.0"
5
+ end
6
+ end
@@ -0,0 +1,19 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/madvertise/ext/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.name = "madvertise-ext"
6
+ gem.version = Madvertise::Ext::VERSION
7
+ gem.authors = ["Benedikt Böhm"]
8
+ gem.email = ["benedikt.boehm@madvertise.com"]
9
+ gem.description = %q{Ruby extensions}
10
+ gem.summary = %q{Ruby extensions}
11
+ gem.homepage = "https://github.com/madvertise/ext"
12
+
13
+ gem.add_dependency "madvertise-logging"
14
+
15
+ gem.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
16
+ gem.files = `git ls-files`.split("\n")
17
+ gem.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
18
+ gem.require_paths = ["lib"]
19
+ end
@@ -0,0 +1,26 @@
1
+ require File.dirname(__FILE__) + '/spec_helper'
2
+ require 'madvertise/ext/enumerable'
3
+
4
+ describe Enumerable do
5
+
6
+ it "should support the sum for a list of numbers" do
7
+ [1,2,3,4,5].sum.should == 15
8
+ end
9
+
10
+ it "should support the mean for a list of numbers" do
11
+ [1,2,3,4,5].mean.should == 3.0
12
+ end
13
+
14
+ it "should support the variance for a list of numbers" do
15
+ [9,8,7,6,5].variance.should == 2.5
16
+ end
17
+
18
+ it "should support the standard deviation for a list of numbers" do
19
+ [9,8,7,6,5].stdev.should == 1.5811388300841898
20
+ end
21
+
22
+ it "should support a percentile method for a list of numbers" do
23
+ [9,1,8,2,7,3,6,4,5,4,3,2,1].percentile(0.9).should == 8
24
+ end
25
+
26
+ end
data/spec/spec.opts ADDED
@@ -0,0 +1 @@
1
+ --colour
@@ -0,0 +1,19 @@
1
+ require 'rubygems'
2
+ require 'rspec'
3
+
4
+ require 'simplecov'
5
+ SimpleCov.start
6
+
7
+ $:.unshift(File.dirname(__FILE__) + '/../lib')
8
+ #require 'madvertise-ext'
9
+
10
+ RSpec.configure do |config|
11
+ # == Mock Framework
12
+ #
13
+ # RSpec uses it's own mocking framework by default. If you prefer to
14
+ # use mocha, flexmock or RR, uncomment the appropriate line:
15
+ #
16
+ # config.mock_with :mocha
17
+ # config.mock_with :flexmock
18
+ # config.mock_with :rr
19
+ end
data/tasks/reek.rake ADDED
@@ -0,0 +1,5 @@
1
+ require 'reek/rake/task'
2
+
3
+ Reek::Rake::Task.new do |t|
4
+ t.fail_on_error = false
5
+ end
data/tasks/rspec.rake ADDED
@@ -0,0 +1,7 @@
1
+ require 'rspec'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc "Run the specs"
5
+ RSpec::Core::RakeTask.new do |t|
6
+ t.rspec_opts = ['--options', "spec/spec.opts"]
7
+ end
data/tasks/yard.rake ADDED
@@ -0,0 +1,5 @@
1
+ require 'yard'
2
+
3
+ YARD::Rake::YardocTask.new do |t|
4
+ t.files = ['lib/**/*.rb', 'README.rdoc']
5
+ end
metadata ADDED
@@ -0,0 +1,88 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: madvertise-ext
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Benedikt Böhm
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-04-15 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: madvertise-logging
16
+ requirement: &12312600 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *12312600
25
+ description: Ruby extensions
26
+ email:
27
+ - benedikt.boehm@madvertise.com
28
+ executables: []
29
+ extensions: []
30
+ extra_rdoc_files: []
31
+ files:
32
+ - .gitignore
33
+ - .rvmrc
34
+ - .travis.yml
35
+ - .yardopts
36
+ - Gemfile
37
+ - LICENSE
38
+ - README.md
39
+ - Rakefile
40
+ - lib/madvertise/ext/config.rb
41
+ - lib/madvertise/ext/enumerable.rb
42
+ - lib/madvertise/ext/environment.rb
43
+ - lib/madvertise/ext/hash.rb
44
+ - lib/madvertise/ext/logging.rb
45
+ - lib/madvertise/ext/mask.reek
46
+ - lib/madvertise/ext/version.rb
47
+ - madvertise-ext.gemspec
48
+ - spec/enumerable_spec.rb
49
+ - spec/spec.opts
50
+ - spec/spec_helper.rb
51
+ - tasks/reek.rake
52
+ - tasks/rspec.rake
53
+ - tasks/yard.rake
54
+ homepage: https://github.com/madvertise/ext
55
+ licenses: []
56
+ post_install_message:
57
+ rdoc_options: []
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ none: false
62
+ requirements:
63
+ - - ! '>='
64
+ - !ruby/object:Gem::Version
65
+ version: '0'
66
+ segments:
67
+ - 0
68
+ hash: 3585342747307682113
69
+ required_rubygems_version: !ruby/object:Gem::Requirement
70
+ none: false
71
+ requirements:
72
+ - - ! '>='
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ segments:
76
+ - 0
77
+ hash: 3585342747307682113
78
+ requirements: []
79
+ rubyforge_project:
80
+ rubygems_version: 1.8.17
81
+ signing_key:
82
+ specification_version: 3
83
+ summary: Ruby extensions
84
+ test_files:
85
+ - spec/enumerable_spec.rb
86
+ - spec/spec.opts
87
+ - spec/spec_helper.rb
88
+ has_rdoc: