sip 0.0.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/Gemfile +2 -0
- data/LICENSE +674 -0
- data/README.rdoc +32 -0
- data/Rakefile +21 -0
- data/bin/sip +83 -0
- data/bin/transpart +114 -0
- data/docs/classes/Sip.html +169 -0
- data/docs/classes/Sip/CmdOpts.html +179 -0
- data/docs/classes/Sip/Config.html +362 -0
- data/docs/classes/Sip/DBBase.html +368 -0
- data/docs/classes/Sip/HadoopException.html +111 -0
- data/docs/classes/Sip/Hive.html +295 -0
- data/docs/classes/Sip/HiveQueryException.html +111 -0
- data/docs/classes/Sip/ImportScriptExecutionError.html +111 -0
- data/docs/classes/Sip/MySQLSipper.html +273 -0
- data/docs/classes/Sip/NoSuchColumn.html +111 -0
- data/docs/classes/Sip/NoSuchTable.html +111 -0
- data/docs/classes/Sip/PastFailureException.html +111 -0
- data/docs/classes/Sip/Sipper.html +454 -0
- data/docs/classes/Sip/UnsupportedDatabaseType.html +111 -0
- data/docs/classes/Sip/Utils.html +269 -0
- data/docs/classes/Struct.html +146 -0
- data/docs/created.rid +1 -0
- data/docs/files/README_rdoc.html +174 -0
- data/docs/files/lib/sip/cmdopts_rb.html +101 -0
- data/docs/files/lib/sip/config_rb.html +108 -0
- data/docs/files/lib/sip/databases/dbbase_rb.html +108 -0
- data/docs/files/lib/sip/databases/mysql_rb.html +108 -0
- data/docs/files/lib/sip/exceptions_rb.html +101 -0
- data/docs/files/lib/sip/extensions_rb.html +101 -0
- data/docs/files/lib/sip/hive_rb.html +101 -0
- data/docs/files/lib/sip/sipper_rb.html +101 -0
- data/docs/files/lib/sip/utils_rb.html +110 -0
- data/docs/files/lib/sip/version_rb.html +101 -0
- data/docs/files/lib/sip_rb.html +117 -0
- data/docs/fr_class_index.html +42 -0
- data/docs/fr_file_index.html +38 -0
- data/docs/fr_method_index.html +72 -0
- data/docs/index.html +24 -0
- data/docs/rdoc-style.css +208 -0
- data/lib/sip.rb +10 -0
- data/lib/sip/cmdopts.rb +20 -0
- data/lib/sip/config.rb +80 -0
- data/lib/sip/databases/dbbase.rb +56 -0
- data/lib/sip/databases/mysql.rb +52 -0
- data/lib/sip/exceptions.rb +9 -0
- data/lib/sip/extensions.rb +5 -0
- data/lib/sip/hive.rb +62 -0
- data/lib/sip/sipper.rb +118 -0
- data/lib/sip/templates/export.sh +73 -0
- data/lib/sip/utils.rb +58 -0
- data/lib/sip/version.rb +3 -0
- data/test/database_interaction_test.rb +7 -0
- data/test/hive_test.rb +28 -0
- data/test/sipper_test.rb +25 -0
- metadata +125 -0
data/README.rdoc
ADDED
@@ -0,0 +1,32 @@
|
|
1
|
+
= SIP: SQL to Hive Importer
|
2
|
+
SIP is a ETL[http://en.wikipedia.org/wiki/Extract,_transform,_load] tool for extracting SQL databases and importing them into Hive[http://hive.apache.org]. It was created because the ability to transform columns and partition data was an absolute requirement, and no other tool provided that functionality.
|
3
|
+
|
4
|
+
Unique features include:
|
5
|
+
* The ability to transform columns (using Ruby code)
|
6
|
+
* A single, simple, human readable configuration file
|
7
|
+
* The ability to parition tables in Hive based on the value of any (possibly transformed) columns
|
8
|
+
|
9
|
+
Bug reports and pull requests welcome on github[https://github.com/livingsocial/sip].
|
10
|
+
|
11
|
+
== Requirements
|
12
|
+
* A working Hadoop installation
|
13
|
+
* Hive on the namenode
|
14
|
+
* Ruby >= 1.8.6 on all datanodes
|
15
|
+
* SQL Ruby libs
|
16
|
+
|
17
|
+
== Installation, Configuration, and Use
|
18
|
+
gem install sip
|
19
|
+
|
20
|
+
note: if no primary key (default: id), must set incremental_index to blank
|
21
|
+
|
22
|
+
|
23
|
+
== How it Works
|
24
|
+
Per table to be imported, SIP determines the queries necessary to perform an export and the creates scripts (one per datanode) that are then run individually in parallel. Each script:
|
25
|
+
1. Copies a transformation / partition (transpart) script to the datanode
|
26
|
+
1. Performs the SQL extraction, piping output through the transpart script
|
27
|
+
1. Uploads all partitions to HDFS
|
28
|
+
|
29
|
+
Then, all of the partitions are imported from HDFS into Hive. Easy squeezy.
|
30
|
+
|
31
|
+
|
32
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'bundler'
|
3
|
+
require 'rake/testtask'
|
4
|
+
require 'rake/rdoctask'
|
5
|
+
|
6
|
+
Bundler::GemHelper.install_tasks
|
7
|
+
|
8
|
+
desc "Run all unit tests"
|
9
|
+
Rake::TestTask.new("test") { |t|
|
10
|
+
t.libs << "lib"
|
11
|
+
t.test_files = FileList['test/*_test.rb']
|
12
|
+
t.verbose = true
|
13
|
+
}
|
14
|
+
|
15
|
+
desc "Create documentation"
|
16
|
+
Rake::RDocTask.new("docs") { |rdoc|
|
17
|
+
rdoc.title = "Sip - SQL to Hive importer"
|
18
|
+
rdoc.rdoc_dir = 'docs'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
}
|
data/bin/sip
ADDED
@@ -0,0 +1,83 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'rubygems'
|
4
|
+
require 'sip'
|
5
|
+
|
6
|
+
starttime = Time.now
|
7
|
+
|
8
|
+
options = { :db => nil, :table => nil, :config => 'sip.yml', :debug => false, :tfile => nil, :overwrite => false }
|
9
|
+
parser = OptionParser.new { |opts|
|
10
|
+
opts.banner = "Usage: sip [options]"
|
11
|
+
|
12
|
+
opts.on('-h', '--help', 'displays usage information') {
|
13
|
+
puts opts
|
14
|
+
exit
|
15
|
+
}
|
16
|
+
|
17
|
+
opts.on('-o', '--overwrite', 'force full overwrite') {
|
18
|
+
options[:overwrite] = true
|
19
|
+
}
|
20
|
+
|
21
|
+
opts.on('-d', '--debug', 'Print debugging information') { |d|
|
22
|
+
options[:debug] = true
|
23
|
+
}
|
24
|
+
|
25
|
+
opts.on('-D <database>', '--database <database>', 'only import from given database') { |db|
|
26
|
+
options[:db] = db
|
27
|
+
}
|
28
|
+
|
29
|
+
opts.on('-c <config file>', '--config <config file>', 'use specified config') { |c|
|
30
|
+
options[:config] = c
|
31
|
+
}
|
32
|
+
|
33
|
+
opts.on('-t <table>', '--table <table>', 'only import from given table (must specify -D as well)') { |t|
|
34
|
+
options[:table] = t
|
35
|
+
}
|
36
|
+
|
37
|
+
opts.on('-f <file>', '--transpart-file <file>', 'translation/partition file location (default: looks for file in path)') { |t|
|
38
|
+
options[:tfile] = t
|
39
|
+
}
|
40
|
+
}.parse!
|
41
|
+
|
42
|
+
|
43
|
+
if ENV['HADOOP_HOME'].nil? or ENV['HIVE_HOME'].nil?
|
44
|
+
puts "You must first set both the HADOOP_HOME and HIVE_HOME environment variables."
|
45
|
+
exit 1
|
46
|
+
end
|
47
|
+
|
48
|
+
debug = Proc.new { |t| puts "#{Sip::Utils::hostname} #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{t}" if options[:debug] }
|
49
|
+
|
50
|
+
debug.call "Using config file #{options[:config]}"
|
51
|
+
config = Sip::Config.load_file options[:config]
|
52
|
+
config.set_temp options, [:debug, :overwrite]
|
53
|
+
|
54
|
+
config['tfile'] = Sip::Utils::tfile_path(options[:tfile] || config['tfile'])
|
55
|
+
config['hdfs_tmpdir'] ||= "/tmp/sip"
|
56
|
+
|
57
|
+
if config['tfile'].nil?
|
58
|
+
puts "Could not find transforation / partition (transpart) script. Please use -f option to specify a location."
|
59
|
+
exit 1
|
60
|
+
end
|
61
|
+
debug.call "Using transformation / partitioning script '#{config['tfile']}'"
|
62
|
+
|
63
|
+
sipper = Sip::Sipper.new config
|
64
|
+
config['databases'].each { |dbname, dbconfig|
|
65
|
+
next if not options[:db].nil? and options[:db] != dbname
|
66
|
+
dbconfig['tables'].each { |tablename, tableconfig|
|
67
|
+
next if not options[:db].nil? and not options[:table].nil? and options[:table] != tablename
|
68
|
+
debug.call "creating script for table #{tablename} in database #{dbname}"
|
69
|
+
script_count = sipper.create_scripts dbconfig, tableconfig
|
70
|
+
if script_count > 0
|
71
|
+
debug.call "Executing #{script_count} scripts..."
|
72
|
+
sipper.run_scripts
|
73
|
+
debug.call "Running hive import..."
|
74
|
+
sipper.run_hive_import tableconfig
|
75
|
+
end
|
76
|
+
}
|
77
|
+
}
|
78
|
+
|
79
|
+
# Save new version of config
|
80
|
+
debug.call "Writing new version of config file to #{options[:config]}"
|
81
|
+
sipper.config.save_file options[:config]
|
82
|
+
|
83
|
+
debug.call "Finished running import in #{Time.now - starttime} seconds"
|
data/bin/transpart
ADDED
@@ -0,0 +1,114 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
require 'optparse'
|
3
|
+
require 'socket'
|
4
|
+
require 'fileutils'
|
5
|
+
require 'tmpdir'
|
6
|
+
require 'date'
|
7
|
+
require 'socket'
|
8
|
+
|
9
|
+
class Transformer
|
10
|
+
def self.add_one(value)
|
11
|
+
value.to_i + 1
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.datetime_to_date(value)
|
15
|
+
value.split(' ').first
|
16
|
+
end
|
17
|
+
|
18
|
+
# this takes forever to run
|
19
|
+
def self.to_date(value)
|
20
|
+
Date.parse(value).to_s
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
############################################################################
|
26
|
+
# -c one,two,three,created_at -p created_at -t one:transone,two:transformtwo -o /tmp/sip -s 1234 -d
|
27
|
+
options = { :cols => [], :partition_by => nil, :trans => {}, :debug => false, :outdir => nil, :onehundreth => nil, :hive_tablename => nil }
|
28
|
+
parser = OptionParser.new { |opts|
|
29
|
+
opts.banner = "Usage: transpart [options]"
|
30
|
+
|
31
|
+
opts.on('-c <colum list>', '--columns <column list>', 'list of columns in order') { |c|
|
32
|
+
options[:cols] = c.split(",")
|
33
|
+
}
|
34
|
+
|
35
|
+
opts.on('-p <partition column>', '--partition-by <partition column>', 'partition by given column') { |c|
|
36
|
+
options[:partition_by] = c
|
37
|
+
}
|
38
|
+
|
39
|
+
opts.on('-t <transformations>', '--transformations <transformations>', 'comma separated col:transmethod list') { |t|
|
40
|
+
t.split(',').each { |trans|
|
41
|
+
key, value = trans.split(':')
|
42
|
+
options[:trans][key] = value
|
43
|
+
}
|
44
|
+
}
|
45
|
+
|
46
|
+
opts.on('-H <hive tablename>', '--hive-table <hive tablename>', 'name of the hive table to import into') { |h|
|
47
|
+
options[:hive_tablename] = h
|
48
|
+
}
|
49
|
+
|
50
|
+
opts.on('-o <output dir>', '--output-dir <output dir>', 'Directory to output partitions to') { |o|
|
51
|
+
options[:outdir] = o
|
52
|
+
}
|
53
|
+
|
54
|
+
opts.on('-s <num rows>', '--size <num rows>', 'Number of rows - used to estimate % done') { |s|
|
55
|
+
options[:onehundreth] = s.to_i / 100
|
56
|
+
}
|
57
|
+
|
58
|
+
opts.on('-d', '--debug', 'print debugging info') {
|
59
|
+
options[:debug] = true
|
60
|
+
}
|
61
|
+
}.parse!
|
62
|
+
|
63
|
+
|
64
|
+
if options[:cols].length == 0 and (options[:trans].length > 0 or not options[:partition_by].nil?)
|
65
|
+
puts "You must specify column names with the -c option if you also give transformation or parition options"
|
66
|
+
exit 1
|
67
|
+
elsif not options[:partition_by].nil? and not options[:cols].include? options[:partition_by]
|
68
|
+
puts "Can not partition by a non-existant column"
|
69
|
+
exit 1
|
70
|
+
end
|
71
|
+
|
72
|
+
partfiles = {}
|
73
|
+
outputdir = options[:outdir] || Dir.mktmpdir('sip_')
|
74
|
+
hostname = Socket.gethostname
|
75
|
+
tmpfname = Proc.new { |partition|
|
76
|
+
odir = partition.nil? ? outputdir : File.join(outputdir, partition)
|
77
|
+
FileUtils.mkdir_p odir
|
78
|
+
File.join(odir, "#{hostname}_#{Time.now.to_f}_#{ (1...10).map { ('a'...'z').to_a.sort_by{rand}.first }.join }.part")
|
79
|
+
}
|
80
|
+
debug = Proc.new { |t| puts "#{hostname} #{Time.now.strftime("%Y-%m-%d %H:%M:%S")}: #{t}" if options[:debug] }
|
81
|
+
|
82
|
+
|
83
|
+
lineno = 0
|
84
|
+
pdone = 0
|
85
|
+
$stdin.each_line do |line|
|
86
|
+
lineno += 1
|
87
|
+
vals = line.chomp("\n").split("\t")
|
88
|
+
partval = nil
|
89
|
+
transvalues = []
|
90
|
+
vals.each_with_index { |value, index|
|
91
|
+
if options[:trans].has_key? options[:cols][index]
|
92
|
+
value = Transformer.send(options[:trans][options[:cols][index]], value)
|
93
|
+
end
|
94
|
+
if options[:cols][index] == options[:partition_by]
|
95
|
+
partval = value
|
96
|
+
else
|
97
|
+
transvalues << value
|
98
|
+
end
|
99
|
+
}
|
100
|
+
|
101
|
+
if not partfiles.has_key? partval
|
102
|
+
partfiles[partval] = File.open(tmpfname.call(partval), 'w')
|
103
|
+
end
|
104
|
+
partfiles[partval].write(transvalues.join("\001") + "\n")
|
105
|
+
|
106
|
+
if not options[:onehundreth].nil? and lineno == options[:onehundreth]
|
107
|
+
lineno = 0
|
108
|
+
pdone += 1
|
109
|
+
debug.call "#{pdone}% finished exporting table"
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
debug.call "finished exporting table"
|
114
|
+
partfiles.values.each { |f| f.close }
|
@@ -0,0 +1,169 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Module: Sip</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href=".././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Module</strong></td>
|
53
|
+
<td class="class-name-in-header">Sip</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../files/lib/sip/cmdopts_rb.html">
|
59
|
+
lib/sip/cmdopts.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
<a href="../files/lib/sip/config_rb.html">
|
63
|
+
lib/sip/config.rb
|
64
|
+
</a>
|
65
|
+
<br />
|
66
|
+
<a href="../files/lib/sip/databases/dbbase_rb.html">
|
67
|
+
lib/sip/databases/dbbase.rb
|
68
|
+
</a>
|
69
|
+
<br />
|
70
|
+
<a href="../files/lib/sip/databases/mysql_rb.html">
|
71
|
+
lib/sip/databases/mysql.rb
|
72
|
+
</a>
|
73
|
+
<br />
|
74
|
+
<a href="../files/lib/sip/exceptions_rb.html">
|
75
|
+
lib/sip/exceptions.rb
|
76
|
+
</a>
|
77
|
+
<br />
|
78
|
+
<a href="../files/lib/sip/hive_rb.html">
|
79
|
+
lib/sip/hive.rb
|
80
|
+
</a>
|
81
|
+
<br />
|
82
|
+
<a href="../files/lib/sip/sipper_rb.html">
|
83
|
+
lib/sip/sipper.rb
|
84
|
+
</a>
|
85
|
+
<br />
|
86
|
+
<a href="../files/lib/sip/utils_rb.html">
|
87
|
+
lib/sip/utils.rb
|
88
|
+
</a>
|
89
|
+
<br />
|
90
|
+
<a href="../files/lib/sip/version_rb.html">
|
91
|
+
lib/sip/version.rb
|
92
|
+
</a>
|
93
|
+
<br />
|
94
|
+
</td>
|
95
|
+
</tr>
|
96
|
+
|
97
|
+
</table>
|
98
|
+
</div>
|
99
|
+
<!-- banner header -->
|
100
|
+
|
101
|
+
<div id="bodyContent">
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
<div id="contextContent">
|
106
|
+
|
107
|
+
|
108
|
+
|
109
|
+
</div>
|
110
|
+
|
111
|
+
|
112
|
+
</div>
|
113
|
+
|
114
|
+
|
115
|
+
<!-- if includes -->
|
116
|
+
|
117
|
+
<div id="section">
|
118
|
+
|
119
|
+
<div id="class-list">
|
120
|
+
<h3 class="section-bar">Classes and Modules</h3>
|
121
|
+
|
122
|
+
Module <a href="Sip/Hive.html" class="link">Sip::Hive</a><br />
|
123
|
+
Module <a href="Sip/Utils.html" class="link">Sip::Utils</a><br />
|
124
|
+
Class <a href="Sip/CmdOpts.html" class="link">Sip::CmdOpts</a><br />
|
125
|
+
Class <a href="Sip/Config.html" class="link">Sip::Config</a><br />
|
126
|
+
Class <a href="Sip/DBBase.html" class="link">Sip::DBBase</a><br />
|
127
|
+
Class <a href="Sip/HadoopException.html" class="link">Sip::HadoopException</a><br />
|
128
|
+
Class <a href="Sip/HiveQueryException.html" class="link">Sip::HiveQueryException</a><br />
|
129
|
+
Class <a href="Sip/ImportScriptExecutionError.html" class="link">Sip::ImportScriptExecutionError</a><br />
|
130
|
+
Class <a href="Sip/MySQLSipper.html" class="link">Sip::MySQLSipper</a><br />
|
131
|
+
Class <a href="Sip/NoSuchColumn.html" class="link">Sip::NoSuchColumn</a><br />
|
132
|
+
Class <a href="Sip/NoSuchTable.html" class="link">Sip::NoSuchTable</a><br />
|
133
|
+
Class <a href="Sip/PastFailureException.html" class="link">Sip::PastFailureException</a><br />
|
134
|
+
Class <a href="Sip/Sipper.html" class="link">Sip::Sipper</a><br />
|
135
|
+
Class <a href="Sip/UnsupportedDatabaseType.html" class="link">Sip::UnsupportedDatabaseType</a><br />
|
136
|
+
|
137
|
+
</div>
|
138
|
+
|
139
|
+
<div id="constants-list">
|
140
|
+
<h3 class="section-bar">Constants</h3>
|
141
|
+
|
142
|
+
<div class="name-list">
|
143
|
+
<table summary="Constants">
|
144
|
+
<tr class="top-aligned-row context-row">
|
145
|
+
<td class="context-item-name">VERSION</td>
|
146
|
+
<td>=</td>
|
147
|
+
<td class="context-item-value">"0.0.1"</td>
|
148
|
+
</tr>
|
149
|
+
</table>
|
150
|
+
</div>
|
151
|
+
</div>
|
152
|
+
|
153
|
+
|
154
|
+
|
155
|
+
|
156
|
+
|
157
|
+
|
158
|
+
<!-- if method_list -->
|
159
|
+
|
160
|
+
|
161
|
+
</div>
|
162
|
+
|
163
|
+
|
164
|
+
<div id="validator-badges">
|
165
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
166
|
+
</div>
|
167
|
+
|
168
|
+
</body>
|
169
|
+
</html>
|
@@ -0,0 +1,179 @@
|
|
1
|
+
<?xml version="1.0" encoding="iso-8859-1"?>
|
2
|
+
<!DOCTYPE html
|
3
|
+
PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
|
4
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
|
5
|
+
|
6
|
+
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
|
7
|
+
<head>
|
8
|
+
<title>Class: Sip::CmdOpts</title>
|
9
|
+
<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1" />
|
10
|
+
<meta http-equiv="Content-Script-Type" content="text/javascript" />
|
11
|
+
<link rel="stylesheet" href="../.././rdoc-style.css" type="text/css" media="screen" />
|
12
|
+
<script type="text/javascript">
|
13
|
+
// <![CDATA[
|
14
|
+
|
15
|
+
function popupCode( url ) {
|
16
|
+
window.open(url, "Code", "resizable=yes,scrollbars=yes,toolbar=no,status=no,height=150,width=400")
|
17
|
+
}
|
18
|
+
|
19
|
+
function toggleCode( id ) {
|
20
|
+
if ( document.getElementById )
|
21
|
+
elem = document.getElementById( id );
|
22
|
+
else if ( document.all )
|
23
|
+
elem = eval( "document.all." + id );
|
24
|
+
else
|
25
|
+
return false;
|
26
|
+
|
27
|
+
elemStyle = elem.style;
|
28
|
+
|
29
|
+
if ( elemStyle.display != "block" ) {
|
30
|
+
elemStyle.display = "block"
|
31
|
+
} else {
|
32
|
+
elemStyle.display = "none"
|
33
|
+
}
|
34
|
+
|
35
|
+
return true;
|
36
|
+
}
|
37
|
+
|
38
|
+
// Make codeblocks hidden by default
|
39
|
+
document.writeln( "<style type=\"text/css\">div.method-source-code { display: none }</style>" )
|
40
|
+
|
41
|
+
// ]]>
|
42
|
+
</script>
|
43
|
+
|
44
|
+
</head>
|
45
|
+
<body>
|
46
|
+
|
47
|
+
|
48
|
+
|
49
|
+
<div id="classHeader">
|
50
|
+
<table class="header-table">
|
51
|
+
<tr class="top-aligned-row">
|
52
|
+
<td><strong>Class</strong></td>
|
53
|
+
<td class="class-name-in-header">Sip::CmdOpts</td>
|
54
|
+
</tr>
|
55
|
+
<tr class="top-aligned-row">
|
56
|
+
<td><strong>In:</strong></td>
|
57
|
+
<td>
|
58
|
+
<a href="../../files/lib/sip/cmdopts_rb.html">
|
59
|
+
lib/sip/cmdopts.rb
|
60
|
+
</a>
|
61
|
+
<br />
|
62
|
+
</td>
|
63
|
+
</tr>
|
64
|
+
|
65
|
+
<tr class="top-aligned-row">
|
66
|
+
<td><strong>Parent:</strong></td>
|
67
|
+
<td>
|
68
|
+
Hash
|
69
|
+
</td>
|
70
|
+
</tr>
|
71
|
+
</table>
|
72
|
+
</div>
|
73
|
+
<!-- banner header -->
|
74
|
+
|
75
|
+
<div id="bodyContent">
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
<div id="contextContent">
|
80
|
+
|
81
|
+
|
82
|
+
|
83
|
+
</div>
|
84
|
+
|
85
|
+
<div id="method-list">
|
86
|
+
<h3 class="section-bar">Methods</h3>
|
87
|
+
|
88
|
+
<div class="name-list">
|
89
|
+
<a href="#M000040">set</a>
|
90
|
+
<a href="#M000041">to_s</a>
|
91
|
+
</div>
|
92
|
+
</div>
|
93
|
+
|
94
|
+
</div>
|
95
|
+
|
96
|
+
|
97
|
+
<!-- if includes -->
|
98
|
+
|
99
|
+
<div id="section">
|
100
|
+
|
101
|
+
|
102
|
+
|
103
|
+
|
104
|
+
|
105
|
+
|
106
|
+
|
107
|
+
|
108
|
+
<!-- if method_list -->
|
109
|
+
<div id="methods">
|
110
|
+
<h3 class="section-bar">Public Instance methods</h3>
|
111
|
+
|
112
|
+
<div id="method-M000040" class="method-detail">
|
113
|
+
<a name="M000040"></a>
|
114
|
+
|
115
|
+
<div class="method-heading">
|
116
|
+
<a href="#M000040" class="method-signature">
|
117
|
+
<span class="method-name">set</span><span class="method-args">(*k)</span>
|
118
|
+
</a>
|
119
|
+
</div>
|
120
|
+
|
121
|
+
<div class="method-description">
|
122
|
+
<p><a class="source-toggle" href="#"
|
123
|
+
onclick="toggleCode('M000040-source');return false;">[Source]</a></p>
|
124
|
+
<div class="method-source-code" id="M000040-source">
|
125
|
+
<pre>
|
126
|
+
<span class="ruby-comment cmt"># File lib/sip/cmdopts.rb, line 3</span>
|
127
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">set</span>(<span class="ruby-operator">*</span><span class="ruby-identifier">k</span>)
|
128
|
+
<span class="ruby-identifier">k</span>.<span class="ruby-identifier">each</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">key</span><span class="ruby-operator">|</span>
|
129
|
+
<span class="ruby-keyword kw">self</span>[<span class="ruby-identifier">key</span>] = <span class="ruby-keyword kw">nil</span>
|
130
|
+
}
|
131
|
+
<span class="ruby-keyword kw">end</span>
|
132
|
+
</pre>
|
133
|
+
</div>
|
134
|
+
</div>
|
135
|
+
</div>
|
136
|
+
|
137
|
+
<div id="method-M000041" class="method-detail">
|
138
|
+
<a name="M000041"></a>
|
139
|
+
|
140
|
+
<div class="method-heading">
|
141
|
+
<a href="#M000041" class="method-signature">
|
142
|
+
<span class="method-name">to_s</span><span class="method-args">(prefix=nil, suffix=nil)</span>
|
143
|
+
</a>
|
144
|
+
</div>
|
145
|
+
|
146
|
+
<div class="method-description">
|
147
|
+
<p><a class="source-toggle" href="#"
|
148
|
+
onclick="toggleCode('M000041-source');return false;">[Source]</a></p>
|
149
|
+
<div class="method-source-code" id="M000041-source">
|
150
|
+
<pre>
|
151
|
+
<span class="ruby-comment cmt"># File lib/sip/cmdopts.rb, line 9</span>
|
152
|
+
<span class="ruby-keyword kw">def</span> <span class="ruby-identifier">to_s</span>(<span class="ruby-identifier">prefix</span>=<span class="ruby-keyword kw">nil</span>, <span class="ruby-identifier">suffix</span>=<span class="ruby-keyword kw">nil</span>)
|
153
|
+
<span class="ruby-identifier">opts</span> = <span class="ruby-identifier">map</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">k</span>,<span class="ruby-identifier">v</span><span class="ruby-operator">|</span>
|
154
|
+
<span class="ruby-keyword kw">if</span> <span class="ruby-identifier">v</span>.<span class="ruby-identifier">nil?</span>
|
155
|
+
(<span class="ruby-identifier">k</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">></span> <span class="ruby-value">1</span>) <span class="ruby-operator">?</span> <span class="ruby-node">"--#{k}"</span> <span class="ruby-operator">:</span> <span class="ruby-node">"-#{k}"</span>
|
156
|
+
<span class="ruby-keyword kw">else</span>
|
157
|
+
(<span class="ruby-identifier">k</span>.<span class="ruby-identifier">length</span> <span class="ruby-operator">></span> <span class="ruby-value">1</span>) <span class="ruby-operator">?</span> <span class="ruby-node">"--#{k}=#{v}"</span> <span class="ruby-operator">:</span> <span class="ruby-node">"-#{k} #{v}"</span>
|
158
|
+
<span class="ruby-keyword kw">end</span>
|
159
|
+
}.<span class="ruby-identifier">join</span>(<span class="ruby-value str">" "</span>)
|
160
|
+
[(<span class="ruby-identifier">prefix</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-value">? </span><span class="ruby-value str">""</span> <span class="ruby-operator">:</span> <span class="ruby-identifier">prefix</span>), <span class="ruby-identifier">opts</span>, (<span class="ruby-identifier">suffix</span>.<span class="ruby-identifier">nil?</span> <span class="ruby-value">? </span><span class="ruby-value str">""</span> <span class="ruby-operator">:</span> <span class="ruby-identifier">suffix</span>)].<span class="ruby-identifier">select</span> { <span class="ruby-operator">|</span><span class="ruby-identifier">v</span><span class="ruby-operator">|</span> <span class="ruby-identifier">v</span> <span class="ruby-operator">!=</span> <span class="ruby-value str">""</span> }.<span class="ruby-identifier">join</span>(<span class="ruby-value str">" "</span>)
|
161
|
+
<span class="ruby-keyword kw">end</span>
|
162
|
+
</pre>
|
163
|
+
</div>
|
164
|
+
</div>
|
165
|
+
</div>
|
166
|
+
|
167
|
+
|
168
|
+
</div>
|
169
|
+
|
170
|
+
|
171
|
+
</div>
|
172
|
+
|
173
|
+
|
174
|
+
<div id="validator-badges">
|
175
|
+
<p><small><a href="http://validator.w3.org/check/referer">[Validate]</a></small></p>
|
176
|
+
</div>
|
177
|
+
|
178
|
+
</body>
|
179
|
+
</html>
|