google_drive 1.0.6 → 2.0.0.pre1
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.
- checksums.yaml +4 -4
- data/README.rdoc +3 -7
- data/doc_src/google_drive/acl.rb +13 -17
- data/lib/google_drive.rb +130 -160
- data/lib/google_drive/acl.rb +77 -93
- data/lib/google_drive/acl_entry.rb +149 -105
- data/lib/google_drive/api_client_fetcher.rb +22 -41
- data/lib/google_drive/authentication_error.rb +4 -8
- data/lib/google_drive/collection.rb +127 -149
- data/lib/google_drive/config.rb +23 -25
- data/lib/google_drive/error.rb +3 -3
- data/lib/google_drive/file.rb +215 -273
- data/lib/google_drive/list.rb +108 -113
- data/lib/google_drive/list_row.rb +65 -70
- data/lib/google_drive/response_code_error.rb +11 -16
- data/lib/google_drive/session.rb +412 -444
- data/lib/google_drive/spreadsheet.rb +62 -67
- data/lib/google_drive/util.rb +200 -160
- data/lib/google_drive/worksheet.rb +453 -469
- metadata +60 -22
@@ -1,77 +1,74 @@
|
|
1
1
|
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
2
|
# The license of this source is "New BSD Licence"
|
3
3
|
|
4
|
-
require
|
5
|
-
|
6
|
-
require "google_drive/util"
|
7
|
-
require "google_drive/error"
|
8
|
-
require "google_drive/worksheet"
|
9
|
-
require "google_drive/acl"
|
10
|
-
require "google_drive/file"
|
4
|
+
require 'time'
|
11
5
|
|
6
|
+
require 'google_drive/util'
|
7
|
+
require 'google_drive/error'
|
8
|
+
require 'google_drive/worksheet'
|
9
|
+
require 'google_drive/acl'
|
10
|
+
require 'google_drive/file'
|
12
11
|
|
13
12
|
module GoogleDrive
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
13
|
+
# A spreadsheet.
|
14
|
+
#
|
15
|
+
# Use methods in GoogleDrive::Session to get GoogleDrive::Spreadsheet object.
|
16
|
+
class Spreadsheet < GoogleDrive::File
|
17
|
+
include(Util)
|
19
18
|
|
20
|
-
|
21
|
-
|
22
|
-
|
19
|
+
SUPPORTED_EXPORT_FORMAT = Set.new(%w(xlsx csv pdf))
|
20
|
+
|
21
|
+
# Key of the spreadsheet.
|
22
|
+
def key
|
23
|
+
id
|
24
|
+
end
|
23
25
|
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
# URL of worksheet-based feed of the spreadsheet.
|
30
|
-
def worksheets_feed_url
|
31
|
-
return "https://spreadsheets.google.com/feeds/worksheets/%s/private/full" %
|
32
|
-
self.id
|
33
|
-
end
|
26
|
+
# URL of worksheet-based feed of the spreadsheet.
|
27
|
+
def worksheets_feed_url
|
28
|
+
'https://spreadsheets.google.com/feeds/worksheets/%s/private/full' %
|
29
|
+
id
|
30
|
+
end
|
34
31
|
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
32
|
+
# URL of feed used in the deprecated document list feed API.
|
33
|
+
def document_feed_url
|
34
|
+
'https://docs.google.com/feeds/documents/private/full/' + CGI.escape(resource_id)
|
35
|
+
end
|
39
36
|
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
# Returns worksheets of the spreadsheet as array of GoogleDrive::Worksheet.
|
46
|
-
def worksheets
|
47
|
-
doc = @session.request(:get, self.worksheets_feed_url)
|
48
|
-
if doc.root.name != "feed"
|
49
|
-
raise(GoogleDrive::Error,
|
50
|
-
"%s doesn't look like a worksheets feed URL because its root is not <feed>." %
|
51
|
-
self.worksheets_feed_url)
|
52
|
-
end
|
53
|
-
return doc.css("entry").map(){ |e| Worksheet.new(@session, self, e) }.freeze
|
54
|
-
end
|
55
|
-
|
56
|
-
# Returns a GoogleDrive::Worksheet with the given title in the spreadsheet.
|
57
|
-
#
|
58
|
-
# Returns nil if not found. Returns the first one when multiple worksheets with the
|
59
|
-
# title are found.
|
60
|
-
def worksheet_by_title(title)
|
61
|
-
return self.worksheets.find(){ |ws| ws.title == title }
|
62
|
-
end
|
37
|
+
# Spreadsheet feed URL of the spreadsheet.
|
38
|
+
def spreadsheet_feed_url
|
39
|
+
'https://spreadsheets.google.com/feeds/spreadsheets/private/full/' + id
|
40
|
+
end
|
63
41
|
|
64
|
-
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
42
|
+
# Returns worksheets of the spreadsheet as array of GoogleDrive::Worksheet.
|
43
|
+
def worksheets
|
44
|
+
doc = @session.request(:get, worksheets_feed_url)
|
45
|
+
if doc.root.name != 'feed'
|
46
|
+
fail(GoogleDrive::Error,
|
47
|
+
"%s doesn't look like a worksheets feed URL because its root is not <feed>." %
|
48
|
+
worksheets_feed_url)
|
49
|
+
end
|
50
|
+
doc.css('entry').map { |e| Worksheet.new(@session, self, e) }.freeze
|
51
|
+
end
|
71
52
|
|
72
|
-
|
73
|
-
|
74
|
-
|
53
|
+
# Returns a GoogleDrive::Worksheet with the given title in the spreadsheet.
|
54
|
+
#
|
55
|
+
# Returns nil if not found. Returns the first one when multiple worksheets with the
|
56
|
+
# title are found.
|
57
|
+
def worksheet_by_title(title)
|
58
|
+
worksheets.find { |ws| ws.title == title }
|
59
|
+
end
|
60
|
+
|
61
|
+
# Returns a GoogleDrive::Worksheet with the given gid.
|
62
|
+
#
|
63
|
+
# Returns nil if not found.
|
64
|
+
def worksheet_by_gid(gid)
|
65
|
+
gid = gid.to_s
|
66
|
+
worksheets.find { |ws| ws.gid == gid }
|
67
|
+
end
|
68
|
+
|
69
|
+
# Adds a new worksheet to the spreadsheet. Returns added GoogleDrive::Worksheet.
|
70
|
+
def add_worksheet(title, max_rows = 100, max_cols = 20)
|
71
|
+
xml = <<-"EOS"
|
75
72
|
<entry xmlns='http://www.w3.org/2005/Atom'
|
76
73
|
xmlns:gs='http://schemas.google.com/spreadsheets/2006'>
|
77
74
|
<title>#{h(title)}</title>
|
@@ -79,10 +76,8 @@ module GoogleDrive
|
|
79
76
|
<gs:colCount>#{h(max_cols)}</gs:colCount>
|
80
77
|
</entry>
|
81
78
|
EOS
|
82
|
-
|
83
|
-
|
84
|
-
end
|
85
|
-
|
79
|
+
doc = @session.request(:post, worksheets_feed_url, data: xml)
|
80
|
+
Worksheet.new(@session, self, doc.root)
|
86
81
|
end
|
87
|
-
|
82
|
+
end
|
88
83
|
end
|
data/lib/google_drive/util.rb
CHANGED
@@ -1,182 +1,222 @@
|
|
1
1
|
# Author: Hiroshi Ichikawa <http://gimite.net/>
|
2
2
|
# The license of this source is "New BSD Licence"
|
3
3
|
|
4
|
-
require
|
4
|
+
require 'cgi'
|
5
5
|
|
6
|
-
|
6
|
+
module GoogleDrive
|
7
|
+
module Util #:nodoc:
|
8
|
+
EXT_TO_CONTENT_TYPE = {
|
9
|
+
'.csv' => 'text/csv',
|
10
|
+
'.tsv' => 'text/tab-separated-values',
|
11
|
+
'.tab' => 'text/tab-separated-values',
|
12
|
+
'.doc' => 'application/msword',
|
13
|
+
'.docx' => 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
14
|
+
'.ods' => 'application/x-vnd.oasis.opendocument.spreadsheet',
|
15
|
+
'.odt' => 'application/vnd.oasis.opendocument.text',
|
16
|
+
'.rtf' => 'application/rtf',
|
17
|
+
'.sxw' => 'application/vnd.sun.xml.writer',
|
18
|
+
'.txt' => 'text/plain',
|
19
|
+
'.xls' => 'application/vnd.ms-excel',
|
20
|
+
'.xlsx' => 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
21
|
+
'.pdf' => 'application/pdf',
|
22
|
+
'.png' => 'image/png',
|
23
|
+
'.ppt' => 'application/vnd.ms-powerpoint',
|
24
|
+
'.pps' => 'application/vnd.ms-powerpoint',
|
25
|
+
'.htm' => 'text/html',
|
26
|
+
'.html' => 'text/html',
|
27
|
+
'.zip' => 'application/zip',
|
28
|
+
'.swf' => 'application/x-shockwave-flash'
|
29
|
+
}
|
30
|
+
|
31
|
+
IMPORTABLE_CONTENT_TYPE_MAP = {
|
32
|
+
'application/x-vnd.oasis.opendocument.presentation' => 'application/vnd.google-apps.presentation',
|
33
|
+
'text/tab-separated-values' => 'application/vnd.google-apps.spreadsheet',
|
34
|
+
'image/jpeg' => 'application/vnd.google-apps.document',
|
35
|
+
'image/bmp' => 'application/vnd.google-apps.document',
|
36
|
+
'image/gif' => 'application/vnd.google-apps.document',
|
37
|
+
'application/vnd.ms-excel.sheet.macroenabled.12' => 'application/vnd.google-apps.spreadsheet',
|
38
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.template' => 'application/vnd.google-apps.document',
|
39
|
+
'application/vnd.ms-powerpoint.presentation.macroenabled.12' => 'application/vnd.google-apps.presentation',
|
40
|
+
'application/vnd.ms-word.template.macroenabled.12' => 'application/vnd.google-apps.document',
|
41
|
+
'application/vnd.openxmlformats-officedocument.wordprocessingml.document' => 'application/vnd.google-apps.document',
|
42
|
+
'image/pjpeg' => 'application/vnd.google-apps.document',
|
43
|
+
'application/vnd.google-apps.script+text/plain' => 'application/vnd.google-apps.script',
|
44
|
+
'application/vnd.ms-excel' => 'application/vnd.google-apps.spreadsheet',
|
45
|
+
'application/vnd.sun.xml.writer' => 'application/vnd.google-apps.document',
|
46
|
+
'application/vnd.ms-word.document.macroenabled.12' => 'application/vnd.google-apps.document',
|
47
|
+
'application/vnd.ms-powerpoint.slideshow.macroenabled.12' => 'application/vnd.google-apps.presentation',
|
48
|
+
'text/rtf' => 'application/vnd.google-apps.document',
|
49
|
+
'text/plain' => 'application/vnd.google-apps.document',
|
50
|
+
'application/vnd.oasis.opendocument.spreadsheet' => 'application/vnd.google-apps.spreadsheet',
|
51
|
+
'application/x-vnd.oasis.opendocument.spreadsheet' => 'application/vnd.google-apps.spreadsheet',
|
52
|
+
'image/png' => 'application/vnd.google-apps.document',
|
53
|
+
'application/x-vnd.oasis.opendocument.text' => 'application/vnd.google-apps.document',
|
54
|
+
'application/msword' => 'application/vnd.google-apps.document',
|
55
|
+
'application/pdf' => 'application/vnd.google-apps.document',
|
56
|
+
'application/json' => 'application/vnd.google-apps.script',
|
57
|
+
'application/x-msmetafile' => 'application/vnd.google-apps.drawing',
|
58
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.template' => 'application/vnd.google-apps.spreadsheet',
|
59
|
+
'application/vnd.ms-powerpoint' => 'application/vnd.google-apps.presentation',
|
60
|
+
'application/vnd.ms-excel.template.macroenabled.12' => 'application/vnd.google-apps.spreadsheet',
|
61
|
+
'image/x-bmp' => 'application/vnd.google-apps.document',
|
62
|
+
'application/rtf' => 'application/vnd.google-apps.document',
|
63
|
+
'application/vnd.openxmlformats-officedocument.presentationml.template' => 'application/vnd.google-apps.presentation',
|
64
|
+
'image/x-png' => 'application/vnd.google-apps.document',
|
65
|
+
'text/html' => 'application/vnd.google-apps.document',
|
66
|
+
'application/vnd.oasis.opendocument.text' => 'application/vnd.google-apps.document',
|
67
|
+
'application/vnd.openxmlformats-officedocument.presentationml.presentation' => 'application/vnd.google-apps.presentation',
|
68
|
+
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => 'application/vnd.google-apps.spreadsheet',
|
69
|
+
'application/vnd.google-apps.script+json' => 'application/vnd.google-apps.script',
|
70
|
+
'application/vnd.openxmlformats-officedocument.presentationml.slideshow' => 'application/vnd.google-apps.presentation',
|
71
|
+
'application/vnd.ms-powerpoint.template.macroenabled.12' => 'application/vnd.google-apps.presentation',
|
72
|
+
'text/csv' => 'application/vnd.google-apps.spreadsheet',
|
73
|
+
'application/vnd.oasis.opendocument.presentation' => 'application/vnd.google-apps.presentation',
|
74
|
+
'image/jpg' => 'application/vnd.google-apps.document',
|
75
|
+
'text/richtext' => 'application/vnd.google-apps.document',
|
76
|
+
}
|
77
|
+
|
78
|
+
module_function
|
79
|
+
|
80
|
+
def encode_query(params)
|
81
|
+
params.map { |k, v| CGI.escape(k.to_s) + '=' + CGI.escape(v.to_s) }.join('&')
|
82
|
+
end
|
7
83
|
|
84
|
+
def concat_url(url, piece)
|
85
|
+
(url_base, url_query) = url.split(/\?/, 2)
|
86
|
+
(piece_base, piece_query) = piece.split(/\?/, 2)
|
87
|
+
result_query = [url_query, piece_query].select { |s| s && !s.empty? }.join('&')
|
88
|
+
(url_base || '') +
|
89
|
+
(piece_base || '') +
|
90
|
+
(result_query.empty? ? '' : "?#{result_query}")
|
91
|
+
end
|
8
92
|
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
EXT_TO_CONTENT_TYPE = {
|
14
|
-
".csv" =>"text/csv",
|
15
|
-
".tsv" =>"text/tab-separated-values",
|
16
|
-
".tab" =>"text/tab-separated-values",
|
17
|
-
".doc" =>"application/msword",
|
18
|
-
".docx" => "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
|
19
|
-
".ods" =>"application/x-vnd.oasis.opendocument.spreadsheet",
|
20
|
-
".odt" =>"application/vnd.oasis.opendocument.text",
|
21
|
-
".rtf" =>"application/rtf",
|
22
|
-
".sxw" =>"application/vnd.sun.xml.writer",
|
23
|
-
".txt" =>"text/plain",
|
24
|
-
".xls" =>"application/vnd.ms-excel",
|
25
|
-
".xlsx" => "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
|
26
|
-
".pdf" =>"application/pdf",
|
27
|
-
".png" =>"image/png",
|
28
|
-
".ppt" =>"application/vnd.ms-powerpoint",
|
29
|
-
".pps" =>"application/vnd.ms-powerpoint",
|
30
|
-
".htm" =>"text/html",
|
31
|
-
".html" =>"text/html",
|
32
|
-
".zip" =>"application/zip",
|
33
|
-
".swf" =>"application/x-shockwave-flash",
|
34
|
-
}
|
35
|
-
|
36
|
-
module_function
|
37
|
-
|
38
|
-
def encode_query(params)
|
39
|
-
return params.map(){ |k, v| CGI.escape(k.to_s()) + "=" + CGI.escape(v.to_s()) }.join("&")
|
40
|
-
end
|
41
|
-
|
42
|
-
def concat_url(url, piece)
|
43
|
-
(url_base, url_query) = url.split(/\?/, 2)
|
44
|
-
(piece_base, piece_query) = piece.split(/\?/, 2)
|
45
|
-
result_query = [url_query, piece_query].select(){ |s| s && !s.empty? }.join("&")
|
46
|
-
return (url_base || "") +
|
47
|
-
(piece_base || "") +
|
48
|
-
(result_query.empty? ? "" : "?#{result_query}")
|
49
|
-
end
|
93
|
+
def h(str)
|
94
|
+
# Should also escape "\n" to keep it in cell contents.
|
95
|
+
CGI.escapeHTML(str.to_s).gsub(/\n/, '
')
|
96
|
+
end
|
50
97
|
|
51
|
-
|
52
|
-
|
53
|
-
return CGI.escapeHTML(str.to_s()).gsub(/\n/, '
')
|
54
|
-
end
|
55
|
-
|
56
|
-
def construct_query(arg)
|
57
|
-
|
58
|
-
case arg
|
59
|
-
|
60
|
-
when String
|
61
|
-
return arg
|
62
|
-
|
63
|
-
when Array
|
64
|
-
if arg[0].scan(/\?/).size != arg.size - 1
|
65
|
-
raise(
|
66
|
-
ArgumentError,
|
67
|
-
"The number of placeholders doesn't match the number of arguments: %p" % [arg])
|
68
|
-
end
|
69
|
-
i = 1
|
70
|
-
return arg[0].gsub(/\?/) do
|
71
|
-
v = arg[i]
|
72
|
-
i += 1
|
73
|
-
case v
|
74
|
-
when String
|
75
|
-
"'%s'" % v.gsub(/['\\]/){ "\\" + $& }
|
76
|
-
when Time
|
77
|
-
"'%s'" % v.iso8601
|
78
|
-
when TrueClass
|
79
|
-
"true"
|
80
|
-
when FalseClass
|
81
|
-
"false"
|
82
|
-
else
|
83
|
-
raise(ArgumentError, "Expected String, Time, true or false, but got %p" % [v])
|
84
|
-
end
|
85
|
-
end
|
86
|
-
|
87
|
-
else
|
88
|
-
raise(ArgumentError, "Expected String or Array, but got %p" % [arg])
|
98
|
+
def construct_query(arg)
|
99
|
+
case arg
|
89
100
|
|
90
|
-
|
101
|
+
when String
|
102
|
+
return arg
|
91
103
|
|
104
|
+
when Array
|
105
|
+
if arg[0].scan(/\?/).size != arg.size - 1
|
106
|
+
fail(
|
107
|
+
ArgumentError,
|
108
|
+
"The number of placeholders doesn't match the number of arguments: %p" % [arg])
|
92
109
|
end
|
93
|
-
|
94
|
-
|
95
|
-
|
110
|
+
i = 1
|
111
|
+
return arg[0].gsub(/\?/) do
|
112
|
+
v = arg[i]
|
113
|
+
i += 1
|
114
|
+
case v
|
115
|
+
when String
|
116
|
+
"'%s'" % v.gsub(/['\\]/) { '\\' + $& }
|
117
|
+
when Time
|
118
|
+
"'%s'" % v.iso8601
|
119
|
+
when TrueClass
|
120
|
+
'true'
|
121
|
+
when FalseClass
|
122
|
+
'false'
|
123
|
+
else
|
124
|
+
fail(ArgumentError, 'Expected String, Time, true or false, but got %p' % [v])
|
125
|
+
end
|
96
126
|
end
|
97
127
|
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
old_terms.push(["? in owners", v])
|
128
|
-
when "writer"
|
129
|
-
old_terms.push(["? in writers", v])
|
130
|
-
when "reader"
|
131
|
-
old_terms.push(["? in readers", v])
|
132
|
-
when "showfolders"
|
133
|
-
if v.to_s() == "false"
|
134
|
-
old_terms.push("mimeType != 'application/vnd.google-apps.folder'")
|
135
|
-
end
|
136
|
-
when "showdeleted"
|
137
|
-
if v.to_s() == "false"
|
138
|
-
old_terms.push("trashed = false")
|
139
|
-
end
|
140
|
-
when "ocr", "targetLanguage", "sourceLanguage"
|
141
|
-
raise(ArgumentError, "'%s' parameter is no longer supported." % k)
|
142
|
-
else
|
143
|
-
new_params[k] = v
|
144
|
-
end
|
128
|
+
else
|
129
|
+
fail(ArgumentError, 'Expected String or Array, but got %p' % [arg])
|
130
|
+
|
131
|
+
end
|
132
|
+
end
|
133
|
+
|
134
|
+
def construct_and_query(args)
|
135
|
+
args.select { |a| a }.map { |a| '(%s)' % construct_query(a) }.join(' and ')
|
136
|
+
end
|
137
|
+
|
138
|
+
def convert_params(params)
|
139
|
+
str_params = {}
|
140
|
+
params.each do |k, v|
|
141
|
+
str_params[k.to_s] = v
|
142
|
+
end
|
143
|
+
|
144
|
+
old_terms = []
|
145
|
+
new_params = {}
|
146
|
+
str_params.each do |k, v|
|
147
|
+
case k
|
148
|
+
when 'q'
|
149
|
+
new_params[:q] = construct_query(v)
|
150
|
+
|
151
|
+
# Parameters in the old API.
|
152
|
+
when 'title'
|
153
|
+
if str_params['title-exact'].to_s == 'true'
|
154
|
+
old_terms.push(['name = ?', v])
|
155
|
+
else
|
156
|
+
old_terms.push(['name contains ?', v])
|
145
157
|
end
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
158
|
+
when 'title-exact'
|
159
|
+
# Skips it. It is handled above.
|
160
|
+
when 'opened-min'
|
161
|
+
old_terms.push(['lastViewedByMeDate >= ?', v])
|
162
|
+
when 'opened-max'
|
163
|
+
old_terms.push(['lastViewedByMeDate <= ?', v])
|
164
|
+
when 'edited-min'
|
165
|
+
old_terms.push(['modifiedDate >= ?', v])
|
166
|
+
when 'edited-max'
|
167
|
+
old_terms.push(['modifiedDate <= ?', v])
|
168
|
+
when 'owner'
|
169
|
+
old_terms.push(['? in owners', v])
|
170
|
+
when 'writer'
|
171
|
+
old_terms.push(['? in writers', v])
|
172
|
+
when 'reader'
|
173
|
+
old_terms.push(['? in readers', v])
|
174
|
+
when 'showfolders'
|
175
|
+
if v.to_s == 'false'
|
176
|
+
old_terms.push("mimeType != 'application/vnd.google-apps.folder'")
|
152
177
|
end
|
153
|
-
|
178
|
+
when 'showdeleted'
|
179
|
+
old_terms.push('trashed = false') if v.to_s == 'false'
|
180
|
+
when 'ocr', 'targetLanguage', 'sourceLanguage'
|
181
|
+
fail(ArgumentError, "'%s' parameter is no longer supported." % k)
|
182
|
+
else
|
183
|
+
# e.g., 'pageToken' -> :page_token
|
184
|
+
new_key = k.
|
185
|
+
gsub(/([A-Z]+)([A-Z][a-z])/,'\1_\2').
|
186
|
+
gsub(/([a-z\d])([A-Z])/,'\1_\2').
|
187
|
+
downcase.
|
188
|
+
intern
|
189
|
+
new_params[new_key] = v
|
154
190
|
end
|
191
|
+
end
|
155
192
|
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
193
|
+
unless old_terms.empty?
|
194
|
+
if new_params.key?(:q)
|
195
|
+
fail(ArgumentError, "Cannot specify both 'q' parameter and old query parameters.")
|
196
|
+
else
|
197
|
+
new_params[:q] = construct_and_query(old_terms)
|
160
198
|
end
|
199
|
+
end
|
161
200
|
|
162
|
-
|
163
|
-
|
164
|
-
names = api_obj.class.keys.keys - exceptions.map(&:to_s)
|
165
|
-
names.each() do |name|
|
166
|
-
sc.__send__(:define_method, name) do
|
167
|
-
api_obj.__send__(name)
|
168
|
-
end
|
169
|
-
end
|
170
|
-
end
|
201
|
+
new_params
|
202
|
+
end
|
171
203
|
|
172
|
-
|
173
|
-
|
174
|
-
|
175
|
-
|
176
|
-
|
177
|
-
|
204
|
+
def get_singleton_class(obj)
|
205
|
+
class << obj
|
206
|
+
return self
|
207
|
+
end
|
208
|
+
end
|
209
|
+
|
210
|
+
def delegate_api_methods(obj, api_obj, exceptions = [])
|
211
|
+
sc = get_singleton_class(obj)
|
212
|
+
names = api_obj.public_methods(false) - exceptions
|
213
|
+
names.each do |name|
|
214
|
+
if !(name.to_s =~ /=$/)
|
215
|
+
sc.__send__(:define_method, name) do
|
216
|
+
api_obj.__send__(name)
|
217
|
+
end
|
178
218
|
end
|
179
|
-
|
219
|
+
end
|
180
220
|
end
|
181
|
-
|
221
|
+
end
|
182
222
|
end
|