google_drive 1.0.6 → 2.0.0.pre1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|