buzztools 0.0.3 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,114 @@
1
+ module Buzztools
2
+ class Config < Hash
3
+
4
+ attr_reader :default_values
5
+
6
+ def initialize(aDefaultValues,aNewValues=nil,&aBlock)
7
+ @default_values = aDefaultValues.clone
8
+ reset()
9
+ if aNewValues
10
+ block_given? ? read(aNewValues,&aBlock) : read(aNewValues)
11
+ end
12
+ end
13
+
14
+ # aBlock allows values to be filtered based on key,default and new values
15
+ def read(aSource,&aBlock)
16
+ default_values.each do |k,v|
17
+ done = false
18
+ if block_given? && ((newv = yield(k,v,aSource && aSource[k])) != nil)
19
+ self[k] = newv
20
+ done = true
21
+ end
22
+ copy_item(aSource,k) if !done && aSource && !aSource[k].nil?
23
+ end
24
+ self
25
+ end
26
+
27
+ # reset values back to defaults
28
+ def reset
29
+ self.clear
30
+ me = self
31
+ @default_values.each {|n,v| me[n] = v.is_a?(Class) ? nil : v}
32
+ end
33
+
34
+ def set_int(aKey,aValue)
35
+ case aValue
36
+ when String then self[aKey] = aValue.to_integer(self[aKey]);
37
+ when Fixnum then self[aKey] = aValue;
38
+ when Float then self[aKey] = aValue.to_i;
39
+ end
40
+ end
41
+
42
+ def set_float(aKey,aValue)
43
+ case aValue
44
+ when String then self[aKey] = aValue.to_float(self[aKey]);
45
+ when Fixnum then self[aKey] = aValue.to_f;
46
+ when Float then self[aKey] = aValue;
47
+ end
48
+ end
49
+
50
+ def set_boolean(aKey,aValue)
51
+ case aValue
52
+ when TrueClass,FalseClass then self[aKey] = aValue;
53
+ when String then self[aKey] = (['1','yes','y','true','on'].include?(aValue.downcase))
54
+ else
55
+ set_boolean(aKey,aValue.to_s)
56
+ end
57
+ end
58
+
59
+ def set_symbol(aKey,aValue)
60
+ case aValue
61
+ when String then self[aKey] = (aValue.to_sym rescue nil);
62
+ when Symbol then self[aKey] = aValue;
63
+ end
64
+ end
65
+
66
+ def copy_item(aHash,aKey)
67
+ d = default_values[aKey]
68
+ d_class = (d.is_a?(Class) ? d : d.class)
69
+ cname = d_class.name.to_sym
70
+ case cname
71
+ when :NilClass then self[aKey] = aHash[aKey];
72
+ when :String then self[aKey] = aHash[aKey].to_s unless aHash[aKey].nil?
73
+ when :Float then set_float(aKey,aHash[aKey]);
74
+ when :Fixnum then set_int(aKey,aHash[aKey]);
75
+ when :TrueClass, :FalseClass then set_boolean(aKey,aHash[aKey]);
76
+ when :Symbol then self[aKey] = (aHash[aKey].to_sym rescue nil)
77
+ when :Proc then self[aKey] = aHash[aKey] if aHash[aKey].is_a?(Proc)
78
+ else
79
+ raise StandardError.new('unsupported type')
80
+ end
81
+ end
82
+
83
+ def copy_strings(aHash,*aKeys)
84
+ aKeys.each do |k|
85
+ self[k] = aHash[k].to_s unless aHash[k].nil?
86
+ end
87
+ end
88
+
89
+ def copy_ints(*aDb)
90
+ aHash = aDb.shift
91
+ aKeys = aDb
92
+ aKeys.each do |k|
93
+ set_int(k,aHash[k])
94
+ end
95
+ end
96
+
97
+ def copy_floats(aHash,*aKeys)
98
+ aKeys.each do |k|
99
+ set_float(k,aHash[k])
100
+ end
101
+ end
102
+
103
+ def copy_booleans(aHash,*aKeys)
104
+ aKeys.each do |k|
105
+ set_boolean(k,aHash[k])
106
+ end
107
+ end
108
+
109
+ def to_hash
110
+ {}.merge(self)
111
+ end
112
+
113
+ end
114
+ end
@@ -1,3 +1,5 @@
1
+ require 'csv'
2
+
1
3
  module ExtendArray
2
4
 
3
5
  module_function # this makes the methods accessible on the module as well as instances when the module is included into a class
@@ -41,6 +43,27 @@ module ExtendArray
41
43
  def to_nil
42
44
  self.empty? ? nil : self
43
45
  end
46
+
47
+ def to_csv
48
+ def as_hash(aItem)
49
+ aItem = aItem.attributes if aItem.respond_to?(:attributes)
50
+ return aItem if aItem.is_a?(Hash)
51
+ nil
52
+ end
53
+ item1 = as_hash(first)
54
+ raise "Must be an array of hashes" unless item1 && item1.is_a?(Hash)
55
+ fields = item1.keys.map(&:to_s).sort
56
+ if fields.delete('id')
57
+ fields.unshift('id')
58
+ end
59
+ CSV.generate do |csv|
60
+ csv << fields
61
+ self.each do |i|
62
+ next unless i = as_hash(i)
63
+ csv << i.values_at(*column_names)
64
+ end
65
+ end
66
+ end
44
67
  end
45
68
 
46
69
  Array.class_eval do
@@ -13,7 +13,7 @@ end
13
13
  Float.class_eval do
14
14
 
15
15
  def to_nil
16
- (self==0 || self.nan?) ? nil : self
16
+ (self==0 || !self.finite?) ? nil : self
17
17
  end
18
18
 
19
19
  end
@@ -24,21 +24,24 @@ module ExtendObject
24
24
  path = args
25
25
  end
26
26
  if path.is_a?(String)
27
- segments = path.split('.').map!(&:to_sym)
27
+ segments = path.split('.')
28
28
  segment = segments.shift
29
29
  elsif path.is_a?(Symbol)
30
- segments = []
31
- segment = path
30
+ path = path.to_s
31
+ segments = [path]
32
+ segment = segments.shift
32
33
  elsif path.is_a?(Array)
33
34
  segments = path
34
35
  segment = segments.shift
35
- segment = segment.to_sym if segment
36
+ #segment = segment.to_sym if segment
36
37
  end
37
38
  return self unless segment.to_nil
38
- value = if self.respond_to?(segment)
39
+ value = if self.is_a?(Array)
40
+ self[segment.to_i] rescue nil
41
+ elsif (self.respond_to?(segment.to_sym) rescue nil)
39
42
  self.send(segment)
40
43
  elsif self.respond_to?(:[])
41
- (self[segment] || self[segment.to_s]) rescue nil
44
+ (begin self[segment] rescue nil end) || (begin self[segment.to_sym] rescue nil end)
42
45
  end
43
46
  if segments.empty?
44
47
  value
@@ -215,6 +215,21 @@ String.class_eval do
215
215
  def self.from_file(aFilename)
216
216
  File.open(aFilename, "rb") { |f| f.read }
217
217
  end
218
+
219
+ # given ('abcdefg','c.*?e') returns ['ab','cde','fg'] so you can manipulate the head, match and tail seperately, and potentially rejoin
220
+ def split3(aPattern,aOccurence=0)
221
+ aString = self
222
+ matches = aString.scan_md(aPattern)
223
+ match = matches[aOccurence]
224
+ parts = (match ? [match.pre_match,match.to_s,match.post_match] : [aString,nil,''])
225
+
226
+ if !block_given? # return head,match,tail
227
+ parts
228
+ else # return string
229
+ parts[1] = yield *parts if match
230
+ parts.join
231
+ end
232
+ end
218
233
  end
219
234
 
220
235
 
@@ -81,4 +81,14 @@ Time.class_eval do
81
81
  def to_w3c
82
82
  utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")
83
83
  end
84
+
85
+ # returns an integer date stamp (milliseconds since 1970) compatible with Javascript
86
+ def to_ms
87
+ (to_f*1000).round
88
+ end
89
+
90
+ # creates a Time object from an integer date stamp (milliseconds since 1970) compatible with Javascript
91
+ def self.from_ms(aMilliseconds)
92
+ at(aMilliseconds/1000.0)
93
+ end
84
94
  end
@@ -0,0 +1,79 @@
1
+ gem 'POpen4'; require 'popen4'
2
+
3
+ module POpen4
4
+
5
+ class ExecuteError < StandardError
6
+
7
+ attr_reader :result #,:stderr,:stdout,:exitcode,:pid
8
+
9
+ def initialize(aArg)
10
+ if aArg.is_a? Hash
11
+ msg = ([aArg[:stderr],aArg[:stdout],"Error #{aArg[:exitcode].to_s}"].find {|i| i && !i.empty?})
12
+ super(msg)
13
+ @result = aArg
14
+ else
15
+ super(aArg)
16
+ end
17
+ end
18
+
19
+ def inspect
20
+ "#{self.class.to_s}: #{@result.inspect}"
21
+ end
22
+
23
+ end
24
+
25
+ def self.pump_thread(aIn,aOut)
26
+ Thread.new do
27
+ loop { aOut.puts aIn.gets }
28
+ end
29
+ end
30
+
31
+ # Usage :
32
+ # result = POpen4::shell('somebinary') do |r| # block gives opportunity to adjust result, and avoid exception raised from non-zero exit codes
33
+ # if r[:exitcode]==254 # eg. say this binary returns 254 to mean something special but not an error
34
+ # r[:stdout] = 'some correct output'
35
+ # r[:stderr] = ''
36
+ # r[:exitcode] = 0
37
+ # end
38
+ # end
39
+ #
40
+ # OR
41
+ #
42
+ # result = POpen4::shell('somebinary');
43
+ # puts result[:stdout]
44
+ #
45
+ # Giving aStdOut,aStdErr causes the command output to be connected to the given stream, and that stream to not be given in the result hash
46
+ def self.shell(aCommand,aWorkingDir=nil,aTimeout=nil,aStdOut=nil,aStdErr=nil)
47
+ raise ExecuteError.new('aWorkingDir doesnt exist') unless !aWorkingDir || File.exists?(aWorkingDir)
48
+ orig_wd = Dir.getwd
49
+ result = {:command => aCommand, :dir => (aWorkingDir || orig_wd)}
50
+ status = nil
51
+ begin
52
+ Dir.chdir(aWorkingDir) if aWorkingDir
53
+ Timeout.timeout(aTimeout,ExecuteError) do # nil aTimeout will not time out
54
+ status = POpen4::popen4(aCommand) do |stdout, stderr, stdin, pid|
55
+ thrOut = aStdOut ? Thread.new { aStdOut.puts stdout.read } : nil
56
+ thrErr = aStdErr ? Thread.new { aStdErr.puts stderr.read } : nil
57
+ thrOut.join if thrOut
58
+ thrErr.join if thrErr
59
+
60
+ result[:stdout] = stdout.read unless aStdOut
61
+ result[:stderr] = stderr.read unless aStdErr
62
+ result[:pid] = pid
63
+ end
64
+ end
65
+ ensure
66
+ Dir.chdir(orig_wd)
67
+ end
68
+ result[:exitcode] = (status && status.exitstatus) || 1
69
+ yield(result) if block_given?
70
+ raise ExecuteError.new(result) if result[:exitcode] != 0
71
+ return result
72
+ end
73
+
74
+ def self.shell_out(aCommand,aWorkingDir=nil,aTimeout=nil,&block)
75
+ block_given? ? POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR,&block) : POpen4::shell(aCommand,aWorkingDir,aTimeout,STDOUT,STDERR)
76
+ end
77
+
78
+ end
79
+
@@ -0,0 +1,123 @@
1
+ module Buzztools
2
+ module File
3
+
4
+ module_function
5
+
6
+ def sniff_seperator(aPath)
7
+ result = 0.upto(aPath.length-1) do |i|
8
+ char = aPath[i,1]
9
+ break char if char=='\\' || char=='/'
10
+ end
11
+ result = ::File::SEPARATOR if result==0
12
+ return result
13
+ end
14
+
15
+ def append_slash(aPath,aSep=nil)
16
+ aSep = sniff_seperator(aPath) unless aSep
17
+ aPath.ensure_suffix(aSep)
18
+ end
19
+
20
+ def remove_slash(aPath)
21
+ last_char = aPath[-1,1]
22
+ aPath = aPath[0..-2] if last_char=='\\' || last_char=='/'
23
+ return aPath
24
+ end
25
+
26
+ #def ensure_prefix(aString,aPrefix)
27
+ # aString.begins_with?(aPrefix) ? aString : aPrefix+aString
28
+ #end
29
+ #
30
+ #def ensure_suffix(aString,aSuffix)
31
+ # aString.ends_with?(aSuffix) ? aString : aString+aSuffix
32
+ #end
33
+
34
+ # Remove base dir from given path. Result will be relative to base dir and not have a leading or trailing slash
35
+ #'/a/b/c','/a' = 'b/c'
36
+ #'/a/b/c','/' = 'a/b/c'
37
+ #'/','/' = ''
38
+ def path_debase(aPath,aBase)
39
+ aBase = append_slash(aBase)
40
+ aPath = remove_slash(aPath) unless aPath=='/'
41
+ aPath[0,aBase.length]==aBase ? aPath[aBase.length,aPath.length-aBase.length] : aPath
42
+ end
43
+
44
+ def path_rebase(aPath,aOldBase,aNewBase)
45
+ rel_path = path_debase(aPath,aOldBase)
46
+ append_slash(aNewBase)+rel_path
47
+ end
48
+
49
+ def path_combine(aBasePath,aPath)
50
+ return aBasePath if !aPath
51
+ return aPath if !aBasePath
52
+ return path_relative?(aPath) ? ::File.join(aBasePath,aPath) : aPath
53
+ end
54
+
55
+ # make path real according to file system
56
+ def real_path(aPath)
57
+ (path = Pathname.new(::File.expand_path(aPath))) && path.realpath.to_s
58
+ end
59
+
60
+ # takes a path and combines it with a root path (which defaults to Dir.pwd) unless it is absolute
61
+ # the final result is then expanded
62
+ def canonize_path(aPath,aRootPath=nil)
63
+ path = path_combine(aRootPath,aPath)
64
+ path = real_path(path) if path
65
+ path
66
+ end
67
+
68
+ def find_upwards(aStartPath,aPath)
69
+ curr_path = ::File.expand_path(aStartPath)
70
+ while curr_path && !(test_path_exists = ::File.exists?(test_path = ::File.join(curr_path,aPath))) do
71
+ curr_path = path_parent(curr_path)
72
+ end
73
+ curr_path && test_path_exists ? test_path : nil
74
+ end
75
+
76
+ # allows special symbols in path
77
+ # currently only ... supported, which looks upward in the filesystem for the following relative path from the basepath
78
+ def expand_magic_path(aPath,aBasePath=nil)
79
+ aBasePath ||= Dir.pwd
80
+ path = aPath
81
+ if path.begins_with?('...')
82
+ rel_part = path.split3(/\.\.\.[\/\\]/)[2]
83
+ path = find_upwards(aBasePath,rel_part)
84
+ end
85
+ end
86
+
87
+ def path_parent(aPath)
88
+ return nil if is_root_path?(aPath)
89
+ append_slash(::File.dirname(remove_slash(expand_path(aPath))))
90
+ end
91
+
92
+ def simple_dir_name(aPath)
93
+ ::File.basename(remove_slash(aPath))
94
+ end
95
+
96
+ def simple_file_name(aPath)
97
+ f = ::File.basename(aPath)
98
+ dot = f.index('.')
99
+ return dot ? f[0,dot] : f
100
+ end
101
+
102
+ def path_parts(aPath)
103
+ sep = sniff_seperator(aPath)
104
+ aPath.split(sep)
105
+ end
106
+
107
+ def extension(aFile,aExtended=true)
108
+ f = ::File.basename(aFile)
109
+ dot = aExtended ? f.index('.') : f.rindex('.')
110
+ return dot ? f[dot+1..-1] : f
111
+ end
112
+
113
+ def no_extension(aFile,aExtended=true)
114
+ ext = extension(aFile,aExtended)
115
+ return aFile.chomp('.'+ext)
116
+ end
117
+
118
+ def change_ext(aFile,aExt,aExtend=false)
119
+ no_extension(aFile,false)+(aExtend ? '.'+aExt+'.'+extension(aFile,false) : '.'+aExt)
120
+ end
121
+
122
+ end
123
+ end
@@ -1,3 +1,3 @@
1
1
  module Buzztools
2
- VERSION = "0.0.3"
2
+ VERSION = "0.0.5"
3
3
  end
@@ -0,0 +1,163 @@
1
+ # Versionary is a mixin for implementing versioning of models with ActiveRecord in Rails 3.2+
2
+ # It attempts to be better than other solutions eg.
3
+ #
4
+ # * no shadow tables
5
+ # * does not abuse ActiveRecord, no magic
6
+ # * no serialization at all, so queries work with all versions
7
+ # * associations work like normal ActiveRecord. The id column identifies a single version of an instance. You can associate to an old version
8
+ # * its easy to read and write old versions
9
+ # * if you use and keep updated the ver_current column, it is extremely fast
10
+ # * this file is really all there is to it
11
+ # * supports future versions that become current when the time comes eg. future price changes
12
+ #
13
+ # This is achieved by using the id column to identify each version of each instance, unlike some solutions that use the id per instance, then have to do trickery to provide versions.
14
+ # This means associations can simply attach to any version of any instance using the id column as normal
15
+ # Instances are identified by the iid column
16
+ #
17
+ # id iid version name price
18
+ # 1 3 1 eggs 2.99
19
+ # 2 3 2 eggs 3.10
20
+ # 3 4 1 bread 3.50
21
+ #
22
+ # In the above table, eggs (iid = 3) has 2 versions and bread (iid = 4) has 1 version.
23
+ # An order can simply attach to any product/version using the id column
24
+ #
25
+ # The eggs product would be created as follows :
26
+ #
27
+ # eggs = Product.create!(name: 'eggs', price: 2.99)
28
+ # eggs2 = eggs.create_version!(price: 3.10)
29
+ #
30
+ # current_10_dollar_products = Product.live_current_versions.where(price: 10)
31
+ #
32
+ # Migration
33
+ #
34
+ #class CreateThings < ActiveRecord::Migration
35
+ # def change
36
+ # create_table :things do |t|
37
+ # t.integer :iid # instance id - versions of an instance will have different ids but the same iid
38
+ # t.integer :version
39
+ # t.integer :current_from, limit: 8 # timestamp in milliseconds since 1970
40
+ # t.boolean :ver_current, null: false, default: false # optional, for performance. true indicates this is the current version
41
+ #
42
+ # t.integer :size
43
+ # t.string :colour
44
+ # t.string :shape
45
+ # end
46
+ # add_index(:things, [:iid, :version], :unique => true)
47
+ # end
48
+ #end
49
+ #
50
+ # Model
51
+ #
52
+ #class Thing < ActiveRecord::Base
53
+ #
54
+ # include Versionary
55
+ #
56
+ #end
57
+ #
58
+ #
59
+ module Versionary
60
+
61
+ def self.included(aClass)
62
+ aClass.class_eval do
63
+
64
+ def self.next_version_id(aIid)
65
+ where(iid: aIid).maximum(:version).to_i + 1
66
+ end
67
+
68
+ after_create do
69
+ updates = {}
70
+ updates[:iid] = id if !iid
71
+ if !version
72
+ updates[:version] = self.class.next_version_id(self.iid)
73
+ end
74
+ update_attributes!(updates) unless updates.empty?
75
+ true
76
+ end
77
+
78
+ # should be able to do eg. : TaxRate.where(owner_id: 1,dealership_id: 2).latest_versions.where(state: 'WA')
79
+ scope :live_latest_versions, -> {
80
+ inner = clone.select("iid, max(version) as version").group(:iid).to_sql
81
+ ids = ActiveRecord::Base.connection.execute("select id from (#{inner}) as v inner join #{table_name} as t on t.iid = v.iid and t.version = v.version").to_a
82
+ if (adapter = ActiveRecord::Base.configurations[Rails.env]['adapter'])=='postgresql'
83
+ ids = ids.map{|i| i['id']}.join(',')
84
+ elsif adapter.begins_with? 'mysql'
85
+ ids = ids.flatten.join(',')
86
+ else
87
+ raise "Adapter #{adapter} not supported"
88
+ end
89
+
90
+ #ids = ActiveRecord::Base.connection.execute("select id from (SELECT iid, max(version) as version FROM `things` GROUP BY iid) as v inner join things as t on t.iid = v.iid and t.version = v.version").to_a.flatten.join(',')
91
+ where "id IN (#{ids})"
92
+ }
93
+
94
+ # Scopes to the current version for all iids at the given timestamp
95
+ # This and other methods beginning with "live" do not use the ver_current column
96
+ scope :live_current_versions, ->(aTimestamp) {
97
+ inner = clone.select("iid, max(version) as version").where(["current_from <= ?",aTimestamp]).group(:iid).to_sql
98
+ ids = ActiveRecord::Base.connection.execute("select id from (#{inner}) as v inner join #{table_name} as t on t.iid = v.iid and t.version = v.version").to_a
99
+ if (adapter = ActiveRecord::Base.configurations[Rails.env]['adapter'])=='postgresql'
100
+ ids = ids.map{|i| i['id']}.join(',')
101
+ elsif adapter.begins_with? 'mysql'
102
+ ids = ids.flatten.join(',')
103
+ else
104
+ raise "Adapter #{adapter} not supported"
105
+ end
106
+ if ids.to_nil
107
+ where "id IN (#{ids})"
108
+ else
109
+ where("1=0") # relation that matches nothing
110
+ end
111
+ }
112
+
113
+ # Scopes to the current version of a given iid. Can only return 0 or 1 records
114
+ # This and other methods beginning with "live" do not use the ver_current column
115
+ scope :live_current_version, ->(aIid,aTimestamp=nil) {
116
+ aTimestamp ||= KojacUtils.timestamp
117
+ where(iid: aIid).where(["current_from <= ?",aTimestamp]).order('version DESC').limit(1)
118
+ }
119
+
120
+ # Scopes to current version for all iids using the ver_current column. The ver_current must be updated regularly using update_all_ver_current.
121
+ # This method is much faster than live_current_versions
122
+ scope :current_versions, -> {
123
+ where(ver_current: true)
124
+ }
125
+
126
+ # Updates the ver_current column, which enables simpler and much faster queries on current versions eg. using current_versions instead of live_current_versions.
127
+ # Must be run periodically eg. 4am daily
128
+ def self.update_all_ver_current
129
+ self.update_all(ver_current: false)
130
+ self.live_current_versions(Time.now.to_ms).update_all(ver_current: true)
131
+ end
132
+ end
133
+ end
134
+
135
+ def copyable_attributes
136
+ result = {}
137
+ self.class.columns.each do |c|
138
+ next if ['id', 'version'].include? c.name
139
+ result[c.name.to_sym] = self.send(c.name)
140
+ end
141
+ result
142
+ end
143
+
144
+ def new_version(aValues)
145
+ raise "iid must be set before calling new_version" unless self.iid
146
+ attrs = copyable_attributes
147
+ attrs[:version] = self.class.next_version_id(self.iid)
148
+ ver = self.class.new(attrs)
149
+ ver
150
+ end
151
+
152
+ def create_version!(aValues)
153
+ raise "iid must be set before calling new_version" unless self.iid
154
+ attrs = copyable_attributes
155
+ attrs[:version] = self.class.next_version_id(self.iid)
156
+ attrs.merge!(aValues.symbolize_keys)
157
+ self.class.create!(attrs)
158
+ end
159
+
160
+ def current_version
161
+ self.class.live_current_version(self.iid,KojacUtils.timestamp).first
162
+ end
163
+ end
metadata CHANGED
@@ -1,18 +1,20 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: buzztools
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.3
4
+ version: 0.0.5
5
+ prerelease:
5
6
  platform: ruby
6
7
  authors:
7
8
  - Gary McGhee
8
9
  autorequire:
9
10
  bindir: bin
10
11
  cert_chain: []
11
- date: 2013-12-12 00:00:00.000000000 Z
12
+ date: 2014-04-09 00:00:00.000000000 Z
12
13
  dependencies:
13
14
  - !ruby/object:Gem::Dependency
14
15
  name: bundler
15
16
  requirement: !ruby/object:Gem::Requirement
17
+ none: false
16
18
  requirements:
17
19
  - - ! '>='
18
20
  - !ruby/object:Gem::Version
@@ -20,6 +22,7 @@ dependencies:
20
22
  type: :development
21
23
  prerelease: false
22
24
  version_requirements: !ruby/object:Gem::Requirement
25
+ none: false
23
26
  requirements:
24
27
  - - ! '>='
25
28
  - !ruby/object:Gem::Version
@@ -27,6 +30,7 @@ dependencies:
27
30
  - !ruby/object:Gem::Dependency
28
31
  name: rake
29
32
  requirement: !ruby/object:Gem::Requirement
33
+ none: false
30
34
  requirements:
31
35
  - - ! '>='
32
36
  - !ruby/object:Gem::Version
@@ -34,6 +38,7 @@ dependencies:
34
38
  type: :development
35
39
  prerelease: false
36
40
  version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
37
42
  requirements:
38
43
  - - ! '>='
39
44
  - !ruby/object:Gem::Version
@@ -52,6 +57,7 @@ files:
52
57
  - Rakefile
53
58
  - buzztools.gemspec
54
59
  - lib/buzztools.rb
60
+ - lib/buzztools/config.rb
55
61
  - lib/buzztools/extend_array.rb
56
62
  - lib/buzztools/extend_bignum.rb
57
63
  - lib/buzztools/extend_fixnum.rb
@@ -60,29 +66,39 @@ files:
60
66
  - lib/buzztools/extend_object.rb
61
67
  - lib/buzztools/extend_string.rb
62
68
  - lib/buzztools/extend_time.rb
69
+ - lib/buzztools/extras/shell_extras.rb
70
+ - lib/buzztools/file.rb
63
71
  - lib/buzztools/version.rb
72
+ - lib/buzztools/versionary.rb
64
73
  homepage: https://github.com/buzzware/buzztools
65
74
  licenses:
66
75
  - MIT
67
- metadata: {}
68
76
  post_install_message:
69
77
  rdoc_options: []
70
78
  require_paths:
71
79
  - lib
72
80
  required_ruby_version: !ruby/object:Gem::Requirement
81
+ none: false
73
82
  requirements:
74
83
  - - ! '>='
75
84
  - !ruby/object:Gem::Version
76
85
  version: '0'
86
+ segments:
87
+ - 0
88
+ hash: -3067569873639998217
77
89
  required_rubygems_version: !ruby/object:Gem::Requirement
90
+ none: false
78
91
  requirements:
79
92
  - - ! '>='
80
93
  - !ruby/object:Gem::Version
81
94
  version: '0'
95
+ segments:
96
+ - 0
97
+ hash: -3067569873639998217
82
98
  requirements: []
83
99
  rubyforge_project:
84
- rubygems_version: 2.1.11
100
+ rubygems_version: 1.8.23
85
101
  signing_key:
86
- specification_version: 4
102
+ specification_version: 3
87
103
  summary: reusable function library
88
104
  test_files: []
checksums.yaml DELETED
@@ -1,15 +0,0 @@
1
- ---
2
- !binary "U0hBMQ==":
3
- metadata.gz: !binary |-
4
- NTI2MDkwZmY0Mjc1NTllMzk0NzgyMGY3YzBlNTAwNDlkNWRlOTJkNA==
5
- data.tar.gz: !binary |-
6
- OTg3MWE5YTQ3ODU3NGU1YmU4YjdkNGVjYzA1NGU0M2VjZDRhMDgxNA==
7
- SHA512:
8
- metadata.gz: !binary |-
9
- MDhiZTMwNmQyYWVjNmIwZDE2NjY5OTMwZmQ5NjNmNTcxZmEyOTg0YTYxZDE3
10
- NzA4MDY3MDJiMDM0ZjkzMDYzNGVhYzhhYmM1MzlhOTlhNzQ1N2FjN2RlZjI2
11
- ODQxYTVkMzQwMDI2YTg3ZTAxZTBkYTU1YTFkNmQ4Y2MzMDY4YzM=
12
- data.tar.gz: !binary |-
13
- OGZmYjZiMDllNmVkMDlmMTY0YzQ3YTFlNmJhYTQyOGU1NDYxZTZiOGZhYTJk
14
- MDlmNDNmNjVmOTdiMzY0NjI0ZDA2ZmVmYTM1NTg2ZDM1ZDM0MTJjZTEwOTZh
15
- YTM0MjFmMjY3ODkwYjU0NjY1OTUzMTgzNDFkMjVkZGY5ZTk2MTY=