p2ruby 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 +27 -0
- data/HISTORY +7 -0
- data/LICENSE +20 -0
- data/README.rdoc +24 -0
- data/Rakefile +42 -0
- data/VERSION +1 -0
- data/bin/olegen.rb +368 -0
- data/features/p2ruby.feature +9 -0
- data/features/step_definitions/p2ruby_steps.rb +0 -0
- data/features/support/env.rb +10 -0
- data/features/support/world.rb +12 -0
- data/lib/extension.rb +19 -0
- data/lib/ole20110223-013209.rb +1677 -0
- data/lib/p2ruby/application.rb +111 -0
- data/lib/p2ruby/base.rb +59 -0
- data/lib/p2ruby/connection.rb +250 -0
- data/lib/p2ruby/data_stream.rb +215 -0
- data/lib/p2ruby/library.rb +24 -0
- data/lib/p2ruby/message.rb +150 -0
- data/lib/p2ruby/message_factory.rb +70 -0
- data/lib/p2ruby/record.rb +104 -0
- data/lib/p2ruby/router.rb +45 -0
- data/lib/p2ruby/table_set.rb +166 -0
- data/lib/p2ruby.rb +156 -0
- data/lib/version.rb +8 -0
- data/lib/win32ole-pr.rb +5540 -0
- data/spec/encoding_spec.rb +15 -0
- data/spec/p2ruby/application_spec.rb +35 -0
- data/spec/p2ruby/connection_spec.rb +293 -0
- data/spec/p2ruby/data_stream_spec.rb +218 -0
- data/spec/p2ruby/library_spec.rb +42 -0
- data/spec/p2ruby/message_factory_spec.rb +69 -0
- data/spec/p2ruby/message_spec.rb +159 -0
- data/spec/p2ruby/record_spec.rb +85 -0
- data/spec/p2ruby/router_spec.rb +54 -0
- data/spec/p2ruby/table_set_spec.rb +132 -0
- data/spec/p2ruby_spec.rb +46 -0
- data/spec/spec_helper.rb +78 -0
- data/tasks/common.rake +18 -0
- data/tasks/doc.rake +14 -0
- data/tasks/gem.rake +40 -0
- data/tasks/git.rake +34 -0
- data/tasks/spec.rake +16 -0
- data/tasks/version.rake +71 -0
- metadata +149 -0
data/.gitignore
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
## MAC OS
|
2
|
+
.DS_Store
|
3
|
+
|
4
|
+
## TEXTMATE
|
5
|
+
*.tmproj
|
6
|
+
tmtags
|
7
|
+
|
8
|
+
## EMACS
|
9
|
+
*~
|
10
|
+
\#*
|
11
|
+
.\#*
|
12
|
+
|
13
|
+
## VIM
|
14
|
+
*.swp
|
15
|
+
|
16
|
+
## PROJECT::GENERAL
|
17
|
+
coverage
|
18
|
+
config
|
19
|
+
rdoc
|
20
|
+
pkg
|
21
|
+
log
|
22
|
+
tmp
|
23
|
+
.idea
|
24
|
+
.bundle
|
25
|
+
|
26
|
+
## PROJECT::SPECIFIC
|
27
|
+
*.db
|
data/HISTORY
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2010 Arvicco
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
= p2ruby
|
2
|
+
by:: Arvicco
|
3
|
+
url:: http://github.com/arvicco/p2ruby
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Ruby bindings and wrapper classes for P2ClientGate.
|
8
|
+
|
9
|
+
== FEATURES/PROBLEMS:
|
10
|
+
|
11
|
+
All implemented COM classes wrapped except for CP2DataBuffer. Most event interfaces work,
|
12
|
+
except for IP2AsyncEvent* since they are not implemented anywhere.
|
13
|
+
|
14
|
+
== REQUIREMENTS:
|
15
|
+
|
16
|
+
* Plaza 2 gateway account
|
17
|
+
* P2ClientGate installed and connected to Plaza 2 gateway
|
18
|
+
|
19
|
+
== INSTALL:
|
20
|
+
|
21
|
+
$ sudo gem install p2ruby
|
22
|
+
|
23
|
+
== LICENSE:
|
24
|
+
Copyright (c) 2010 Arvicco. See LICENSE for details.
|
data/Rakefile
ADDED
@@ -0,0 +1,42 @@
|
|
1
|
+
begin
|
2
|
+
require 'rake'
|
3
|
+
rescue LoadError
|
4
|
+
require 'rubygems'
|
5
|
+
gem 'rake', '~> 0.8.3.1'
|
6
|
+
require 'rake'
|
7
|
+
end
|
8
|
+
|
9
|
+
require 'pathname'
|
10
|
+
|
11
|
+
BASE_PATH = Pathname.new(__FILE__).dirname
|
12
|
+
LIB_PATH = BASE_PATH + 'lib'
|
13
|
+
PKG_PATH = BASE_PATH + 'pkg'
|
14
|
+
DOC_PATH = BASE_PATH + 'rdoc'
|
15
|
+
P2_PATH = BASE_PATH + 'p2'
|
16
|
+
|
17
|
+
$LOAD_PATH.unshift LIB_PATH.to_s
|
18
|
+
require 'version'
|
19
|
+
|
20
|
+
NAME = 'p2ruby'
|
21
|
+
CLASS_NAME = P2
|
22
|
+
|
23
|
+
# Load rakefile tasks
|
24
|
+
Dir['tasks/*.rake'].sort.each { |file| load file }
|
25
|
+
|
26
|
+
# Project-specific tasks
|
27
|
+
|
28
|
+
namespace :ole do
|
29
|
+
desc "Register P2ClientGate.dll COM/OLE objects with Windows"
|
30
|
+
task :register do
|
31
|
+
cd P2_PATH
|
32
|
+
system 'regsvr32 P2ClientGate.dll'
|
33
|
+
cd BASE_PATH
|
34
|
+
end
|
35
|
+
|
36
|
+
desc "Generate OLE class stubs from typelib"
|
37
|
+
task :generate do
|
38
|
+
puts "Generate P2 OLE classes"
|
39
|
+
filename = Time.now.strftime "ole%Y%m%d-%H%M%S"
|
40
|
+
system "ruby bin/olegen.rb > lib/#{filename}.rb"
|
41
|
+
end
|
42
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/bin/olegen.rb
ADDED
@@ -0,0 +1,368 @@
|
|
1
|
+
# View of /branches/ruby_1_9_2/ext/win32ole/sample/olegen.rb
|
2
|
+
#
|
3
|
+
# Parent Directory Parent Directory | Revision Log Revision Log
|
4
|
+
# Revision 27657 - (download) (annotate)
|
5
|
+
# Fri May 7 09:08:53 2010 UTC (9 months, 1 week ago) by yugui
|
6
|
+
# File size: 8428 byte(s)
|
7
|
+
#
|
8
|
+
# branches ruby_1_9_2 from r27656 on the trunk for release process of Ruby 1.9.2.
|
9
|
+
#
|
10
|
+
#-----------------------------
|
11
|
+
# olegen.rb
|
12
|
+
#-----------------------------
|
13
|
+
|
14
|
+
require 'win32ole'
|
15
|
+
|
16
|
+
class String
|
17
|
+
# returns snake_case representation of string
|
18
|
+
def snake_case
|
19
|
+
gsub(/([a-z])([A-Z0-9])/, '\1_\2').downcase
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
class WIN32COMGen
|
24
|
+
def initialize(typelib)
|
25
|
+
@typelib = typelib
|
26
|
+
@reciever = ""
|
27
|
+
end
|
28
|
+
|
29
|
+
attr_reader :typelib
|
30
|
+
|
31
|
+
def ole_classes(typelib)
|
32
|
+
begin
|
33
|
+
@ole = WIN32OLE.new(typelib)
|
34
|
+
[@ole.ole_obj_help]
|
35
|
+
rescue
|
36
|
+
WIN32OLE_TYPE.ole_classes(typelib)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_args(method)
|
41
|
+
args = []
|
42
|
+
if method.size_opt_params >= 0
|
43
|
+
size_required_params = method.size_params - method.size_opt_params
|
44
|
+
else
|
45
|
+
size_required_params = method.size_params - 1
|
46
|
+
end
|
47
|
+
size_required_params.times do |i|
|
48
|
+
if method.params[i]
|
49
|
+
param = method.params[i].name.snake_case || "arg#{i}"
|
50
|
+
param += "=nil" if method.params[i].optional?
|
51
|
+
args.push param
|
52
|
+
end
|
53
|
+
end
|
54
|
+
if method.size_opt_params >= 0
|
55
|
+
method.size_opt_params.times do |i|
|
56
|
+
if method.params[i]
|
57
|
+
param = method.params[i].name.snake_case || "arg#{i}" + "=nil"
|
58
|
+
else
|
59
|
+
param = "arg#{i + size_required_params}=nil"
|
60
|
+
end
|
61
|
+
args.push param
|
62
|
+
end
|
63
|
+
else
|
64
|
+
args.push "*args"
|
65
|
+
end
|
66
|
+
args.push "val" if method.invoke_kind == 'PROPERTYPUT'
|
67
|
+
args.join(", ")
|
68
|
+
end
|
69
|
+
|
70
|
+
def generate_argtype(typedetails)
|
71
|
+
ts = ''
|
72
|
+
typedetails.each do |t|
|
73
|
+
case t
|
74
|
+
when 'CARRAY', 'VOID', 'UINT', 'RESULT', 'DECIMAL' #, 'I8', 'UI8'
|
75
|
+
ts << "\"??? NOT SUPPORTED TYPE:`#{t}'\""
|
76
|
+
when 'USERDEFINED', 'Unknown Type 9'
|
77
|
+
ts << 'VT_DISPATCH'
|
78
|
+
break;
|
79
|
+
when 'SAFEARRAY'
|
80
|
+
ts << 'VT_ARRAY|'
|
81
|
+
when 'PTR'
|
82
|
+
ts << 'VT_BYREF|'
|
83
|
+
when 'INT'
|
84
|
+
ts << 'VT_I4'
|
85
|
+
else
|
86
|
+
if String === t
|
87
|
+
ts << 'VT_' + t
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
if ts.empty?
|
92
|
+
ts = 'VT_VARIANT'
|
93
|
+
elsif ts[-1] == ?|
|
94
|
+
ts += 'VT_VARIANT'
|
95
|
+
end
|
96
|
+
ts
|
97
|
+
end
|
98
|
+
|
99
|
+
def generate_argtypes(method, proptypes)
|
100
|
+
types = method.params.collect { |param|
|
101
|
+
generate_argtype(param.ole_type_detail)
|
102
|
+
}.join(", ")
|
103
|
+
if proptypes
|
104
|
+
types += ", " if types.size > 0
|
105
|
+
types += generate_argtype(proptypes)
|
106
|
+
end
|
107
|
+
types
|
108
|
+
end
|
109
|
+
|
110
|
+
def generate_method_body(method, disptype, types=nil)
|
111
|
+
# Check if we need to keep WIN32OLE::ARGV to access OUT args...
|
112
|
+
args = generate_method_args_help(method)
|
113
|
+
(args && args['OUT'] ? " keep_lastargs " : " ") +
|
114
|
+
"#{@reciever}#{disptype}(#{method.dispid}, " +
|
115
|
+
"[#{generate_args(method).gsub('=nil', '')}], " +
|
116
|
+
"[#{generate_argtypes(method, types)}])"
|
117
|
+
end
|
118
|
+
|
119
|
+
def generate_method_help(method, type = nil)
|
120
|
+
str = " # "
|
121
|
+
typed_name = "#{type || method.return_type} #{method.name}"
|
122
|
+
if method.helpstring && method.helpstring != ""
|
123
|
+
if method.helpstring[method.name]
|
124
|
+
str += method.helpstring.sub(method.name, typed_name)
|
125
|
+
else
|
126
|
+
str += typed_name + ': ' + method.helpstring
|
127
|
+
end
|
128
|
+
else
|
129
|
+
str += typed_name
|
130
|
+
end
|
131
|
+
str += " - EVENT in #{method.event_interface}" if method.event?
|
132
|
+
args_help = generate_method_args_help(method)
|
133
|
+
str += "\n#{args_help}" if args_help
|
134
|
+
str
|
135
|
+
end
|
136
|
+
|
137
|
+
def generate_method_args_help(method)
|
138
|
+
args = []
|
139
|
+
method.params.each_with_index { |param, i|
|
140
|
+
h = " # #{param.ole_type} #{param.name.snake_case}"
|
141
|
+
inout = []
|
142
|
+
inout.push "IN" if param.input?
|
143
|
+
inout.push "OUT" if param.output?
|
144
|
+
h += " [#{inout.join('/')}]"
|
145
|
+
h += " ( = #{param.default})" if param.default
|
146
|
+
args.push h
|
147
|
+
}
|
148
|
+
if args.size > 0
|
149
|
+
args.join("\n")
|
150
|
+
else
|
151
|
+
nil
|
152
|
+
end
|
153
|
+
end
|
154
|
+
|
155
|
+
def generate_method(method, disptype, io = STDOUT, types = nil)
|
156
|
+
io.puts "\n"
|
157
|
+
io.puts generate_method_help(method)
|
158
|
+
if method.invoke_kind == 'PROPERTYPUT'
|
159
|
+
io.print " def #{method.name}=("
|
160
|
+
else
|
161
|
+
io.print " def #{method.name}("
|
162
|
+
end
|
163
|
+
io.print generate_args(method)
|
164
|
+
io.puts ")"
|
165
|
+
io.puts generate_method_body(method, disptype, types)
|
166
|
+
io.puts " end"
|
167
|
+
end
|
168
|
+
|
169
|
+
def generate_propputref_methods(klass, io = STDOUT)
|
170
|
+
klass.ole_methods.select { |method|
|
171
|
+
method.invoke_kind == 'PROPERTYPUTREF' && method.visible?
|
172
|
+
}.each do |method|
|
173
|
+
generate_method(method, io)
|
174
|
+
end
|
175
|
+
end
|
176
|
+
|
177
|
+
def generate_properties_with_args(klass, io = STDOUT)
|
178
|
+
klass.ole_methods.select { |method|
|
179
|
+
method.invoke_kind == 'PROPERTYGET' &&
|
180
|
+
method.visible? &&
|
181
|
+
method.size_params > 0
|
182
|
+
}.each do |method|
|
183
|
+
types = method.return_type_detail
|
184
|
+
io.puts "\n"
|
185
|
+
io.puts generate_method_help(method, types[0])
|
186
|
+
io.puts " def #{method.name}"
|
187
|
+
if klass.ole_type == "Class"
|
188
|
+
io.print " @_#{method.name} ||= OLEProperty.new(@ole, #{method.dispid}, ["
|
189
|
+
else
|
190
|
+
io.print " @_#{method.name} ||= OLEProperty.new(self, #{method.dispid}, ["
|
191
|
+
end
|
192
|
+
io.print generate_argtypes(method, nil)
|
193
|
+
io.print "], ["
|
194
|
+
io.print generate_argtypes(method, types)
|
195
|
+
io.puts "])"
|
196
|
+
io.puts " end"
|
197
|
+
end
|
198
|
+
end
|
199
|
+
|
200
|
+
def generate_propput_methods(klass, io = STDOUT)
|
201
|
+
klass.ole_methods.select { |method|
|
202
|
+
method.invoke_kind == 'PROPERTYPUT' && method.visible? &&
|
203
|
+
method.size_params == 1
|
204
|
+
}.each do |method|
|
205
|
+
ms = klass.ole_methods.select { |m|
|
206
|
+
m.invoke_kind == 'PROPERTYGET' &&
|
207
|
+
m.dispid == method.dispid
|
208
|
+
}
|
209
|
+
types = []
|
210
|
+
if ms.size == 1
|
211
|
+
types = ms[0].return_type_detail
|
212
|
+
end
|
213
|
+
generate_method(method, '_setproperty', io, types)
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
def generate_propget_methods(klass, io = STDOUT)
|
218
|
+
klass.ole_methods.select { |method|
|
219
|
+
method.invoke_kind == 'PROPERTYGET' && method.visible? &&
|
220
|
+
method.size_params == 0
|
221
|
+
}.each do |method|
|
222
|
+
generate_method(method, '_getproperty', io)
|
223
|
+
end
|
224
|
+
end
|
225
|
+
|
226
|
+
def generate_func_methods(klass, io = STDOUT)
|
227
|
+
klass.ole_methods.select { |method|
|
228
|
+
method.invoke_kind == "FUNC" && method.visible?
|
229
|
+
}.each do |method|
|
230
|
+
generate_method(method, '_invoke', io)
|
231
|
+
end
|
232
|
+
end
|
233
|
+
|
234
|
+
def generate_methods(klass, io = STDOUT)
|
235
|
+
generate_propget_methods(klass, io)
|
236
|
+
generate_propput_methods(klass, io)
|
237
|
+
generate_properties_with_args(klass, io)
|
238
|
+
generate_func_methods(klass, io)
|
239
|
+
# generate_propputref_methods(klass, io)
|
240
|
+
end
|
241
|
+
|
242
|
+
def generate_constants(klass, io = STDOUT)
|
243
|
+
klass.variables.select { |v|
|
244
|
+
v.visible? && v.variable_kind == 'CONSTANT'
|
245
|
+
}.each do |v|
|
246
|
+
io.print " "
|
247
|
+
io.print v.name.sub(/^./) { $&.upcase }
|
248
|
+
io.print " = "
|
249
|
+
io.puts v.value
|
250
|
+
end
|
251
|
+
end
|
252
|
+
|
253
|
+
def class_name(klass)
|
254
|
+
klass_name = klass.name
|
255
|
+
if klass.ole_type == "Class" &&
|
256
|
+
klass.guid &&
|
257
|
+
klass.progid
|
258
|
+
klass_name = klass.progid.gsub(/\./, '_')
|
259
|
+
end
|
260
|
+
if /^[A-Z]/ !~ klass_name || Module.constants.include?(klass_name)
|
261
|
+
klass_name = 'OLE' + klass_name
|
262
|
+
end
|
263
|
+
klass_name
|
264
|
+
end
|
265
|
+
|
266
|
+
def define_initialize(klass)
|
267
|
+
<<STR
|
268
|
+
|
269
|
+
def initialize opts = {}
|
270
|
+
super PROGID, opts
|
271
|
+
end
|
272
|
+
STR
|
273
|
+
end
|
274
|
+
|
275
|
+
def define_include
|
276
|
+
" include WIN32OLE::VARIANT"
|
277
|
+
end
|
278
|
+
|
279
|
+
def define_instance_variables
|
280
|
+
" attr_reader :lastargs"
|
281
|
+
end
|
282
|
+
|
283
|
+
def define_common_methods
|
284
|
+
<<STR
|
285
|
+
|
286
|
+
def method_missing(cmd, *args)
|
287
|
+
@ole.method_missing(cmd, *args)
|
288
|
+
end
|
289
|
+
|
290
|
+
def keep_lastargs(return_value)
|
291
|
+
@lastargs = WIN32OLE::ARGV
|
292
|
+
return_value
|
293
|
+
end
|
294
|
+
|
295
|
+
def clsid
|
296
|
+
CLSID
|
297
|
+
end
|
298
|
+
|
299
|
+
def progid
|
300
|
+
PROGID
|
301
|
+
end
|
302
|
+
STR
|
303
|
+
end
|
304
|
+
|
305
|
+
def define_class(klass, io = STDOUT)
|
306
|
+
io.puts "class #{klass.name} < Base # #{class_name(klass)}"
|
307
|
+
io.puts " CLSID = '#{klass.guid}'"
|
308
|
+
io.puts " PROGID = '#{klass.progid}'"
|
309
|
+
io.puts define_include
|
310
|
+
io.puts define_instance_variables
|
311
|
+
io.puts " attr_reader :ole"
|
312
|
+
io.puts define_initialize(klass)
|
313
|
+
io.puts define_common_methods
|
314
|
+
end
|
315
|
+
|
316
|
+
def define_module(klass, io = STDOUT)
|
317
|
+
io.puts "module #{class_name(klass)}"
|
318
|
+
io.puts define_include
|
319
|
+
io.puts define_instance_variables
|
320
|
+
end
|
321
|
+
|
322
|
+
def generate_class(klass, io = STDOUT)
|
323
|
+
io.puts "\n# #{klass.helpstring}"
|
324
|
+
if klass.ole_type == "Class" &&
|
325
|
+
klass.guid &&
|
326
|
+
klass.progid
|
327
|
+
@reciever = "@ole."
|
328
|
+
define_class(klass, io)
|
329
|
+
else
|
330
|
+
@reciever = ""
|
331
|
+
define_module(klass, io)
|
332
|
+
end
|
333
|
+
generate_constants(klass, io)
|
334
|
+
generate_methods(klass, io)
|
335
|
+
io.puts "end"
|
336
|
+
end
|
337
|
+
|
338
|
+
def generate(io = STDOUT)
|
339
|
+
io.puts "require 'win32ole'"
|
340
|
+
io.puts "require 'win32ole/property'"
|
341
|
+
|
342
|
+
ole_classes(typelib).select { |klass|
|
343
|
+
klass.visible? &&
|
344
|
+
(klass.ole_type == "Class" ||
|
345
|
+
klass.ole_type == "Interface" ||
|
346
|
+
klass.ole_type == "Dispatch" ||
|
347
|
+
klass.ole_type == "Enum")
|
348
|
+
}.each do |klass|
|
349
|
+
generate_class(klass, io)
|
350
|
+
end
|
351
|
+
begin
|
352
|
+
@ole.quit if @ole
|
353
|
+
rescue
|
354
|
+
end
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
if __FILE__ == $0
|
359
|
+
# if ARGV.size == 0
|
360
|
+
# $stderr.puts "usage: #{$0} Type Library [...]"
|
361
|
+
# exit 1
|
362
|
+
# end
|
363
|
+
# ARGV.each do |typelib|
|
364
|
+
typelib = WIN32OLE_TYPELIB.typelibs.find { |t| t.name =~ /P2ClientGate / }
|
365
|
+
comgen = WIN32COMGen.new(typelib.guid)
|
366
|
+
comgen.generate
|
367
|
+
# end
|
368
|
+
end
|
File without changes
|
data/lib/extension.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
class String
|
2
|
+
# returns snake_case representation of string
|
3
|
+
def snake_case
|
4
|
+
gsub(/([a-z])([A-Z0-9])/, '\1_\2' ).downcase
|
5
|
+
end
|
6
|
+
|
7
|
+
# returns camel_case representation of string
|
8
|
+
def camel_case
|
9
|
+
if self.include? '_'
|
10
|
+
self.split('_').map{|e| e.capitalize}.join
|
11
|
+
else
|
12
|
+
unless self =~ (/^[A-Z]/)
|
13
|
+
self.capitalize
|
14
|
+
else
|
15
|
+
self
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|