p2ruby 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|