yql 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ === 0.1.1 2010-06-20
2
+
3
+ * 1 major enhancement:
4
+ * Initial release
@@ -0,0 +1,7 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.rdoc
4
+ lib/yql.rb
5
+ lib/yql/client.rb
6
+ lib/yql/error.rb
7
+ lib/yql/query_builder.rb
@@ -0,0 +1,105 @@
1
+ ==DESCRIPTION
2
+
3
+ A basic Ruby Wrapper for interacting programatically with YQL API.
4
+
5
+
6
+ ==TODO
7
+
8
+ 1. Add Unit Tests
9
+ 2. Add oauth
10
+ 3. Add table creation
11
+ 4. Add update / insert / delete operations
12
+
13
+ ==INSTALLATION
14
+
15
+ sudo gem source --add http://rubygems.org
16
+
17
+ sudo gem install yql
18
+
19
+
20
+ ==USAGE
21
+
22
+ require 'rubygems'
23
+
24
+ require 'yql'
25
+
26
+ ===Building Query
27
+
28
+
29
+ ====Finders
30
+
31
+ yql = Yql::Client.new
32
+
33
+ query = Yql::QueryBuilder.new 'yelp.review.search'
34
+
35
+ query.to_s #=> "select * from yelp.review.search"
36
+
37
+ query.find #=> "select * from yelp.review.search limit 1"
38
+
39
+ query.limit = 4
40
+
41
+ query.to_s #=> "select * from yelp.review.search limit 4"
42
+
43
+ query.find_all #=> "select * from yelp.review.search"
44
+
45
+
46
+ ====Conditions
47
+
48
+ query.conditions = "term like '%pizza%'"
49
+
50
+ query.to_s #=> "select * from yelp.review.search where term='%pizza%'"
51
+
52
+ query.conditions = {:term => 'pizza'}
53
+
54
+ query.to_s #=> "select * from yelp.review.search where term = 'pizza'"
55
+
56
+ query.conditions = {:term => 'pizza', :location => 'london', 'ywsid' => '6L0Lc-yn1OKMkCKeXLD4lg'}
57
+
58
+ query.to_s #=> "select * from yelp.review.search where term='pizza' and location='london' and ywsid= '6L0Lc-yn1OKMkCKeXLD4lg'"
59
+
60
+ query.select = 'user_photo_url, state'
61
+
62
+ yql.query = query
63
+ response = yql.get
64
+
65
+ yql.format = 'json'
66
+ response = yql.get #=> Yql::Response object
67
+
68
+
69
+ ===Piped Filters
70
+
71
+ query.unique = 'name'
72
+
73
+ query.to_s #=> "select title, Rating, LastReviewIntro from yelp.review.search where ywsid='6L0Lc-yn1OKMkCKeXLD4lg' and term='pizza' and location='london' | unique(field='name')"
74
+
75
+ query.tail = 4
76
+
77
+ query.to_s #=> "select title, Rating, LastReviewIntro from yelp.review.search where ywsid='6L0Lc-yn1OKMkCKeXLD4lg' and term='pizza' and location='london' | unique(field='name') | tail(count=4)"
78
+
79
+ query.reorder_pipe_command :from => 1, :to => 0
80
+
81
+ query.to_s #=> "select title, Rating, LastReviewIntro from yelp.review.search where ywsid='6L0Lc-yn1OKMkCKeXLD4lg' and term='pizza' and location='london' | tail(count=4) | unique(field='name')"
82
+
83
+ yql.format = 'json'
84
+ response = yql.get #=> Yql::Response object
85
+
86
+
87
+ ====Pagination
88
+
89
+ query.per_page = 10
90
+ query.current_page = 1
91
+
92
+ yql.query = query
93
+ response = yql.get #=> Yql::Response object
94
+
95
+
96
+ ===Describe and show tables
97
+
98
+ query = Yql::QueryBuilder.describe_table('yelp.review.search')
99
+
100
+ query = Yql::QueryBuilder.show_tables
101
+
102
+ yql.query = query
103
+ response = yql.get #=> Yql::Response object
104
+
105
+ response.show
@@ -0,0 +1,12 @@
1
+ $:.unshift(File.dirname(__FILE__)) unless
2
+ $:.include?(File.dirname(__FILE__)) || $:.include?(File.expand_path(File.dirname(__FILE__)))
3
+
4
+ require 'rubygems'
5
+ require 'CGI'
6
+ require 'net/http'
7
+ require 'net/https'
8
+ require 'rexml/document'
9
+ require 'yql/error.rb'
10
+ require 'yql/client.rb'
11
+ require 'yql/query_builder.rb'
12
+ require 'yql/response.rb'
@@ -0,0 +1,61 @@
1
+ module Yql
2
+
3
+ class Client
4
+
5
+ BASE_URL = 'query.yahooapis.com'
6
+ VERSION = 'v1'
7
+ URL_SUFFIX = 'public/yql'
8
+ YQL_ENV = 'http://datatables.org/alltables.env'
9
+
10
+ attr_accessor :query, :diagnostics, :format
11
+
12
+ def initialize(args={})
13
+ @diagnostics = args[:diagnostics] #true or false
14
+ @version = args[:version]
15
+ @query = args[:query]
16
+ @format = args[:format] || 'xml'
17
+ end
18
+
19
+ def query
20
+ @query.kind_of?(Yql::QueryBuilder) ? @query.to_s : @query
21
+ end
22
+
23
+ def version
24
+ @version ||= VERSION
25
+ end
26
+
27
+ def full_url
28
+ "#{version}/#{URL_SUFFIX}"
29
+ end
30
+
31
+ def get
32
+ if query.nil?
33
+ raise Yql::IncompleteRequestParameter, "Query not specified"
34
+ end
35
+ http = Net::HTTP.new(BASE_URL, Net::HTTP.https_default_port)
36
+ http.use_ssl = true
37
+ path = "/#{version}/#{URL_SUFFIX}"
38
+ Yql::Response.new(http.post(path, parameters), format)
39
+ end
40
+
41
+ def parameters
42
+ url_parameters = "q=#{CGI.escape(query)}&env=#{YQL_ENV}"
43
+ url_parameters = add_format(url_parameters)
44
+ add_diagnostics(url_parameters)
45
+ end
46
+
47
+ def add_format(existing_parameters)
48
+ return unless existing_parameters
49
+ return existing_parameters unless format
50
+ return existing_parameters + "&format=#{format}"
51
+ end
52
+
53
+ def add_diagnostics(existing_parameters)
54
+ return unless existing_parameters
55
+ return existing_parameters unless diagnostics
56
+ return existing_parameters + "&diagnostics=true"
57
+ end
58
+
59
+ end
60
+
61
+ end
@@ -0,0 +1,19 @@
1
+ module Yql
2
+ class Error < StandardError
3
+
4
+ def initialize(data)
5
+ @data = data
6
+ super
7
+ end
8
+ end
9
+
10
+ class ResponseFailure < Error
11
+ end
12
+
13
+ class NoResult < Error
14
+ end
15
+
16
+ class IncompleteRequestParameter < Error
17
+ end
18
+
19
+ end
@@ -0,0 +1,186 @@
1
+ module Yql
2
+
3
+ class QueryBuilder
4
+
5
+ attr_accessor :table, :conditions, :limit, :truncate, :sanitize_field, :select,
6
+ :sort_field, :current_pipe_command_types, :sort_descending,
7
+ :per_page, :current_page
8
+
9
+ def initialize(table, args = {})
10
+ @select = args[:select]
11
+ @table = table
12
+ @use_statement = args[:use]
13
+ @conditions = args[:conditions]
14
+ @limit = args[:limit]
15
+ @tail = args[:tail]
16
+ @reverse = args[:reverse]
17
+ @unique = args[:unique]
18
+ @sanitize = args[:sanitize]
19
+ @sort_descending = args[:sort_descending]
20
+ @sanitize_field = args[:sanitize_field]
21
+ @sort_field = args[:sort_field]
22
+ @current_pipe_command_types = []
23
+ @per_page = args[:per_page]
24
+ end
25
+
26
+ def find
27
+ self.limit = 1
28
+ "#{construct_query}"
29
+ end
30
+
31
+ def find_all
32
+ self.limit = nil
33
+ construct_query
34
+ end
35
+
36
+ def self.show_tables
37
+ "show tables;"
38
+ end
39
+
40
+ def self.describe_table(table)
41
+ "desc #{table};"
42
+ end
43
+
44
+ def describe_table
45
+ Yql::QueryBuilder.describle_table(table)
46
+ end
47
+
48
+ def to_s
49
+ construct_query
50
+ end
51
+
52
+ def limit
53
+ return unless @limit
54
+ "limit #{@limit}"
55
+ end
56
+
57
+ # Conditions can either be provided as hash or plane string
58
+ def conditions
59
+ if @conditions.kind_of?(String)
60
+ cond = @conditions
61
+ elsif @conditions.kind_of?(Hash)
62
+ cond = @conditions.collect do |k,v|
63
+ val = v.kind_of?(String) ? "'#{v}'" : v
64
+ "#{k.to_s}=#{val}"
65
+ end
66
+ cond = cond.join(' and ')
67
+ else
68
+ return
69
+ end
70
+ return "where #{cond}"
71
+ end
72
+
73
+ %w{sort tail truncate reverse unique sanitize}.each do |method|
74
+ self.send(:define_method, "#{method}=") do |param|
75
+ instance_variable_set("@#{method}", param)
76
+ current_pipe_command_types << method unless current_pipe_command_types.include?(method)
77
+ end
78
+ end
79
+
80
+ # Cption can be piped
81
+ # Sorts the result set according to the specified field (column) in the result set.
82
+ def sort
83
+ return unless @sort_field
84
+ return "sort(field='#{@sort_field}')" unless @sort_descending
85
+ return "sort(field='#{@sort_field}', descending='true')"
86
+ end
87
+
88
+ # Cption can be piped
89
+ # Gets the last count items
90
+ def tail
91
+ return unless @tail
92
+ "tail(count=#{@tail})"
93
+ end
94
+
95
+ # Cption can be piped
96
+ # Gets the first count items (rows)
97
+ def truncate
98
+ return unless @truncate
99
+ "truncate(count=#{@truncate})"
100
+ end
101
+
102
+ # Cption can be piped
103
+ # Reverses the order of the rows
104
+ def reverse
105
+ return unless @reverse
106
+ "reverse()"
107
+ end
108
+
109
+ # Cption can be piped
110
+ # Removes items (rows) with duplicate values in the specified field (column)
111
+ def unique
112
+ return unless @unique
113
+ "unique(field='#{@unique}')"
114
+ end
115
+
116
+ # Cption can be piped
117
+ # Sanitizes the output for HTML-safe rendering. To sanitize all returned fields, omit the field parameter.
118
+ def sanitize
119
+ return unless @sanitize
120
+ return "sanitize()" unless @sanitize_field
121
+ "sanitize(field='#{@sanitize_field}')"
122
+ end
123
+
124
+ # Its always advisable to order the pipe when there are more than one
125
+ # pipe commands available else unexpected results might get returned
126
+ # reorder_pipe_command {:from => 1, :to => 0}
127
+ # the values in the hash are the element numbers
128
+ #
129
+ def reorder_pipe_command(args)
130
+ return if current_pipe_command_types.empty?
131
+ if args[:from].nil? or args[:to].nil?
132
+ raise Yql::Error, "Not able to move pipe commands. Wrong element numbers. Please try again"
133
+ end
134
+ args.values.each do |element|
135
+ if element > current_pipe_command_types.size-1
136
+ raise Yql::Error, "Not able to move pipe commands. Wrong element numbers. Please try again"
137
+ end
138
+ end
139
+ element_to_be_inserted_at = args[:from] < args[:to] ? args[:to]+1 : args[:to]
140
+ element_to_be_removed = args[:from] < args[:to] ? args[:from] : args[:from]+1
141
+ current_pipe_command_types.insert(element_to_be_inserted_at, current_pipe_command_types.at(args[:from]))
142
+ current_pipe_command_types.delete_at(element_to_be_removed)
143
+ end
144
+
145
+
146
+ # Remove a command that will be piped to the yql query
147
+ def remove_pipe_command(command)
148
+ current_pipe_command_types.delete(command)
149
+ end
150
+
151
+ private
152
+
153
+ def pipe_commands
154
+ return if current_pipe_command_types.empty?
155
+ '| ' + current_pipe_command_types.map{|c| self.send(c)}.join(' | ')
156
+ end
157
+
158
+ def build_select_query
159
+ [select_statement, conditions, limit, pipe_commands].compact.join(' ')
160
+ end
161
+
162
+ def construct_query
163
+ return build_select_query unless @use
164
+ return [@use, build_select_query].join('; ')
165
+ end
166
+
167
+ def select_statement
168
+ select = "select #{column_select} from #{table}"
169
+ return select unless per_page
170
+ with_pagination(select)
171
+ end
172
+
173
+ def with_pagination(select)
174
+ self.current_page ||= 1
175
+ offset = (current_page - 1) * per_page
176
+ last_record = current_page * per_page
177
+ "#{select}(#{offset},#{last_record})"
178
+ end
179
+
180
+ def column_select
181
+ @select ? @select : '*'
182
+ end
183
+
184
+ end
185
+
186
+ end
metadata ADDED
@@ -0,0 +1,69 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: yql
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - Nasir Jamal
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2010-06-20 00:00:00 +01:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: Yql is a ruby wrapper for Yahoo Query Language.
22
+ email: nas35_in@yahoo.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files:
28
+ - README.rdoc
29
+ files:
30
+ - History.txt
31
+ - Manifest.txt
32
+ - README.rdoc
33
+ - lib/yql.rb
34
+ - lib/yql/client.rb
35
+ - lib/yql/error.rb
36
+ - lib/yql/query_builder.rb
37
+ has_rdoc: true
38
+ homepage: http://github.com/nas/yql
39
+ licenses: []
40
+
41
+ post_install_message:
42
+ rdoc_options:
43
+ - --charset=UTF-8
44
+ require_paths:
45
+ - lib
46
+ required_ruby_version: !ruby/object:Gem::Requirement
47
+ requirements:
48
+ - - ">="
49
+ - !ruby/object:Gem::Version
50
+ segments:
51
+ - 1
52
+ - 8
53
+ version: "1.8"
54
+ required_rubygems_version: !ruby/object:Gem::Requirement
55
+ requirements:
56
+ - - ">="
57
+ - !ruby/object:Gem::Version
58
+ segments:
59
+ - 0
60
+ version: "0"
61
+ requirements: []
62
+
63
+ rubyforge_project:
64
+ rubygems_version: 1.3.6
65
+ signing_key:
66
+ specification_version: 3
67
+ summary: Yql is a ruby wrapper for Yahoo Query Language.
68
+ test_files: []
69
+