buzzware-buzzcore 0.2.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,210 @@
1
+ require 'buzzcore/xml_utils'
2
+ require 'buzzcore/extend_base_classes'
3
+
4
+ class ConfigClass < Hash
5
+
6
+ attr_reader :default_values
7
+
8
+ def initialize(aDefaultValues,aNewValues=nil,&aBlock)
9
+ @default_values = aDefaultValues.clone
10
+ reset()
11
+ if aNewValues
12
+ block_given? ? read(aNewValues,&aBlock) : read(aNewValues)
13
+ end
14
+ end
15
+
16
+ # aBlock allows values to be filtered based on key,default and new values
17
+ def read(aSource,&aBlock)
18
+ default_values.each do |k,v|
19
+ done = false
20
+ if block_given? && ((newv = yield(k,v,aSource && aSource[k])) != nil)
21
+ self[k] = newv
22
+ done = true
23
+ end
24
+ copy_item(aSource,k) if !done && aSource && !aSource[k].nil?
25
+ end
26
+ self
27
+ end
28
+
29
+ # reset values back to defaults
30
+ def reset
31
+ self.clear
32
+ me = self
33
+ @default_values.each {|n,v| me[n] = v.is_a?(Class) ? nil : v}
34
+ end
35
+
36
+ def set_int(aKey,aValue)
37
+ case aValue
38
+ when String then self[aKey] = aValue.to_integer(self[aKey]);
39
+ when Fixnum then self[aKey] = aValue;
40
+ when Float then self[aKey] = aValue.to_i;
41
+ end
42
+ end
43
+
44
+ def set_float(aKey,aValue)
45
+ case aValue
46
+ when String then self[aKey] = aValue.to_float(self[aKey]);
47
+ when Fixnum then self[aKey] = aValue.to_f;
48
+ when Float then self[aKey] = aValue;
49
+ end
50
+ end
51
+
52
+ def set_boolean(aKey,aValue)
53
+ case aValue
54
+ when TrueClass,FalseClass then self[aKey] = aValue;
55
+ when String then self[aKey] = (['1','yes','y','true','on'].include?(aValue.downcase))
56
+ else
57
+ set_boolean(aKey,aValue.to_s)
58
+ end
59
+ end
60
+
61
+ def set_symbol(aKey,aValue)
62
+ case aValue
63
+ when String then self[aKey] = (aValue.to_sym rescue nil);
64
+ when Symbol then self[aKey] = aValue;
65
+ end
66
+ end
67
+
68
+ def copy_item(aHash,aKey)
69
+ d = default_values[aKey]
70
+ d_class = (d.is_a?(Class) ? d : d.class)
71
+ cname = d_class.name.to_sym
72
+ case cname
73
+ when :NilClass then ;
74
+ when :String then self[aKey] = aHash[aKey].to_s unless aHash[aKey].nil?
75
+ when :Float then set_float(aKey,aHash[aKey]);
76
+ when :Fixnum then set_int(aKey,aHash[aKey]);
77
+ when :TrueClass, :FalseClass then set_boolean(aKey,aHash[aKey]);
78
+ when :Symbol then self[aKey] = (aHash[aKey].to_sym rescue nil)
79
+ else
80
+ raise StandardError.new('unsupported type')
81
+ end
82
+ end
83
+
84
+ def copy_strings(aHash,*aKeys)
85
+ aKeys.each do |k|
86
+ self[k] = aHash[k].to_s unless aHash[k].nil?
87
+ end
88
+ end
89
+
90
+ def copy_ints(*aDb)
91
+ aHash = aDb.shift
92
+ aKeys = aDb
93
+ aKeys.each do |k|
94
+ set_int(k,aHash[k])
95
+ end
96
+ end
97
+
98
+ def copy_floats(aHash,*aKeys)
99
+ aKeys.each do |k|
100
+ set_float(k,aHash[k])
101
+ end
102
+ end
103
+
104
+ def copy_booleans(aHash,*aKeys)
105
+ aKeys.each do |k|
106
+ set_boolean(k,aHash[k])
107
+ end
108
+ end
109
+
110
+ def to_hash
111
+ {}.merge(self)
112
+ end
113
+
114
+ end
115
+
116
+ class ConfigXmlClass < ConfigClass
117
+ attr_accessor :xmlRoot
118
+ def initialize(aDefaultValues,aConfig)
119
+ return super(aDefaultValues,aConfig) unless aConfig.is_a?(REXML::Element)
120
+ @xmlRoot = aConfig.deep_clone
121
+ super(aDefaultValues,XmlUtils.read_simple_items(@xmlRoot,'SimpleItems').symbolize_keys)
122
+ end
123
+
124
+ def self.from_file(aDefaultValues,aFile)
125
+ xml = XmlUtils.get_file_root(aFile)
126
+ return ConfigXmlClass.new(aDefaultValues,xml)
127
+ end
128
+ end
129
+
130
+ # credentials files look like :
131
+ #<?xml version="1.0" encoding="UTF-8"?>
132
+ #<Credentials>
133
+ # <SimpleItems namespace="global">
134
+ # <Item name=""></Item>
135
+ # <Item name=""></Item>
136
+ # <Item name=""></Item>
137
+ # </SimpleItems>
138
+ # <SimpleItems namespace="yore_test">
139
+ # <Item name=""></Item>
140
+ # <Item name=""></Item>
141
+ # <Item name=""></Item>
142
+ # </SimpleItems>
143
+ #</Credentials>
144
+ #
145
+ # global .credentials.xml file
146
+ # local .credentials.xml file
147
+ # cred = Credentials.new() # optionally specify filename or path or hash. if nil then use Dir.pwd
148
+ #
149
+ # def initialize(aSource)
150
+ # # load global namespace from ~/.credentials.xml
151
+ # # load global namespace from local .credentials.xml
152
+ # # load given namespace from ~/.credentials.xml
153
+ # # load given namespace from local .credentials.xml
154
+ # # merge all top to bottom
155
+ class Credentials < Hash
156
+
157
+ CRED_FILENAME = ".credentials.xml"
158
+
159
+ def find_file_upwards(aFilename,aStartPath=nil)
160
+ aStartPath ||= Dir.pwd
161
+ return nil if aFilename.nil? || aFilename.empty?
162
+ arrPath = aStartPath.split(File::SEPARATOR)
163
+ while arrPath.length > 0
164
+ path = File.join(arrPath.join(File::SEPARATOR),aFilename)
165
+ return path if File.exists?(path)
166
+ arrPath.pop
167
+ end
168
+ return nil
169
+ end
170
+
171
+ def get_all_credentials(aXmlRoot)
172
+ return nil unless aXmlRoot
173
+ result = {}
174
+ REXML::XPath.each(aXmlRoot, '/Credentials/SimpleItems') do |si|
175
+ ns = si.attributes['Namespace']
176
+ values = XmlUtils.read_simple_items(si)
177
+ result[ns.to_sym] = values.symbolize_keys if ns && values
178
+ end
179
+ return result
180
+ end
181
+
182
+ #XmlUtils.read_simple_items(@xmlRoot,'/Yore/SimpleItems')
183
+ def get_user_credentials
184
+ return get_all_credentials(XmlUtils.get_file_root(File.join(HOME_PATH,CRED_FILENAME)))
185
+ end
186
+
187
+ def get_local_credentials(aSource=nil)
188
+ aSource ||= Dir.pwd
189
+ # assume source is a directory path, but other types could be supported later
190
+ return nil unless file=find_file_upwards(CRED_FILENAME,aSource)
191
+ return get_all_credentials(XmlUtils.get_file_root(file))
192
+ end
193
+
194
+ def initialize(aNamespace=nil,aSource=nil)
195
+ #HOME_PATH can be preset by tests eg. ::Credentials.const_set('HOME_PATH',@user_dir)
196
+ Credentials.const_set("HOME_PATH", ENV['HOME']) unless Credentials.const_defined? "HOME_PATH"
197
+ arrCredentials = []
198
+ user_credentials = get_user_credentials()
199
+ local_credentials = get_local_credentials(aSource)
200
+ arrCredentials << user_credentials[:global] if user_credentials
201
+ arrCredentials << local_credentials[:global] if local_credentials
202
+ arrCredentials << user_credentials[aNamespace.to_sym] if aNamespace && user_credentials
203
+ arrCredentials << local_credentials[aNamespace.to_sym] if aNamespace && local_credentials
204
+ arrCredentials.compact!
205
+ arrCredentials.each do |c|
206
+ self.merge!(c)
207
+ end
208
+ end
209
+ end
210
+
@@ -0,0 +1,86 @@
1
+ require 'buzzcore/shell_extras'
2
+
3
+ module DatabaseUtils
4
+ def self.execute_sql_file(filename,aUser=nil,aPassword=nil)
5
+ conf = ActiveRecord::Base.configurations[RAILS_ENV]
6
+ pw = aPassword || conf['password'].to_s || ''
7
+ user = aUser || conf['username'].to_s || ''
8
+ cmd_line = "mysql -h #{conf['host']} -D #{conf['database']} #{user.empty? ? '' : '-u '+user} #{pw.empty? ? '' : '-p'+pw} <#{filename}"
9
+ if !system(cmd_line)
10
+ raise Exception, "Error executing "+cmd_line
11
+ end
12
+ end
13
+
14
+ ## http://www.cyberciti.biz/faq/how-do-i-empty-mysql-database/
15
+ #
16
+ #
17
+ ## drop all tables :
18
+ ## mysqldump -uusername -ppassword -hhost \
19
+ ##--add-drop-table --no-data database | grep ^DROP | \
20
+ ##mysql -uusername -ppassword -hhost database
21
+ #
22
+
23
+ def self.database_exists(aDbDetails,aDatabase=nil)
24
+ aDbDetails[:database] = aDatabase if aDatabase
25
+ return false if !aDbDetails[:database]
26
+ response = POpen4::shell("mysql -u #{aDbDetails[:username]} -p#{aDbDetails[:password]} -e 'use #{aDbDetails[:database]}'") do |r|
27
+ if r[:stderr] && r[:stderr].index("ERROR 1049 ")==0 # Unknown database
28
+ r[:exitcode] = 0
29
+ return false
30
+ end
31
+ end
32
+ return (response && response[:exitcode]==0)
33
+ end
34
+
35
+ def self.clear_database(aDbDetails)
36
+ response = POpen4::shell("mysqldump -u #{aDbDetails[:username]} -p#{aDbDetails[:password]} --add-drop-table --no-data #{aDbDetails[:database]} | grep ^DROP | mysql -u #{aDbDetails[:username]} -p#{aDbDetails[:password]} #{aDbDetails[:database]}")
37
+ end
38
+
39
+ def self.create_database(aDbDetails,aDatabase=nil)
40
+ aDbDetails[:database] = aDatabase if aDatabase
41
+ return false if !aDbDetails[:database]
42
+ response = POpen4::shell("mysqladmin -u #{aDbDetails[:username]} -p#{aDbDetails[:password]} create #{aDbDetails[:database]}")
43
+ end
44
+
45
+ def self.ensure_empty_database(aDbDetails,aDatabase=nil)
46
+ aDbDetails[:database] = aDatabase if aDatabase
47
+ if database_exists(aDbDetails)
48
+ clear_database(aDbDetails)
49
+ else
50
+ create_database(aDbDetails)
51
+ end
52
+ end
53
+
54
+ def self.load_database(aDbDetails,aSqlFile)
55
+ ensure_empty_database(aDbDetails)
56
+ response = POpen4::shell("mysql -u #{aDbDetails[:username]} -p#{aDbDetails[:password]} #{aDbDetails[:database]} < #{aSqlFile}")
57
+ end
58
+
59
+ def self.save_database(aDbDetails,aSqlFile)
60
+ response = POpen4::shell("mysqldump --user=#{aDbDetails[:username]} --password=#{aDbDetails[:password]} --skip-extended-insert #{aDbDetails[:database]} > #{aSqlFile}")
61
+ end
62
+
63
+ #
64
+ ## eg. rake metas:spree:data:load from=/tmp/spree_data.tgz to=mysql:fresco_server_d:root:password
65
+ #desc 'load spree data from a file'
66
+ #task :load do
67
+ # from = ENV['from']
68
+ # to=ENV['to']
69
+ # db_server,db,user,password = to.split(':')
70
+ # tmpdir = make_temp_dir('metas')
71
+ # cmd = "tar -xvzf #{from} -C #{tmpdir}"
72
+ # puts CapUtilsClass.shell(cmd)
73
+ #
74
+ # ensure_empty_database(db_server,db,user,password)
75
+ #
76
+ # puts CapUtilsClass.shell("mysql -u #{user} -p#{password} #{db} < #{File.join(tmpdir,'db/dumps/db.sql')}")
77
+ # FileUtils.mkdir_p('public/assets')
78
+ # puts CapUtilsClass.shell("cp -rf #{File.join(tmpdir,'public/assets/products')} public/assets/products")
79
+ #end
80
+
81
+
82
+
83
+
84
+ end
85
+
86
+
@@ -0,0 +1,50 @@
1
+ module Kernel
2
+ # simple (sequential) enumerated values
3
+ # usage :
4
+ #
5
+ # module Constants
6
+ # module Gradient
7
+ # enum :B, :A, :C
8
+ # end
9
+ # end
10
+ #
11
+ # then :
12
+ #
13
+ # puts Constants::Gradient::B -> 0
14
+ # puts Constants::Gradient::C -> 2
15
+ # puts Constants::Gradient::MINVALUE -> 0
16
+ # puts Constants::Gradient::MAXVALUE -> 2
17
+ # puts Constants::Gradient::NAMES -> [:B, :A, :C]
18
+ # puts Constants::Gradient[0] -> :B
19
+ # puts Constants::Gradient[1] -> :A
20
+ # puts Constants::Gradient[2] -> :C
21
+
22
+ def enum(*syms)
23
+ syms.each_index { |i|
24
+ const_set(syms[i], i)
25
+ }
26
+ const_set(:NAMES, syms || [])
27
+ const_set(:MINVALUE, syms==nil ? nil : 0)
28
+ const_set(:MAXVALUE, syms==nil ? nil : syms.length-1)
29
+ const_set(:VALUECOUNT, syms==nil ? nil : syms.length)
30
+ const_set(:ALL, syms==nil ? [] : (0..syms.length-1).to_a)
31
+ const_set(:HUMAN_NAMES, syms.map{|n| n.to_s.humanize} || [])
32
+
33
+ # this returns the enum name given the value
34
+ def self.[]( idx )
35
+ (idx.is_a? Integer) ? const_get(:NAMES)[idx] : nil
36
+ end
37
+
38
+ def self.valid?(idx)
39
+ (idx.is_a? Integer) && (idx >= 0) && (idx <= const_get(:MAXVALUE))
40
+ end
41
+
42
+ def self.parse(name,default=nil)
43
+ return default if name.nil? || name.empty?
44
+ return default if not name = name.to_sym
45
+ result = const_get(:NAMES).index(name)
46
+ return result==nil ? default : result
47
+ end
48
+ end
49
+ end
50
+
@@ -0,0 +1,320 @@
1
+ String.class_eval do
2
+ def pad_left(value)
3
+ increase = value-self.length
4
+ return self if increase==0
5
+ if increase > 0
6
+ return self + ' '*increase
7
+ else
8
+ return self[0,value]
9
+ end
10
+ end
11
+
12
+ def pad_right(value)
13
+ increase = value-self.length
14
+ return self if increase==0
15
+ if increase > 0
16
+ return ' '*increase + self
17
+ else
18
+ return self[0,value]
19
+ end
20
+ end
21
+
22
+ # Like chomp! but operates on the leading characters instead.
23
+ # The aString parameter would not normally be used.
24
+ def bite!(aValue=$/,aString=self)
25
+ if aString[0,aValue.length] == aValue
26
+ aString[0,aValue.length] = ''
27
+ return aString
28
+ else
29
+ return aString
30
+ end
31
+ end
32
+
33
+ def bite(aValue=$/)
34
+ bite!(aValue,self.clone)
35
+ end
36
+
37
+ def begins_with?(aString)
38
+ self[0,aString.length]==aString
39
+ end
40
+
41
+ def ends_with?(aString)
42
+ self[-aString.length,aString.length]==aString
43
+ end
44
+
45
+ # for future methods
46
+ # def centre_bar(aChar = '-', indent = 6)
47
+ # (' '*indent) + aChar*(@width-(indent*2)) + (' '*indent)
48
+ # end
49
+ # def replace_string(aString,aCol,aSubString)
50
+ # return aString if aSubString==nil || aSubString==''
51
+ #
52
+ # aSubString = aSubString.to_s
53
+ # start_col = aCol < 0 ? 0 : aCol
54
+ # end_col = aCol+aSubString.length-1
55
+ # end_col = @width-1 if end_col >= @width
56
+ # source_len = end_col-start_col+1
57
+ # return aString if source_len <= 0 || end_col < 0 || start_col >= @width
58
+ # aString += ' '*((end_col+1) - aString.length) if aString.length < end_col+1
59
+ # aString[start_col,source_len] = aSubString[start_col-aCol,end_col-start_col+1]
60
+ # return aString
61
+ # end
62
+
63
+ def to_integer(aDefault=nil)
64
+ t = self.strip
65
+ return aDefault if t.empty? || !t.index(/^-{0,1}[0-9]+$/)
66
+ return t.to_i
67
+ end
68
+
69
+ def is_i?
70
+ self.to_integer(false) and true
71
+ end
72
+
73
+ def to_float(aDefault=nil)
74
+ t = self.strip
75
+ return aDefault if !t =~ /(\+|-)?([0-9]+\.?[0-9]*|\.[0-9]+)([eE](\+|-)?[0-9]+)?/
76
+ return t.to_f
77
+ end
78
+
79
+ def is_f?
80
+ self.to_float(false) and true
81
+ end
82
+
83
+ end
84
+
85
+
86
+ Time.class_eval do
87
+
88
+ if !respond_to?(:change) # no activesupport loaded
89
+ def change(options)
90
+ ::Time.send(
91
+ self.utc? ? :utc : :local,
92
+ options[:year] || self.year,
93
+ options[:month] || self.month,
94
+ options[:day] || self.day,
95
+ options[:hour] || self.hour,
96
+ options[:min] || (options[:hour] ? 0 : self.min),
97
+ options[:sec] || ((options[:hour] || options[:min]) ? 0 : self.sec),
98
+ options[:usec] || ((options[:hour] || options[:min] || options[:sec]) ? 0 : self.usec)
99
+ )
100
+ end
101
+
102
+ def seconds_since_midnight
103
+ self.to_i - self.change(:hour => 0).to_i + (self.usec/1.0e+6)
104
+ end
105
+
106
+ def beginning_of_day
107
+ (self - self.seconds_since_midnight).change(:usec => 0)
108
+ end
109
+
110
+ alias :midnight :beginning_of_day
111
+ alias :at_midnight :beginning_of_day
112
+ alias :at_beginning_of_day :beginning_of_day
113
+
114
+ end
115
+
116
+ # offset of local machine from UTC, in seconds eg +9.hours
117
+ def self.local_offset
118
+ local(2000).utc_offset
119
+ end
120
+
121
+ def date
122
+ self.at_beginning_of_day
123
+ end
124
+
125
+ # index number of this day, from Time.at(0) + utc_offset
126
+ def day_number
127
+ (self.to_i+self.utc_offset) / 86400
128
+ end
129
+
130
+ # index number of this utc day
131
+ def day_number_utc
132
+ self.to_i / 86400
133
+ end
134
+
135
+ # the last microsecond of the day
136
+ def day_end
137
+ self.at_beginning_of_day + 86399.999999
138
+ end
139
+
140
+ def date_numeric
141
+ self.strftime('%Y%m%d')
142
+ end
143
+
144
+ # create a new Time from eg. "20081231"
145
+ def self.from_date_numeric(aString)
146
+ return nil unless aString
147
+ local(aString[0,4].to_i,aString[4,2].to_i,aString[6,2].to_i)
148
+ end
149
+
150
+ def time_numeric
151
+ self.strftime('%H%M%S')
152
+ end
153
+
154
+ def datetime_numeric
155
+ self.strftime('%Y%m%d-%H%M%S')
156
+ end
157
+
158
+ def to_sql
159
+ self.strftime('%Y-%m-%d %H:%M:%S')
160
+ end
161
+
162
+ def to_w3c
163
+ utc.strftime("%Y-%m-%dT%H:%M:%S+00:00")
164
+ end
165
+ end
166
+
167
+ module HashUtils
168
+ def filter_include!(aKeys,aHash=nil)
169
+ aHash ||= self
170
+
171
+ if aKeys.is_a? Regexp
172
+ return aHash.delete_if {|k,v| not k =~ aKeys }
173
+ else
174
+ aKeys = [aKeys] unless aKeys.is_a? Array
175
+ return aHash.clear if aKeys.empty?
176
+ return aHash.delete_if {|key, value| !((aKeys.include?(key)) || (key.is_a?(Symbol) and aKeys.include?(key.to_s)) || (key.is_a?(String) and aKeys.include?(key.to_sym)))}
177
+ return aHash # last resort
178
+ end
179
+ end
180
+
181
+ def filter_include(aKeys,aHash=nil)
182
+ aHash ||= self
183
+ filter_include!(aKeys,aHash.clone)
184
+ end
185
+
186
+ def filter_exclude!(aKeys,aHash=nil)
187
+ aHash ||= self
188
+
189
+ if aKeys.is_a? Regexp
190
+ return aHash.delete_if {|k,v| k =~ aKeys }
191
+ else
192
+ aKeys = [aKeys] unless aKeys.is_a? Array
193
+ return aHash if aKeys.empty?
194
+ return aHash.delete_if {|key, value| ((aKeys.include?(key)) || (key.is_a?(Symbol) and aKeys.include?(key.to_s)) || (key.is_a?(String) and aKeys.include?(key.to_sym)))}
195
+ end
196
+ end
197
+
198
+ def filter_exclude(aKeys,aHash=nil)
199
+ aHash ||= self
200
+ filter_exclude!(aKeys,aHash.clone)
201
+ end
202
+
203
+ def has_values_for?(aKeys,aHash=nil)
204
+ aHash ||= self
205
+ # check all keys exist in aHash and their values are not nil
206
+ aKeys.all? { |k,v| aHash[k] }
207
+ end
208
+
209
+ # give a block to execute without the given key in this hash
210
+ # It will be replaced after the block (guaranteed by ensure)
211
+ # eg.
212
+ # hash.without_key(:blah) do |aHash|
213
+ # puts aHash.inspect
214
+ # end
215
+ def without_key(aKey)
216
+ temp = nil
217
+ h = self
218
+ begin
219
+ if h.include?(aKey)
220
+ temp = [aKey,h.delete(aKey)]
221
+ end
222
+ result = yield(h)
223
+ ensure
224
+ h[temp[0]] = temp[1] if temp
225
+ end
226
+ return result
227
+ end
228
+
229
+ def symbolize_keys
230
+ result = {}
231
+ self.each { |k,v| k.is_a?(String) ? result[k.to_sym] = v : result[k] = v }
232
+ return result
233
+ end
234
+
235
+ end
236
+
237
+ Hash.class_eval do
238
+ include HashUtils
239
+ end
240
+
241
+ if defined? HashWithIndifferentAccess
242
+ HashWithIndifferentAccess.class_eval do
243
+ include HashUtils
244
+ end
245
+ end
246
+
247
+ module ArrayUtils
248
+ def filter_include!(aValues,aArray=nil)
249
+ aArray ||= self
250
+ if aValues.is_a? Array
251
+ return aArray if aValues.empty?
252
+ return aArray.delete_if {|v| not aValues.include? v }
253
+ elsif aValues.is_a? Regexp
254
+ return aArray.delete_if {|v| not v =~ aValues }
255
+ else
256
+ return filter_include!([aValues],aArray)
257
+ end
258
+ end
259
+
260
+ def filter_include(aValues,aArray=nil)
261
+ aArray ||= self
262
+ filter_include!(aValues,aArray.clone)
263
+ end
264
+
265
+ def filter_exclude!(aValues,aArray=nil)
266
+ aArray ||= self
267
+ if aValues.is_a? Array
268
+ return aArray if aValues.empty?
269
+ return aArray.delete_if {|v| aValues.include? v }
270
+ elsif aValues.is_a? Regexp
271
+ return aArray.delete_if {|v| v =~ aValues }
272
+ else
273
+ return filter_exclude!([aValues],aArray)
274
+ end
275
+ end
276
+
277
+ def filter_exclude(aValues,aArray=nil)
278
+ aArray ||= self
279
+ filter_exclude!(aValues,aArray.clone)
280
+ end
281
+ end
282
+
283
+ Array.class_eval do
284
+ include ArrayUtils
285
+
286
+ # fixes a memory leak in shift in Ruby 1.8 - should be fixed in 1.9
287
+ # see http://blade.nagaokaut.ac.jp/cgi-bin/scat.rb/ruby/ruby-talk/216055
288
+ def shift()
289
+ delete_at(0)
290
+ end
291
+
292
+ end
293
+
294
+ Kernel.class_eval do
295
+ def is_windows?
296
+ RUBY_PLATFORM =~ /(win|w)32$/ ? true : false
297
+ end
298
+ end
299
+
300
+ if defined? ActiveRecord
301
+ ActiveRecord::Base.class_eval do
302
+
303
+ def self.find_any_id(aId)
304
+ with_exclusive_scope { find(:first, {:conditions => {:id => aId}}) }
305
+ end
306
+
307
+ def self.find_any_all(aOptions={})
308
+ with_exclusive_scope { find(:all, aOptions) }
309
+ end
310
+
311
+ def self.find_ids(aIds)
312
+ find(:all, {:conditions=> ["id in (?)",aIds.join(',')]})
313
+ end
314
+
315
+ def self.find_any_ids(aIds)
316
+ with_exclusive_scope { find(:all, {:conditions=> ["id in (?)",aIds.join(',')]}) }
317
+ end
318
+
319
+ end
320
+ end