midwire_common 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/.gitignore ADDED
@@ -0,0 +1,18 @@
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
18
+ vendor/ruby
data/.rspec ADDED
@@ -0,0 +1,2 @@
1
+ --format documentation
2
+ --color
data/CHANGELOG ADDED
@@ -0,0 +1,3 @@
1
+ *0.1.0* (March 29, 2012)
2
+
3
+ * Initial Commit
data/Gemfile ADDED
@@ -0,0 +1,2 @@
1
+ source :rubygems
2
+ gemspec
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard 'rspec', :version => 2, :cli => '--color --format doc', all_on_start: false, all_after_pass: false do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^lib/(.+)\.rb$}) { |m| "spec/lib/#{m[1]}_spec.rb" }
4
+ watch('spec/spec_helper.rb') { "spec" }
5
+ end
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2012 Midwire Technologies, LLC
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,44 @@
1
+ # Midwire Common Gem
2
+
3
+ **Version: 0.1.0**
4
+
5
+ A handy Ruby library for Midwire development
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'midwire_common', :require => 'midwire'
12
+
13
+ And then execute:
14
+
15
+ $ bundle install
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install midwire_common
20
+
21
+ ## Usage
22
+
23
+ ### Ruby Class Extensions
24
+
25
+ To use the standard class extensions you must include the individual files or 'midwire/all' to include everything:
26
+
27
+ require 'midwire/all'
28
+
29
+ require 'midwire/string'
30
+ require 'midwire/array'
31
+
32
+ ### Rake Tasks
33
+
34
+ To use the rake tasks simply `load` that rake file from within your main `Rakefile`:
35
+
36
+ load "version.rake"
37
+
38
+ ## Contributing
39
+
40
+ 1. Fork it
41
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
42
+ 3. Commit your changes (`git commit -am 'Added some feature'`)
43
+ 4. Push to the branch (`git push origin my-new-feature`)
44
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env rake
2
+ require "bundler/gem_tasks"
3
+ Dir["lib/tasks/**/*.rake"].sort.each { |ext| load ext }
4
+
5
+ # RSpec Tasks
6
+ require 'rspec/core/rake_task'
7
+ RSpec::Core::RakeTask.new('spec')
8
+ task :default => :spec
@@ -0,0 +1,8 @@
1
+ require 'midwire_common/array'
2
+ require 'midwire_common/enumerable'
3
+ require 'midwire_common/file'
4
+ require 'midwire_common/fixnum'
5
+ require 'midwire_common/float'
6
+ require 'midwire_common/hash'
7
+ require 'midwire_common/string'
8
+ require 'midwire_common/time'
@@ -0,0 +1,49 @@
1
+ class Array
2
+ def count_occurrences
3
+ k = Hash.new(0)
4
+ self.each{|x| k[x] += 1}
5
+ k
6
+ end
7
+
8
+ def randomize
9
+ self.sort_by { rand }
10
+ end
11
+
12
+ def randomize!
13
+ self.replace(self.randomize)
14
+ end
15
+
16
+ def sort_case_insensitive
17
+ self.sort_by {|x| x.downcase}
18
+ end
19
+
20
+ def each_with_first_last(first_code, main_code, last_code)
21
+ each_with_index do |item, i|
22
+ case i
23
+ when 0 then first_code.call(item)
24
+ when size - 1 then last_code.call(item)
25
+ else main_code.call(item)
26
+ end
27
+ end
28
+ end
29
+
30
+ # Binary search returns index if found or nil
31
+ def bsearch(e, l = 0, u = length - 1)
32
+ return if l>u;m=(l+u)/2;e<self[m]?u=m-1:l=m+1;e==self[m]?m:bsearch(e,l,u)
33
+ end
34
+
35
+ # Make a string from a multi-dimensional array :
36
+ # 1 dimension :
37
+ # [1,2,3].superjoin(["pre-array","between-cell","post-array"])
38
+ #
39
+ # 2 dimensions: (html table)
40
+ # [[1,2],[2,3]].superjoin( %w{<table><tr> </tr><tr> </tr></table>}, %w{<td> </td><td> </td>} )
41
+ # => <table><tr><td>1</td><td>2</td></tr><tr><td>2</td><td>3</td></tr></table>
42
+ def superjoin(*ldescr)
43
+ d, rest = ldescr[0], ldescr[1..-1]
44
+ d[0] + self.map {|a|
45
+ (a.respond_to?(:superjoin) && rest.length > 0) ? a.superjoin(*rest) : a.to_s
46
+ }.join(d[1]) + d[2]
47
+ end
48
+
49
+ end
@@ -0,0 +1,7 @@
1
+ module Enumerable
2
+ # Sort by frequency of occurrence
3
+ def sort_by_frequency
4
+ histogram = inject(Hash.new(0)) {|hash, x| hash[x] += 1; hash}
5
+ sort_by {|x| [histogram[x] * -1, x]}
6
+ end
7
+ end
@@ -0,0 +1,9 @@
1
+ class File
2
+ class Stat
3
+ def self.device_name(file)
4
+ Dir['/dev/*'].inject({}) { |h, v|
5
+ h.update(File.stat(v).rdev => v)
6
+ }.values_at(File.stat(file).dev).first || nil
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,2 @@
1
+ require 'midwire_common/file/stat'
2
+
@@ -0,0 +1,18 @@
1
+ class Fixnum
2
+ # Format a number with commas and a decimal point
3
+ def commify
4
+ to_s =~ /([^\.]*)(\..*)?/
5
+ int, dec = $1.reverse, $2 ? $2 : ""
6
+ while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
7
+ end
8
+ int.reverse + dec
9
+ end
10
+
11
+ def is_even?
12
+ self % 2 == 0
13
+ end
14
+
15
+ def is_odd?
16
+ !is_even?
17
+ end
18
+ end
@@ -0,0 +1,10 @@
1
+ class Float
2
+ # Format a number with commas and a decimal point
3
+ def commify
4
+ to_s =~ /([^\.]*)(\..*)?/
5
+ int, dec = $1.reverse, $2 ? $2 : ""
6
+ while int.gsub!(/(,|\.|^)(\d{3})(\d)/, '\1\2,\3')
7
+ end
8
+ int.reverse + dec
9
+ end
10
+ end
@@ -0,0 +1,51 @@
1
+ class Hash
2
+ def grep(pattern)
3
+ inject([]) do |res, kv|
4
+ res << kv if kv[0] =~ pattern or kv[1] =~ pattern
5
+ res
6
+ end
7
+ end
8
+
9
+ # Usage { :a => 1, :b => 2, :c => 3}.except(:a) -> { :b => 2, :c => 3}
10
+ def except(*keys)
11
+ self.reject { |k,v|
12
+ keys.include? k.to_sym
13
+ }
14
+ end
15
+
16
+ # Usage { :a => 1, :b => 2, :c => 3}.only(:a) -> {:a => 1}
17
+ def only(*keys)
18
+ self.dup.reject { |k,v|
19
+ !keys.include? k.to_sym
20
+ }
21
+ end
22
+
23
+ # Usage { :a => 1, :b => 2, :c => 3}.to_query_string #= a=1&b=2&c=3
24
+ def to_query_string
25
+ require 'uri'
26
+ collect do |k, v|
27
+ "#{URI.encode(k.to_s)}=#{URI.encode(v.to_s)}"
28
+ end.join("&")
29
+ end
30
+
31
+ def symbolize_keys!
32
+ keys.each do |key|
33
+ self[(key.to_sym rescue key) || key] = delete(key)
34
+ end
35
+ self
36
+ end
37
+
38
+ def symbolize_keys
39
+ dup.symbolize_keys!
40
+ end
41
+
42
+ def recursively_symbolize_keys!
43
+ self.symbolize_keys!
44
+ self.values.each do |v|
45
+ if v.is_a? Hash
46
+ v.recursively_symbolize_keys!
47
+ end
48
+ end
49
+ self
50
+ end
51
+ end
@@ -0,0 +1,122 @@
1
+ require 'thor'
2
+ require 'midwire_common'
3
+
4
+ module MidwireCommon
5
+ class RakeHelper
6
+ include Rake::DSL if defined? Rake::DSL
7
+
8
+ def self.install_tasks(opts = {})
9
+ dir = opts[:dir] || Dir.pwd
10
+ self.new(dir).install
11
+ end
12
+
13
+ attr_reader :base
14
+
15
+ def initialize(base)
16
+ @base = base
17
+ end
18
+
19
+ def install
20
+ task_dir = File.expand_path("../tasks", File.dirname(__FILE__))
21
+ Dir["#{task_dir}/*.rake"].sort.each { |ext| load ext }
22
+ end
23
+
24
+ # def build_gem
25
+ # file_name = nil
26
+ # sh("gem build -V '#{spec_path}'") { |out, code|
27
+ # file_name = File.basename(built_gem_path)
28
+ # FileUtils.mkdir_p(File.join(base, 'pkg'))
29
+ # FileUtils.mv(built_gem_path, 'pkg')
30
+ # Bundler.ui.confirm "#{name} #{version} built to pkg/#{file_name}"
31
+ # }
32
+ # File.join(base, 'pkg', file_name)
33
+ # end
34
+
35
+ def install_gem
36
+ built_gem_path = build_gem
37
+ out, _ = sh_with_code("gem install '#{built_gem_path}'")
38
+ raise "Couldn't install gem, run `gem install #{built_gem_path}' for more detailed output" unless out[/Successfully installed/]
39
+ Bundler.ui.confirm "#{name} (#{version}) installed"
40
+ end
41
+
42
+ def release_gem
43
+ guard_clean
44
+ guard_already_tagged
45
+ built_gem_path = build_gem
46
+ tag_version {
47
+ git_push
48
+ rubygem_push(built_gem_path)
49
+ }
50
+ end
51
+
52
+ ##################################################
53
+ protected
54
+
55
+ def rubygem_push(path)
56
+ if Pathname.new("~/.gem/credentials").expand_path.exist?
57
+ sh("gem push '#{path}'")
58
+ Bundler.ui.confirm "Pushed #{name} #{version} to rubygems.org"
59
+ else
60
+ raise "Your rubygems.org credentials aren't set. Run `gem push` to set them."
61
+ end
62
+ end
63
+
64
+ def built_gem_path
65
+ Dir[File.join(base, "#{name}-*.gem")].sort_by{|f| File.mtime(f)}.last
66
+ end
67
+
68
+ def git_push
69
+ perform_git_push
70
+ perform_git_push ' --tags'
71
+ Bundler.ui.confirm "Pushed git commits and tags"
72
+ end
73
+
74
+ def perform_git_push(options = '')
75
+ cmd = "git push #{options}"
76
+ out, code = sh_with_code(cmd)
77
+ raise "Couldn't git push. `#{cmd}' failed with the following output:\n\n#{out}\n" unless code == 0
78
+ end
79
+
80
+ def guard_already_tagged
81
+ if sh('git tag').split(/\n/).include?(version_tag)
82
+ raise("This tag has already been committed to the repo.")
83
+ end
84
+ end
85
+
86
+ def guard_clean
87
+ clean? or raise("There are files that need to be committed first.")
88
+ end
89
+
90
+ def clean?
91
+ sh_with_code("git diff --exit-code")[1] == 0
92
+ end
93
+
94
+ def tag_version
95
+ sh "git tag -a -m \"Version #{version}\" #{version_tag}"
96
+ Bundler.ui.confirm "Tagged #{version_tag}"
97
+ yield if block_given?
98
+ rescue
99
+ Bundler.ui.error "Untagged #{version_tag} due to error"
100
+ sh_with_code "git tag -d #{version_tag}"
101
+ raise
102
+ end
103
+
104
+ def sh(cmd, &block)
105
+ out, code = sh_with_code(cmd, &block)
106
+ code == 0 ? out : raise(out.empty? ? "Running `#{cmd}' failed. Run this command directly for more detailed output." : out)
107
+ end
108
+
109
+ def sh_with_code(cmd, &block)
110
+ cmd << " 2>&1"
111
+ outbuf = ''
112
+ Bundler.ui.debug(cmd)
113
+ Dir.chdir(base) {
114
+ outbuf = `#{cmd}`
115
+ if $? == 0
116
+ block.call(outbuf) if block
117
+ end
118
+ }
119
+ [outbuf, $?]
120
+ end
121
+ end
122
+ end
@@ -0,0 +1,2 @@
1
+ require 'midwire_common/rake_helper'
2
+ MidwireCommon::RakeHelper.install_tasks
@@ -0,0 +1,155 @@
1
+ class String
2
+
3
+ class << self
4
+ def random(count = 6, ranges = [('a'..'z'),('A'..'Z'),('0'..'9')])
5
+ o = ranges.map{|i| i.to_a}.flatten;
6
+ string = (0..(count-1)).map{ o[rand(o.length)] }.join;
7
+ end
8
+ end
9
+
10
+ def left(count)
11
+ self.slice(0,count)
12
+ end
13
+
14
+ def right(count)
15
+ self.slice(-count,count)
16
+ end
17
+
18
+ def left_trim
19
+ # remove leading whitespace
20
+ self.gsub(/^[\t\s]+/, '')
21
+ end
22
+
23
+ def left_trim!
24
+ self.gsub!(/^[\t\s]+/, '') || ''
25
+ end
26
+
27
+ def right_trim
28
+ # remove trailing whitespace
29
+ self.gsub(/[\t\s]+$/, '')
30
+ end
31
+
32
+ def right_trim!
33
+ self.gsub!(/[\t\s]+$/, '') || ''
34
+ end
35
+
36
+ def trim
37
+ # remove leading and trailing whitespace
38
+ self.left_trim.right_trim
39
+ end
40
+
41
+ def trim!
42
+ # remove leading and trailing whitespace
43
+ self.left_trim!.right_trim! || ''
44
+ end
45
+
46
+ # html = <<-stop.here_with_pipe
47
+ # |<!-- Begin: comment -->
48
+ # |<script type="text/javascript">
49
+ # stop
50
+ def here_with_pipe(linefeeds = false)
51
+ lines = self.split("\n")
52
+ lines.map! {|c| c.sub!(/\s*\|/, '')}
53
+ new_string = lines.join(linefeeds ? "\n" : " ")
54
+ self.replace(new_string)
55
+ end
56
+
57
+ def is_alpha_numeric?
58
+ regex = /^[a-zA-Z0-9]+$/
59
+ return (self =~ regex) == 0 ? true : false
60
+ end
61
+
62
+ def is_email_address?
63
+ # //Email address
64
+ # //Use this version to seek out email addresses in random documents and texts.
65
+ # //Does not match email addresses using an IP address instead of a domain name.
66
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
67
+ # //Including these increases the risk of false positives when applying the regex to random documents.
68
+ # '\b[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}\b'
69
+ #
70
+ # //Email address (anchored)
71
+ # //Use this anchored version to check if a valid email address was entered.
72
+ # //Does not match email addresses using an IP address instead of a domain name.
73
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
74
+ # //Requires the "case insensitive" option to be ON.
75
+ # '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$'
76
+ #
77
+ # //Email address (anchored; no consecutive dots)
78
+ # //Use this anchored version to check if a valid email address was entered.
79
+ # //Improves on the original email address regex by excluding addresses with consecutive dots such as john@aol...com
80
+ # //Does not match email addresses using an IP address instead of a domain name.
81
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
82
+ # //Including these increases the risk of false positives when applying the regex to random documents.
83
+ # '^[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}$'
84
+ #
85
+ # //Email address (no consecutive dots)
86
+ # //Use this version to seek out email addresses in random documents and texts.
87
+ # //Improves on the original email address regex by excluding addresses with consecutive dots such as john@aol...com
88
+ # //Does not match email addresses using an IP address instead of a domain name.
89
+ # //Does not match email addresses on new-fangled top-level domains with more than 4 letters such as .museum.
90
+ # //Including these increases the risk of false positives when applying the regex to random documents.
91
+ # '\b[A-Z0-9._%-]+@(?:[A-Z0-9-]+\.)+[A-Z]{2,4}\b'
92
+ #
93
+ # //Email address (specific TLDs)
94
+ # //Does not match email addresses using an IP address instead of a domain name.
95
+ # //Matches all country code top level domains, and specific common top level domains.
96
+ # '^[A-Z0-9._%-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|biz|info|name|aero|biz|info|jobs|museum|name)$'
97
+ #
98
+ # //Email address: Replace with HTML link
99
+ # '\b(?:mailto:)?([A-Z0-9._%-]+@[A-Z0-9.-]+\.[A-Z]{2,4})\b'
100
+
101
+ email_regex = %r{^[A-Z0-9._%-]+@[A-Z0-9.-]+\.(?:[A-Z]{2}|com|org|net|biz|info|name|aero|jobs|museum|edu|pro)$}xi # Case insensitive
102
+
103
+ return (self =~ email_regex) == 0 ? true : false
104
+ end
105
+
106
+ def is_zipcode?
107
+ self =~ %r{^(\d{5})(-\d{4})?$}x ? true : false
108
+ end
109
+
110
+ def is_numeric?
111
+ begin
112
+ Float(self)
113
+ rescue
114
+ false # not numeric
115
+ else
116
+ true # numeric
117
+ end
118
+ end
119
+
120
+ def format_phone
121
+ self.gsub!(/[a-z,! \-\(\)\:\;\.\&\$]+/i, '')
122
+ '(' << slice(0..2) << ')' << slice(3..5) << '-' << slice(-4,4)
123
+ end
124
+
125
+ def sanitize
126
+ self.gsub(/[^a-z0-9,! \-\(\)\:\;\.\&\$]+/i, '')
127
+ end
128
+
129
+ def sanitize!
130
+ self.gsub!(/[^a-z0-9,! \-\(\)\:\;\.\&\$]+/i, '')
131
+ end
132
+
133
+ def shorten(maxcount = 30)
134
+ if self.length >= maxcount
135
+ shortened = self[0, maxcount]
136
+ splitted = shortened.split(/\s/)
137
+ if splitted.length > 1
138
+ words = splitted.length
139
+ splitted[0, words-1].join(" ") + '...'
140
+ else
141
+ shortened[0, maxcount - 3] + '...'
142
+ end
143
+ else
144
+ self
145
+ end
146
+ end
147
+
148
+ def escape_single_quotes
149
+ self.gsub(/[']/, '\\\\\'')
150
+ end
151
+
152
+ def escape_double_quotes
153
+ self.gsub(/["]/, '\\\\\"')
154
+ end
155
+ end
@@ -0,0 +1,9 @@
1
+ class Time
2
+
3
+ class << self
4
+ def timestamp
5
+ "#{Time.now.strftime("%Y%m%d%k%M%S")}"
6
+ end
7
+ end
8
+
9
+ end
@@ -0,0 +1,6 @@
1
+ original_verbosity = $VERBOSE
2
+ $VERBOSE = nil
3
+ module MidwireCommon
4
+ VERSION = "0.1.0"
5
+ end
6
+ $VERBOSE = original_verbosity
@@ -0,0 +1,6 @@
1
+ require 'pathname'
2
+ require "midwire_common/version"
3
+
4
+ module Midwire
5
+ autoload :RakeHelper, 'midwire_common/rake_helper'
6
+ end
@@ -0,0 +1,118 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'readline'
4
+ require 'fileutils'
5
+
6
+ module Bundler
7
+ class GemHelper
8
+
9
+ protected
10
+
11
+ # Push the gem to your own internal gem inabox server
12
+ # def rubygem_push(path)
13
+ # sh("gem inabox '#{path}'")
14
+ # Bundler.ui.confirm "Pushed #{name} #{version} to #{path}"
15
+ # end
16
+ end
17
+ end
18
+
19
+ namespace :version do
20
+ PROJECT_ROOT = File.expand_path(FileUtils.pwd)
21
+ PROJECT_NAME = ENV['PROJECT_NAME'] || File.basename(PROJECT_ROOT)
22
+
23
+ desc "Write changes to the CHANGELOG"
24
+ task :changes do
25
+ text = ask("CHANGELOG Entry:")
26
+ text.insert(0, "*#{read_version.join('.')}* (#{Time.now.strftime("%B %d, %Y")})\n\n")
27
+ text << "\n"
28
+ prepend_changelog(text)
29
+ system("#{ENV['EDITOR']} CHANGELOG")
30
+ end
31
+
32
+ desc "Increment the patch version and write changes to the changelog"
33
+ task :bump_patch do
34
+ major, minor, patch = read_version
35
+ patch = patch.to_i + 1
36
+ write_version([major, minor, patch])
37
+ version_string = read_version.join('.')
38
+ readme = open('README.md').read
39
+ File.open('README.md', 'w') {|f| f.write(readme.gsub(/^\*\*Version: [0-9\.]+\*\*$/, "**Version: #{version_string}**")) }
40
+ Rake::Task["version:changes"].invoke
41
+ end
42
+ desc "Alias for :bump_patch"
43
+ task :bump => :bump_patch do; end
44
+
45
+ desc "Increment the minor version and write changes to the changelog"
46
+ task :bump_minor do
47
+ major, minor, patch = read_version
48
+ minor = minor.to_i + 1
49
+ patch = 0
50
+ write_version([major, minor, patch])
51
+ Rake::Task["version:changes"].invoke
52
+ end
53
+
54
+ desc "Increment the major version and write changes to the changelog"
55
+ task :bump_major do
56
+ major, minor, patch = read_version
57
+ major = major.to_i + 1
58
+ minor = 0
59
+ patch = 0
60
+ write_version([major, minor, patch])
61
+ Rake::Task["version:changes"].invoke
62
+ end
63
+
64
+ ##################################################
65
+ private
66
+
67
+ def version_file_path
68
+ "#{PROJECT_ROOT}/lib/#{PROJECT_NAME}/version.rb"
69
+ end
70
+
71
+ def read_version
72
+ # Get module name
73
+ lines = File.readlines(version_file_path)
74
+ module_name = nil
75
+ if module_line = lines.grep(/^module/)
76
+ module_name = module_line.flatten[0].scan(/[^\s]+\s+([A-Za-z]+)$/).flatten[0]
77
+ end
78
+ load version_file_path
79
+ text = eval("#{module_name}::VERSION")
80
+ major, minor, patch = text.split('.')
81
+ end
82
+
83
+ def write_version(version_array)
84
+ version = version_array.join('.')
85
+ new_version = %Q( VERSION = "#{version}")
86
+ lines = File.readlines(version_file_path)
87
+ File.open(version_file_path, 'w') do |f|
88
+ lines.each do |line|
89
+ if line =~ /VERSION/
90
+ f.write("#{new_version.to_s}\n")
91
+ else
92
+ f.write(line)
93
+ end
94
+ end
95
+ end
96
+ end
97
+
98
+ def prepend_changelog(text_array)
99
+ # read current changelog
100
+ old = File.read("#{PROJECT_ROOT}/CHANGELOG").to_s.chomp
101
+ text_array.push(old)
102
+ File.open("#{PROJECT_ROOT}/CHANGELOG", 'w') do |f|
103
+ text_array.flatten.each do |line|
104
+ f.puts(line)
105
+ end
106
+ end
107
+ end
108
+
109
+ def ask(message)
110
+ response = []
111
+ puts message
112
+ puts "Hit <Control>-D when finished:"
113
+ while line = Readline.readline('* ', false)
114
+ response << "* #{line.chomp}" unless line.nil?
115
+ end
116
+ response
117
+ end
118
+ end
@@ -0,0 +1,27 @@
1
+ # -*- encoding: utf-8 -*-
2
+ require File.expand_path('../lib/midwire_common/version', __FILE__)
3
+
4
+ Gem::Specification.new do |gem|
5
+ gem.authors = ["Chris Blackburn"]
6
+ gem.email = ["chris@midwiretech.com"]
7
+ gem.description = %q{A useful Ruby library for the Midwire development team}
8
+ gem.summary = %q{Midiwre Ruby Library}
9
+ gem.homepage = "http://git-2.americadirect.net/prosup"
10
+
11
+ gem.files = `git ls-files`.split($\)
12
+ gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
13
+ gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
14
+ gem.name = "midwire_common"
15
+ gem.require_paths = ["lib"]
16
+ gem.version = MidwireCommon::VERSION
17
+
18
+ gem.add_development_dependency "rspec"
19
+ gem.add_development_dependency "simplecov"
20
+ gem.add_development_dependency "guard"
21
+ gem.add_development_dependency "guard-bundler"
22
+ gem.add_development_dependency "guard-rspec"
23
+ gem.add_development_dependency "growl"
24
+ gem.add_development_dependency "rb-fsevent"
25
+ gem.add_development_dependency "pry"
26
+ gem.add_development_dependency "rake"
27
+ end
@@ -0,0 +1,42 @@
1
+ require 'spec_helper'
2
+
3
+ describe Array do
4
+ it "counts occurrences of an element" do
5
+ [1,2,2,3,3,3].count_occurrences.should == {1=>1, 2=>2, 3=>3}
6
+ ['asdf','asdf','qwer','asdf'].count_occurrences.should == {'asdf'=>3, 'qwer'=>1}
7
+ end
8
+
9
+ it "randomizes the order of an array" do
10
+ myarray = [1,2,3,4,5,6,7,8,9,'0']
11
+ myarray.randomize.should_not == myarray
12
+ myarray.randomize!
13
+ myarray.should_not == [1,2,3,4,5,6,7,8,9,'0']
14
+ end
15
+
16
+ it "sorts elements case insensitive" do
17
+ myarray = %w(zebra ghost Zebra cat Cat)
18
+ myarray.sort_case_insensitive.should == ["Cat", "cat", "ghost", "Zebra", "zebra"]
19
+ end
20
+
21
+ it "can process first and last entries differently than others" do
22
+ text = ''
23
+ ["KU", "K-State", "MU"].each_with_first_last(
24
+ lambda {|team| text += "#{team} came first in the NCAA basketball tournament.\n"},
25
+ lambda {|team| text += "#{team} did not come first or last in the final four.\n"},
26
+ lambda {|team| text += "#{team} came last in the final four this year.\n"}
27
+ )
28
+ text.should == "KU came first in the NCAA basketball tournament.\nK-State did not come first or last in the final four.\nMU came last in the final four this year.\n"
29
+ end
30
+
31
+ it "can binary search for elements" do
32
+ a = %w(a b c)
33
+ a.bsearch('a').should == 0
34
+ a.bsearch('b').should == 1
35
+ a.bsearch('c').should == 2
36
+ end
37
+
38
+ it "can superjoin elements" do
39
+ [1,2,3].superjoin(["->","+","<-"]).should == "->1+2+3<-"
40
+ [[1,2],[2,3]].superjoin( %w{<table><tr> </tr><tr> </tr></table>}, %w{<td> </td><td> </td>} ).should == "<table><tr><td>1</td><td>2</td></tr><tr><td>2</td><td>3</td></tr></table>"
41
+ end
42
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Enumerable do
4
+ it "can sort by frequency of occurrences" do
5
+ [1,2,3,3,3,3,2].sort_by_frequency.should == [3, 3, 3, 3, 2, 2, 1]
6
+ %w(a b c d e f a f f b f a).sort_by_frequency.should == ["f", "f", "f", "f", "a", "a", "a", "b", "b", "c", "d", "e"]
7
+ end
8
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe File::Stat do
4
+ it "knows on which devise it resides" do
5
+ s = File::Stat.device_name("/tmp")
6
+ s.should_not be_nil
7
+ end
8
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+
3
+ describe Fixnum do
4
+ it "knows if it is odd or even" do
5
+ 777.is_odd?.should be_true
6
+ 776.is_odd?.should be_false
7
+
8
+ 777.is_even?.should be_false
9
+ 776.is_even?.should be_true
10
+ end
11
+
12
+ it "can format itself with commas" do
13
+ 8729928827.commify.should == "8,729,928,827"
14
+ end
15
+ end
@@ -0,0 +1,8 @@
1
+ require 'spec_helper'
2
+
3
+ describe Float do
4
+ it "can format itself with commas" do
5
+ 8729928827.0.commify.should == "8,729,928,827.0"
6
+ 8729928827.20332002.commify.should == "8,729,928,827.20332"
7
+ end
8
+ end
@@ -0,0 +1,34 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hash do
4
+ it "greps key/value pairs using a regular expression" do
5
+ h = {:a => "this is a test", 'b' => 'this is not the answer'}
6
+ h.grep(/a test/).should == [[:a, "this is a test"]]
7
+ h.grep(/b/).should == [['b', "this is not the answer"]]
8
+ h.grep(/^this/).should == [[:a, "this is a test"], ["b", "this is not the answer"]]
9
+ end
10
+
11
+ it "returns elements with certain keys filtered out" do
12
+ {:a => 1, :b => 2, :c => 3}.except(:a).should == {:b => 2, :c => 3}
13
+ end
14
+
15
+ it "returns elements for discretely passed keys" do
16
+ {:a => 1, :b => 2, :c => 3}.only(:a).should == {:a => 1}
17
+ end
18
+
19
+ it "returns a query string" do
20
+ { :a => 1, :b => 2, :c => 3}.to_query_string.should == "a=1&b=2&c=3"
21
+ end
22
+
23
+ it "symbolizes its keys" do
24
+ h = {'a'=>1, 'b'=>2, 'c'=>3}
25
+ h.symbolize_keys.should == {:a=>1, :b=>2, :c=>3}
26
+ h.symbolize_keys!
27
+ h.should == {:a=>1, :b=>2, :c=>3}
28
+ end
29
+
30
+ it "recursively symbolizes its keys" do
31
+ h = {'a'=>1, 'b'=>{'a'=>1, 'b'=>2, 'c'=>{'a'=>1, 'b'=>2, 'c'=>3}}, 'c'=>3}
32
+ h.recursively_symbolize_keys!.should == {:a=>1, :b=>{:a=>1, :b=>2, :c=>{:a=>1, :b=>2, :c=>3}}, :c=>3}
33
+ end
34
+ end
@@ -0,0 +1,161 @@
1
+ # encoding: ascii-8bit
2
+ require 'spec_helper'
3
+
4
+ describe String do
5
+ it "is a String" do
6
+ String.new.should be_a String
7
+ end
8
+
9
+ it "generates a random string" do
10
+ String.random.length.should == 6
11
+ end
12
+
13
+ context "slicing methods" do
14
+ it "'left' returns the leftmost 'n' characters" do
15
+ "My Bogus String".left(2).should == "My"
16
+ end
17
+
18
+ it "'right' returns the rightmost 'n' characters " do
19
+ "My Bogus String".right(2).should == "ng"
20
+ end
21
+ end
22
+
23
+ context "trim method" do
24
+ it "'left_trim' removes all whitespace from the left of the string" do
25
+ " \t = this is a string".left_trim.should == '= this is a string'
26
+ end
27
+
28
+ it "'left_trim!' removes all whitespace from the left of the string" do
29
+ mystring = " \t \t a test is coming"
30
+ mystring.left_trim!
31
+ mystring.should == 'a test is coming'
32
+ end
33
+
34
+ it "'right_trim' removes all whitespace from the right of the string" do
35
+ "= this is a string \t ".right_trim.should == '= this is a string'
36
+ end
37
+
38
+ it "'right_trim!' removes all whitespace from the right of the string" do
39
+ mystring = " \t \t a test is coming \t \t "
40
+ mystring.right_trim!
41
+ mystring.should == " \t \t a test is coming"
42
+ end
43
+
44
+ it "'trim' removes whitespace from both sides of the string" do
45
+ " \t \t a test is coming \t \t ".trim.should == "a test is coming"
46
+ end
47
+
48
+ it "'trim!' removes whitespace from both sides of the string" do
49
+ mystring = " \t \t a test is coming \t \t "
50
+ mystring.trim!
51
+ mystring.should == "a test is coming"
52
+ end
53
+ end
54
+
55
+ context "formatting and manipulation" do
56
+ it "here_with_pipe - without linefeeds" do
57
+ html = <<-STOP.here_with_pipe
58
+ |<!-- Begin: comment -->
59
+ |<script type="text/javascript">
60
+ |</script>
61
+ STOP
62
+ html.should == "<!-- Begin: comment --> <script type=\"text/javascript\"> </script>"
63
+ end
64
+
65
+ it "here_with_pipe - with linefeeds" do
66
+ html = <<-STOP.here_with_pipe(true)
67
+ |<!-- Begin: comment -->
68
+ |<script type="text/javascript">
69
+ |</script>
70
+ STOP
71
+ html.should == "<!-- Begin: comment -->\n<script type=\"text/javascript\">\n</script>"
72
+ end
73
+
74
+ it "format_phone returns a formatted phone number string" do
75
+ "9132329999".format_phone.should == "(913)232-9999"
76
+ "913.232.9999".format_phone.should == "(913)232-9999"
77
+ "913 232 9999".format_phone.should == "(913)232-9999"
78
+ "913-232-9999".format_phone.should == "(913)232-9999"
79
+ end
80
+
81
+ it "sanitizes itself" do
82
+ "|bogus|".sanitize.should == "bogus"
83
+ "|∫|ß".sanitize.should == ""
84
+ "ßogus".sanitize.should == "ogus"
85
+ "<tag>bogus</tag>".sanitize.should == "tagbogustag"
86
+ "<tag>.bogus.</tag>".sanitize.should == "tag.bogus.tag"
87
+ s = "|∫|ß"
88
+ s.sanitize!
89
+ s.should == ""
90
+ end
91
+
92
+ it "shortens itself with elipses at the end" do
93
+ s = "this is my very long string which I will eventually shorten with the enhanced String class that we are now testing."
94
+ short = s.shorten
95
+ short.should == "this is my very long string..."
96
+ short.length.should == 30
97
+
98
+ s = "1234567890123456789012345678901234567890"
99
+ short = s.shorten
100
+ short.should == "123456789012345678901234567..."
101
+ short.length.should == 30
102
+
103
+ s = "12345678901234567890"
104
+ short = s.shorten
105
+ short.should == "12345678901234567890"
106
+ short.length.should == 20
107
+ end
108
+
109
+ context "quotes" do
110
+ it "escapes single quotes" do
111
+ "this is a 'test'".escape_single_quotes.should == "this is a \\'test\\'"
112
+ end
113
+
114
+ it "escapes double quotes" do
115
+ 'this is a "test"'.escape_double_quotes.should == "this is a \\\\\"test\\\\\""
116
+ end
117
+ end
118
+ end
119
+
120
+ context "characterization" do
121
+ it "knows if it is alpha-numeric or not" do
122
+ "abcd-9191".is_alpha_numeric?.should be_false
123
+ "abcd.9191".is_alpha_numeric?.should be_false
124
+ "abcd91910".is_alpha_numeric?.should be_true
125
+ "abcd_9191".is_alpha_numeric?.should be_false
126
+ "abcd 9191".is_alpha_numeric?.should be_false
127
+ end
128
+
129
+ it "knows if it is an email address or not" do
130
+ "abcd_9191".is_email_address?.should be_false
131
+ "abcd@9191".is_email_address?.should be_false
132
+ "abcd@9191.poop".is_email_address?.should be_false
133
+ "abcd@9191.info".is_email_address?.should be_true
134
+ "abcd-asdf@9191.com".is_email_address?.should be_true
135
+ "abcd_asdf@9191.com".is_email_address?.should be_true
136
+ "abcd.asdf@9191.com".is_email_address?.should be_true
137
+ end
138
+
139
+ it "knows if it is a zipcode or not" do
140
+ "13922-2356".is_zipcode?.should be_true
141
+ "13922.2343".is_zipcode?.should be_false
142
+ "13922 2342".is_zipcode?.should be_false
143
+ "ABSSD".is_zipcode?.should be_false
144
+ "i3323".is_zipcode?.should be_false
145
+ "13922".is_zipcode?.should be_true
146
+ end
147
+
148
+ it "knows if it is numeric or not" do
149
+ "12341".is_numeric?.should be_true
150
+ "12341.23".is_numeric?.should be_true
151
+ "12341.00000000000000023".is_numeric?.should be_true
152
+ "0.12341".is_numeric?.should be_true
153
+ "0x2E".is_numeric?.should be_true
154
+ " 0.12341".is_numeric?.should be_true
155
+ " 0.12341 ".is_numeric?.should be_true
156
+ ".12341".is_numeric?.should be_true
157
+ " 12341.".is_numeric?.should be_false
158
+ " 12341. ".is_numeric?.should be_false
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Time do
4
+ it "generates a timestamp, appropriate for a filename" do
5
+ ts = Time.timestamp
6
+ ts.length.should == 14
7
+ ts.is_alpha_numeric?.should be_true
8
+ ts.is_numeric?.should be_true
9
+ end
10
+ end
@@ -0,0 +1,31 @@
1
+ if ENV['COVERAGE']
2
+ require 'simplecov'
3
+ SimpleCov.start do
4
+ add_filter "spec/"
5
+ add_filter "vendor/"
6
+ end
7
+ end
8
+
9
+ require "pry"
10
+ require File.join(File.dirname(__FILE__), '..', 'lib', 'midwire_common')
11
+ require "midwire_common/all"
12
+
13
+ PROJECT_ROOT = File.expand_path('..', File.dirname(__FILE__))
14
+
15
+ RSpec.configure do |config|
16
+ config.mock_with :rspec
17
+ config.color_enabled = true
18
+
19
+ def capture(stream)
20
+ begin
21
+ stream = stream.to_s
22
+ eval "$#{stream} = StringIO.new"
23
+ yield
24
+ result = eval("$#{stream}").string
25
+ ensure
26
+ eval("$#{stream} = #{stream.upcase}")
27
+ end
28
+
29
+ result
30
+ end
31
+ end
metadata ADDED
@@ -0,0 +1,231 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: midwire_common
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Chris Blackburn
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-28 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rspec
16
+ requirement: !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :development
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ! '>='
28
+ - !ruby/object:Gem::Version
29
+ version: '0'
30
+ - !ruby/object:Gem::Dependency
31
+ name: simplecov
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ! '>='
36
+ - !ruby/object:Gem::Version
37
+ version: '0'
38
+ type: :development
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ - !ruby/object:Gem::Dependency
47
+ name: guard
48
+ requirement: !ruby/object:Gem::Requirement
49
+ none: false
50
+ requirements:
51
+ - - ! '>='
52
+ - !ruby/object:Gem::Version
53
+ version: '0'
54
+ type: :development
55
+ prerelease: false
56
+ version_requirements: !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ! '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ - !ruby/object:Gem::Dependency
63
+ name: guard-bundler
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ! '>='
68
+ - !ruby/object:Gem::Version
69
+ version: '0'
70
+ type: :development
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ! '>='
76
+ - !ruby/object:Gem::Version
77
+ version: '0'
78
+ - !ruby/object:Gem::Dependency
79
+ name: guard-rspec
80
+ requirement: !ruby/object:Gem::Requirement
81
+ none: false
82
+ requirements:
83
+ - - ! '>='
84
+ - !ruby/object:Gem::Version
85
+ version: '0'
86
+ type: :development
87
+ prerelease: false
88
+ version_requirements: !ruby/object:Gem::Requirement
89
+ none: false
90
+ requirements:
91
+ - - ! '>='
92
+ - !ruby/object:Gem::Version
93
+ version: '0'
94
+ - !ruby/object:Gem::Dependency
95
+ name: growl
96
+ requirement: !ruby/object:Gem::Requirement
97
+ none: false
98
+ requirements:
99
+ - - ! '>='
100
+ - !ruby/object:Gem::Version
101
+ version: '0'
102
+ type: :development
103
+ prerelease: false
104
+ version_requirements: !ruby/object:Gem::Requirement
105
+ none: false
106
+ requirements:
107
+ - - ! '>='
108
+ - !ruby/object:Gem::Version
109
+ version: '0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: rb-fsevent
112
+ requirement: !ruby/object:Gem::Requirement
113
+ none: false
114
+ requirements:
115
+ - - ! '>='
116
+ - !ruby/object:Gem::Version
117
+ version: '0'
118
+ type: :development
119
+ prerelease: false
120
+ version_requirements: !ruby/object:Gem::Requirement
121
+ none: false
122
+ requirements:
123
+ - - ! '>='
124
+ - !ruby/object:Gem::Version
125
+ version: '0'
126
+ - !ruby/object:Gem::Dependency
127
+ name: pry
128
+ requirement: !ruby/object:Gem::Requirement
129
+ none: false
130
+ requirements:
131
+ - - ! '>='
132
+ - !ruby/object:Gem::Version
133
+ version: '0'
134
+ type: :development
135
+ prerelease: false
136
+ version_requirements: !ruby/object:Gem::Requirement
137
+ none: false
138
+ requirements:
139
+ - - ! '>='
140
+ - !ruby/object:Gem::Version
141
+ version: '0'
142
+ - !ruby/object:Gem::Dependency
143
+ name: rake
144
+ requirement: !ruby/object:Gem::Requirement
145
+ none: false
146
+ requirements:
147
+ - - ! '>='
148
+ - !ruby/object:Gem::Version
149
+ version: '0'
150
+ type: :development
151
+ prerelease: false
152
+ version_requirements: !ruby/object:Gem::Requirement
153
+ none: false
154
+ requirements:
155
+ - - ! '>='
156
+ - !ruby/object:Gem::Version
157
+ version: '0'
158
+ description: A useful Ruby library for the Midwire development team
159
+ email:
160
+ - chris@midwiretech.com
161
+ executables: []
162
+ extensions: []
163
+ extra_rdoc_files: []
164
+ files:
165
+ - .gitignore
166
+ - .rspec
167
+ - CHANGELOG
168
+ - Gemfile
169
+ - Guardfile
170
+ - LICENSE
171
+ - README.md
172
+ - Rakefile
173
+ - lib/midwire_common.rb
174
+ - lib/midwire_common/all.rb
175
+ - lib/midwire_common/array.rb
176
+ - lib/midwire_common/enumerable.rb
177
+ - lib/midwire_common/file.rb
178
+ - lib/midwire_common/file/stat.rb
179
+ - lib/midwire_common/fixnum.rb
180
+ - lib/midwire_common/float.rb
181
+ - lib/midwire_common/hash.rb
182
+ - lib/midwire_common/rake_helper.rb
183
+ - lib/midwire_common/rake_tasks.rb
184
+ - lib/midwire_common/string.rb
185
+ - lib/midwire_common/time.rb
186
+ - lib/midwire_common/version.rb
187
+ - lib/tasks/version.rake
188
+ - midwire_common.gemspec
189
+ - spec/lib/midwire_common/array_spec.rb
190
+ - spec/lib/midwire_common/enumerable_spec.rb
191
+ - spec/lib/midwire_common/file/stat_spec.rb
192
+ - spec/lib/midwire_common/fixnum_spec.rb
193
+ - spec/lib/midwire_common/float_spec.rb
194
+ - spec/lib/midwire_common/hash_spec.rb
195
+ - spec/lib/midwire_common/string_spec.rb
196
+ - spec/lib/midwire_common/time_spec.rb
197
+ - spec/spec_helper.rb
198
+ homepage: http://git-2.americadirect.net/prosup
199
+ licenses: []
200
+ post_install_message:
201
+ rdoc_options: []
202
+ require_paths:
203
+ - lib
204
+ required_ruby_version: !ruby/object:Gem::Requirement
205
+ none: false
206
+ requirements:
207
+ - - ! '>='
208
+ - !ruby/object:Gem::Version
209
+ version: '0'
210
+ required_rubygems_version: !ruby/object:Gem::Requirement
211
+ none: false
212
+ requirements:
213
+ - - ! '>='
214
+ - !ruby/object:Gem::Version
215
+ version: '0'
216
+ requirements: []
217
+ rubyforge_project:
218
+ rubygems_version: 1.8.24
219
+ signing_key:
220
+ specification_version: 3
221
+ summary: Midiwre Ruby Library
222
+ test_files:
223
+ - spec/lib/midwire_common/array_spec.rb
224
+ - spec/lib/midwire_common/enumerable_spec.rb
225
+ - spec/lib/midwire_common/file/stat_spec.rb
226
+ - spec/lib/midwire_common/fixnum_spec.rb
227
+ - spec/lib/midwire_common/float_spec.rb
228
+ - spec/lib/midwire_common/hash_spec.rb
229
+ - spec/lib/midwire_common/string_spec.rb
230
+ - spec/lib/midwire_common/time_spec.rb
231
+ - spec/spec_helper.rb