sensis 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +6 -0
  2. data/.rvmrc +1 -0
  3. data/Gemfile +4 -0
  4. data/Gemfile.lock +95 -0
  5. data/MIT-LICENSE +20 -0
  6. data/README.markdown +216 -0
  7. data/Rakefile +23 -0
  8. data/init.rb +1 -0
  9. data/install.rb +1 -0
  10. data/lib/sensis.rb +320 -0
  11. data/lib/sensis/version.rb +3 -0
  12. data/sensis.gemspec +32 -0
  13. data/spec/dummy/Gemfile +7 -0
  14. data/spec/dummy/Gemfile.lock +90 -0
  15. data/spec/dummy/Rakefile +8 -0
  16. data/spec/dummy/app/assets/javascripts/application.js +6 -0
  17. data/spec/dummy/app/assets/stylesheets/application.css +5 -0
  18. data/spec/dummy/app/controllers/application_controller.rb +3 -0
  19. data/spec/dummy/app/helpers/application_helper.rb +2 -0
  20. data/spec/dummy/app/mailers/.gitkeep +0 -0
  21. data/spec/dummy/app/models/.gitkeep +0 -0
  22. data/spec/dummy/app/views/layouts/application.html.erb +14 -0
  23. data/spec/dummy/config.ru +4 -0
  24. data/spec/dummy/config/application.rb +46 -0
  25. data/spec/dummy/config/boot.rb +10 -0
  26. data/spec/dummy/config/database.yml +22 -0
  27. data/spec/dummy/config/environment.rb +5 -0
  28. data/spec/dummy/config/environments/development.rb +18 -0
  29. data/spec/dummy/config/environments/production.rb +52 -0
  30. data/spec/dummy/config/environments/test.rb +39 -0
  31. data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
  32. data/spec/dummy/config/initializers/inflections.rb +10 -0
  33. data/spec/dummy/config/initializers/mime_types.rb +5 -0
  34. data/spec/dummy/config/initializers/secret_token.rb +7 -0
  35. data/spec/dummy/config/initializers/session_store.rb +8 -0
  36. data/spec/dummy/config/locales/en.yml +5 -0
  37. data/spec/dummy/config/routes.rb +3 -0
  38. data/spec/dummy/config/sensis.yml.example +11 -0
  39. data/spec/dummy/log/.gitkeep +0 -0
  40. data/spec/dummy/public/404.html +26 -0
  41. data/spec/dummy/public/422.html +26 -0
  42. data/spec/dummy/public/500.html +26 -0
  43. data/spec/dummy/public/favicon.ico +0 -0
  44. data/spec/dummy/script/rails +6 -0
  45. data/spec/lib/search_spec.rb +33 -0
  46. data/spec/spec_helper.rb +24 -0
  47. data/uninstall.rb +1 -0
  48. metadata +246 -0
@@ -0,0 +1,6 @@
1
+ spec/dummy/log/*.log
2
+ spec/dummy/tmp/*
3
+ .DS_Store
4
+ .bundle
5
+ spec/dummy/config/sensis.yml
6
+ *.gem
data/.rvmrc ADDED
@@ -0,0 +1 @@
1
+ rvm use 1.8.7@sensis
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # gem's dependencies in sensis.gemspec
4
+ gemspec
@@ -0,0 +1,95 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ sensis (0.0.2)
5
+
6
+ GEM
7
+ remote: http://rubygems.org/
8
+ specs:
9
+ actionpack (3.1.1)
10
+ activemodel (= 3.1.1)
11
+ activesupport (= 3.1.1)
12
+ builder (~> 3.0.0)
13
+ erubis (~> 2.7.0)
14
+ i18n (~> 0.6)
15
+ rack (~> 1.3.2)
16
+ rack-cache (~> 1.1)
17
+ rack-mount (~> 0.8.2)
18
+ rack-test (~> 0.6.1)
19
+ sprockets (~> 2.0.2)
20
+ activemodel (3.1.1)
21
+ activesupport (= 3.1.1)
22
+ builder (~> 3.0.0)
23
+ i18n (~> 0.6)
24
+ activesupport (3.1.1)
25
+ multi_json (~> 1.0)
26
+ builder (3.0.0)
27
+ columnize (0.3.4)
28
+ diff-lcs (1.1.3)
29
+ erubis (2.7.0)
30
+ hike (1.2.1)
31
+ i18n (0.6.0)
32
+ json (1.6.1)
33
+ linecache (0.46)
34
+ rbx-require-relative (> 0.0.4)
35
+ multi_json (1.0.3)
36
+ nokogiri (1.5.0)
37
+ rack (1.3.5)
38
+ rack-cache (1.1)
39
+ rack (>= 0.4)
40
+ rack-mount (0.8.3)
41
+ rack (>= 1.0.0)
42
+ rack-ssl (1.3.2)
43
+ rack
44
+ rack-test (0.6.1)
45
+ rack (>= 1.0)
46
+ railties (3.1.1)
47
+ actionpack (= 3.1.1)
48
+ activesupport (= 3.1.1)
49
+ rack-ssl (~> 1.3.2)
50
+ rake (>= 0.8.7)
51
+ rdoc (~> 3.4)
52
+ thor (~> 0.14.6)
53
+ rake (0.9.2.2)
54
+ rbx-require-relative (0.0.5)
55
+ rcov (0.9.11)
56
+ rdoc (3.11)
57
+ json (~> 1.4)
58
+ rspec (2.7.0)
59
+ rspec-core (~> 2.7.0)
60
+ rspec-expectations (~> 2.7.0)
61
+ rspec-mocks (~> 2.7.0)
62
+ rspec-core (2.7.1)
63
+ rspec-expectations (2.7.0)
64
+ diff-lcs (~> 1.1.2)
65
+ rspec-mocks (2.7.0)
66
+ rspec-rails (2.7.0)
67
+ actionpack (~> 3.0)
68
+ activesupport (~> 3.0)
69
+ railties (~> 3.0)
70
+ rspec (~> 2.7.0)
71
+ ruby-debug (0.10.4)
72
+ columnize (>= 0.1)
73
+ ruby-debug-base (~> 0.10.4.0)
74
+ ruby-debug-base (0.10.4)
75
+ linecache (>= 0.3)
76
+ sprockets (2.0.3)
77
+ hike (~> 1.2)
78
+ rack (~> 1.0)
79
+ tilt (~> 1.1, != 1.3.0)
80
+ thor (0.14.6)
81
+ tilt (1.3.3)
82
+ tzinfo (0.3.31)
83
+
84
+ PLATFORMS
85
+ ruby
86
+
87
+ DEPENDENCIES
88
+ json
89
+ nokogiri
90
+ rcov
91
+ rspec-core
92
+ rspec-rails
93
+ ruby-debug
94
+ sensis!
95
+ tzinfo
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Ben Wiseley wiseleyb@gmail.com
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.
@@ -0,0 +1,216 @@
1
+ # Sensis Search
2
+ This is a pretty basic api wrapper for Sensis searching.
3
+
4
+ For more information on Sensis see their developer site: http://developers.sensis.com.au/
5
+
6
+ ## Install
7
+
8
+ gem install sensis
9
+
10
+ ## Usage
11
+ You can get a free api key at http://developers.sensis.com.au/
12
+
13
+ Note - all methods (search, get_listing_by_id and report) all take an additional key: :env => "test" or "prod". This decides if the test endpoint or the production endpoint will be used. It defaults to "test". You can specify this in the config if you don't want to pass it.
14
+
15
+ All results can be accessed by their hash values or by method names... example:
16
+
17
+ res["code"] == res.code
18
+ res["results"].size == res.results.size
19
+
20
+ ## Config
21
+ If you don't want to pass your api_key or endpoint env every time you can put it config/sensis.yml
22
+
23
+ development:
24
+ api_key: abcdefg
25
+ env: test
26
+
27
+ test:
28
+ api_key: abcdefg
29
+ env: test
30
+
31
+ production:
32
+ api_key: abcdefg
33
+ env: prod
34
+
35
+ ### Search
36
+
37
+ res = Sensis.search(:key => "your api key", :query => "poker")
38
+
39
+ Or - if you are using the config...
40
+
41
+ res = Sensis.search(:query => "poker")
42
+
43
+ Sensis.search takes a hash of options defined here: http://developers.sensis.com.au/docs/endpoint_reference/Search
44
+
45
+ Sample Search result set: see http://developers.sensis.com.au/docs/endpoint_reference for more information
46
+
47
+ {
48
+ "results": [
49
+ {
50
+ "id": "999",
51
+ "name": "Bob's Hairdresser",
52
+ "categories": [
53
+ {
54
+ "name": "Hairdressers"
55
+ }
56
+ ],
57
+ "primaryAddress" {
58
+ "addressLine": "123 Fitzroy Street",
59
+ ...
60
+ }
61
+ ...
62
+ }
63
+ ...
64
+ ],
65
+ ...
66
+ "count": 20,
67
+ "totalResults": 19791,
68
+ "executedQuery": "hairdresser",
69
+ "originalQuery": "hairdresser",
70
+ "date": "2011-02-28T12:01:02.345+1000",
71
+ "time": 10,
72
+ "code": 200,
73
+ "message": "OK"
74
+ }
75
+
76
+ So - you could do something like:
77
+
78
+ res.results.first.name == res["results"][0]["name"]
79
+
80
+ #### Search paging
81
+
82
+ res = Sensis.search(:key => "your api key", :query => "poker")
83
+ pages = res.totalResults.to_i / 20
84
+ pages.times do |page|
85
+ res = Sensis.search(:key => "your api key", :query => "poker", :page => (page +1).to_s)
86
+ end
87
+
88
+ More on paging in the docs http://developers.sensis.com.au/docs/using_endpoints/Pagination
89
+
90
+ ### Get Listing By ID
91
+
92
+ res = Sensis.get_listing_by_id(:key => "your api key", :query => "999")
93
+
94
+ Or - if you are using the config...
95
+
96
+ res = Sensis.get_listing_by_id(:query => "999")
97
+
98
+ Sample result set: see for more information
99
+
100
+ {
101
+ "results": [
102
+ {
103
+ "businessId": "999",
104
+ "businessName": "Hairdresser",
105
+ "categories": [
106
+ {
107
+ "name": "Hairdressers"
108
+ }
109
+ ],
110
+ "primaryAddress": {
111
+ "addressLine": "123 Fitzroy Street",
112
+ },
113
+ ...
114
+ }
115
+ ],
116
+ "count": 1,
117
+ "totalResults": 1,
118
+ "executedQuery": "999",
119
+ "originalQuery": "999",
120
+ "date": "2011-02-28T12:01:02.345+1000",
121
+ "time": 10,
122
+ "code": 200,
123
+ "message": "OK"
124
+ }
125
+
126
+ ### Report
127
+
128
+ res = Sensis.report(:key => "your api key", :userIp => "192.1.2.3", :userAgent => "Mozilla Firefox",
129
+ :userSessionId => "123467890",
130
+ :id => "VyY2UiOiJZRUxMT1ciLCJwcm9kdWN0SWQiOiIxMjM0IiwicHJvZHVjdFZlcnNpb24iOiI1Njc4In0")
131
+
132
+ Or - if you are using the config...
133
+
134
+ res = Sensis.report(:userIp => "192.1.2.3", :userAgent => "Mozilla Firefox",
135
+ :userSessionId => "123467890",
136
+ :id => "VyY2UiOiJZRUxMT1ciLCJwcm9kdWN0SWQiOiIxMjM0IiwicHJvZHVjdFZlcnNpb24iOiI1Njc4In0")
137
+
138
+ You can also include multiple ID's by passing an array
139
+
140
+ res = Sensis.report(:key => "your api key", :userIp => "192.1.2.3", :userAgent => "Mozilla Firefox",
141
+ :userSessionId => "123467890",
142
+ :id => ["1","2","3","4"])
143
+
144
+
145
+ Sample report result set: see http://developers.sensis.com.au/docs/endpoint_reference/Report for more information
146
+
147
+ {
148
+ "results": [
149
+ {
150
+ "id": "999",
151
+ "name": "Bob's Hairdresser",
152
+ "categories": [
153
+ {
154
+ "name": "Hairdressers"
155
+ }
156
+ ],
157
+ "reportingId":"VyY2UiOiJZRUxMT1ciLCJwcm9kdWN0SWQiOiIx ⤶
158
+ MjM0IiwicHJvZHVjdFZlcnNpb24iOiI1Njc4In0",
159
+ ...
160
+ },
161
+ {
162
+ "id": "1000",
163
+ "name": "Jill's Hairdresser",
164
+ "categories": [
165
+ {
166
+ "name": "Hairdressers"
167
+ }
168
+ ],
169
+ "reportingId":"eyJib29rSWQiOiJTMDBXIiwibGlzdGluZ05hbW ⤶
170
+ UiOiJzdWJzY3JpYmVyTmFtZSIsInNvdXJjZSI6",
171
+ ...
172
+ }
173
+ ...
174
+ ],
175
+ ...
176
+ "count": 20,
177
+ "totalResults": 19791,
178
+ "executedQuery": "hairdresser",
179
+ "originalQuery": "hairdresser",
180
+ "date": "2011-02-28T12:01:02.345+1000",
181
+ "time": 10,
182
+ "code": 200,
183
+ "message": "OK"
184
+ }
185
+
186
+ ## TODO
187
+ * add more tests
188
+ * add better examples for Get Listing By ID and Report. Haven't really used these yet.
189
+
190
+ ## Testing
191
+ 1. clone the code: git clone git://github.com/wiseleyb/Sensis.git
192
+ 2. gem install bundler
193
+ 3. bundle install
194
+ 4. copy spec/dummy/config/sensis.yml.example to sensis.yml
195
+ 5. fill in your api_key in sensis.yml
196
+
197
+ bundle exec rspec spec
198
+
199
+ ## Console
200
+ If you're working on the gem you can muck around in console by
201
+
202
+ 1. copy spec/dummy/config/sensis.yml.example to sensis.yml
203
+ 2. fill in your api_key in sensis.yml
204
+
205
+ cd spec/dummy
206
+ bundle execute rails c
207
+
208
+ ### Credits
209
+
210
+ Thank you to jdunwoody for some sample sensis code https://github.com/jdunwoody/SensisSearchApp/blob/master/lib/search_command.rb
211
+
212
+ Thank you to mikedemers for some cool json -> class method code (class ResponseData) https://github.com/mikedemers/rbing/blob/master/lib/rbing.rb
213
+
214
+ # Change log
215
+ 0.0.1 - initial release
216
+ 0.0.2 - adding sensis.yml support for storing api_keys and env setting. reverted to ruby -v 1.8.7
@@ -0,0 +1,23 @@
1
+ require 'rake'
2
+ require 'rake/testtask'
3
+ require 'rdoc/task'
4
+
5
+ desc 'Default: run unit tests.'
6
+ task :default => :test
7
+
8
+ desc 'Test the zemanta_fu plugin.'
9
+ Rake::TestTask.new(:test) do |t|
10
+ t.libs << 'lib'
11
+ t.libs << 'test'
12
+ t.pattern = 'test/**/*_test.rb'
13
+ t.verbose = true
14
+ end
15
+
16
+ desc 'Generate documentation for the zemanta_fu plugin.'
17
+ RDoc::Task.new(:rdoc) do |rdoc|
18
+ rdoc.rdoc_dir = 'rdoc'
19
+ rdoc.title = 'ZemantaFu'
20
+ rdoc.options << '--line-numbers' << '--inline-source'
21
+ rdoc.rdoc_files.include('README')
22
+ rdoc.rdoc_files.include('lib/**/*.rb')
23
+ end
data/init.rb ADDED
@@ -0,0 +1 @@
1
+ # Include hook code here
@@ -0,0 +1 @@
1
+ # Install hook code here
@@ -0,0 +1,320 @@
1
+ require 'rubygems'
2
+ require 'json'
3
+ require 'net/http'
4
+
5
+ module Sensis
6
+
7
+ def Sensis.config
8
+ if @config.nil?
9
+ config_file = "#{::Rails.root}/config/sensis.yml"
10
+ if File.exists?(config_file)
11
+ @config = YAML.load_file(config_file)
12
+ @api_key = @config[::Rails.env]["api_key"]
13
+ @env = @config[::Rails.env]["env"]
14
+ end
15
+ end
16
+ return @config
17
+ end
18
+
19
+ def Sensis.api_key
20
+ @api_key ||= Sensis.config[::Rails.env]["api_key"] unless Sensis.config.nil?
21
+ end
22
+
23
+ def Sensis.env
24
+ @env ||= Sensis.config[::Rails.env]["env"] unless Sensis.config.nil?
25
+ end
26
+
27
+ # Search - http://developers.sensis.com.au/docs/endpoint_reference/Search
28
+ # options (from http://developers.sensis.com.au/docs/endpoint_reference/Search)
29
+ # key string API key (required) See Authenticating for details.
30
+ # query string What to search for (required unless location is given) See Search Query Tips for details.
31
+ # location string Location to search in (required unless query is given) See Location Tips for details.
32
+ # page number Page number to return. See Pagination for details.
33
+ # rows number Number of listings to return per page. See Pagination for details.
34
+ # sortBy string Listing sort order. See Sorting for details.
35
+ # sensitiveCategories boolean Filtering potentially unsafe content. See Filtering Unsafe Content for details.
36
+ # categoryId string Filter listings returned by category id See Category Filtering for details.
37
+ # postcode string Filter listings returned by postcode See Postcode Filtering for details.
38
+ # radius number Filter listings returned to those within the radius distance of the location. See Radius Filtering for details.
39
+ # suburb string Filter listings returned to those within the given suburb. Repeat the parameter to include multiple suburbs in the filter. See Suburb Filtering for details.
40
+ # state string Filter listings returned to those within the given state. Repeat the parameter to include multiple states in the filter. See State Filtering for details.
41
+ # boundingBox string Filter listings returned to those within a bounding box. See Bounding Box Filtering for details.
42
+ # content string Filter listings returned to only those with certain types of content. See Filtering by Content Type for details.
43
+ # productKeyword string Filter listings returned to only those containing certain product keywords. See Filtering by Product Keyword for details.
44
+ # mode string Default is "test" - values "test","prod" - decides which endpoint is used - test or production
45
+ # Example - Sensis.serch(:key => "key you got from developers.sensis.com.au", :query => "poker")
46
+ def Sensis.search(options = {})
47
+ options[:key] ||= Sensis.api_key
48
+ errors = []
49
+ errors << ":key (api key) is required" if options[:key].blank?
50
+ errors << ":query or :location is required" if options[:query].blank? && options[:location].blank?
51
+ raise errors.join("; ") unless errors.empty?
52
+ Sensis.execute("search", options)
53
+ end
54
+
55
+ # Get Listing By ID - http://developers.sensis.com.au/docs/endpoint_reference/Get_by_Listing_ID
56
+ # options
57
+ # key string API key (required) See Authenticating for details.
58
+ # query string Unique ID of the listing to return (required) This is the id field of the listing. See Listing Schema for details.
59
+ # mode string Default is "test" - values "test","prod" - decides which endpoint is used - test or production
60
+ def Sensis.get_listing_by_id(options = {})
61
+ options[:key] ||= Sensis.api_key
62
+ errors = []
63
+ errors << ":key (api key) is required" if options[:key].blank?
64
+ errors << ":query is required" if options[:query].blank?
65
+ raise errors.join("; ") unless errors.empty?
66
+ Sensis.execute("getByListingId", options)
67
+ end
68
+
69
+ # Report - http://developers.sensis.com.au/docs/endpoint_reference/Report
70
+ # key string API key (required) See Authenticating for details.
71
+ # userIp string IP address of user accessing your application (required) See Reporting Usage Events for details.
72
+ # id string or an array reportingId of listing associated with event (required) The reportingId field provided in each listing returned in a search response. Multiple id parameters can be added where the same event applies to each listing, except where the content parameter is specified. See Reporting Usage Events for details.
73
+ # userAgent string User agent of user accessing your application For example, from the user-agent HTTP header. See Reporting Usage Events for details.
74
+ # userSessionId string Session id of user accessing your application See Note below.
75
+ # content string Specific content to which the event applies (required) Only required for certain events. See Reporting Usage Events for details.
76
+ # mode string Default is "test" - values "test","prod" - decides which endpoint is used - test or production
77
+ def Sensis.report(options = {})
78
+ options[:key] ||= Sensis.api_key
79
+ errors = []
80
+ errors << ":key (api key) is required" if options[:key].blank?
81
+ errors << ":userIp is required" if options[:userIp].blank?
82
+ errors << ":id is required" if options[:id].blank?
83
+ raise errors.join("; ") unless errors.empty?
84
+ Sensis.execute("report", options)
85
+ end
86
+
87
+ def Sensis.execute(endpoint_type, options)
88
+ # location of the search endpoint
89
+ endpoint = Sensis.endpoint(endpoint_type, options)
90
+
91
+ # construct a URL with the query string, escaping any special characters.
92
+ url = "#{endpoint}?"
93
+ options.keys.each do |k|
94
+ if options[k].is_a?(Array)
95
+ options[k].each do |v|
96
+ url = "#{url}&#{k}=#{URI.encode(v)}"
97
+ end
98
+ else
99
+ url = "#{url}&#{k}=#{URI.encode(options[k].to_s)}"
100
+ end
101
+ end
102
+
103
+ # call the endpoint, returning the HTTP response
104
+ response = Net::HTTP.get_response(URI.parse(url))
105
+
106
+ # raise an exception if not HTTP 200 (OK)
107
+ response.error! unless response.instance_of? Net::HTTPOK
108
+
109
+ # convert the response message in to a Hash object
110
+ result = JSON.parse(response.body)
111
+
112
+ res = ResponseData.new(result) if result
113
+
114
+ # ensure successful status code
115
+ case result["code"]
116
+ when 200 # success
117
+ return res
118
+ when 206 # spell-checker was run
119
+ puts "Note: #{result["message"]}"
120
+ return res
121
+ else
122
+ raise "API returned error: #{res.message}, code: #{result.code}"
123
+ end
124
+ end
125
+
126
+ def Sensis.endpoint(endpoint_type, options)
127
+ env ||= options.delete(:env)
128
+ env ||= Sensis.env
129
+ env ||= "test"
130
+ endpoint = "http://api.sensis.com.au/ob-20110511/#{env}/#{endpoint_type}"
131
+ endpoint = "#{endpoint}/#{options[:eventName]}" if endpoint_type == "report"
132
+ return endpoint
133
+ end
134
+
135
+ # from https://github.com/mikedemers/rbing/blob/master/lib/rbing.rb
136
+ class ResponseData < Hash
137
+ private
138
+ def initialize(data={})
139
+ data.each_pair {|k,v| self[k.to_s] = deep_parse(v) }
140
+ end
141
+ def deep_parse(data)
142
+ case data
143
+ when Hash
144
+ self.class.new(data)
145
+ when Array
146
+ data.map {|v| deep_parse(v) }
147
+ else
148
+ data
149
+ end
150
+ end
151
+ def method_missing(*args)
152
+ name = args[0].to_s
153
+ return self[name] if has_key? name
154
+ camelname = name.split('_').map {|w| "#{w[0,1].upcase}#{w[1..-1]}" }.join("")
155
+ if has_key? camelname
156
+ self[camelname]
157
+ else
158
+ super *args
159
+ end
160
+ end
161
+ end
162
+
163
+ end
164
+
165
+
166
+ # def example()
167
+ # # perform a search for 'hairdresser'
168
+ # results = perform_search("hairdresser", "st kilda, vic")
169
+ #
170
+ # puts "Total results found: #{results["totalResults"]}"
171
+ #
172
+ # # the results member is an array containing each listings as a nested Hash object
173
+ # results["results"].each do |r|
174
+ # puts "#{r["name"]} (#{r["primaryAddress"]["addressLine"]})"
175
+ # end
176
+ # end
177
+ #
178
+ # # ZemantaFu
179
+ # require 'net/http'
180
+ # require 'rubygems'
181
+ # require 'xmlsimple'
182
+ #
183
+ # class ZemantaFu
184
+ #
185
+ # # refer to http://developer.zemanta.com/docs/suggest/ for valid options
186
+ # def self.search(text, options = {})
187
+ # # tags - keywords
188
+ # # in-text links
189
+ # # categories
190
+ #
191
+ # options[:method] ||= "zemanta.suggest"
192
+ # options[:format] ||= "xml"
193
+ # options[:return_categories] ||= "dmoz"
194
+ # options[:api_key] ||= "o26uvljcvr6q9l0zf155difg"
195
+ # # options[:return_images] ||= 0
196
+ # options[:markup_limit] ||= 1000
197
+ # options[:articles_limit] ||= 1000
198
+ #
199
+ # options[:text] = text
200
+ #
201
+ # [:api_key].each do |k|
202
+ # raise "Missing required key :#{k} in options." unless options.has_key?(k)
203
+ # end
204
+ #
205
+ # gateway = 'http://api.zemanta.com/services/rest/0.0/'
206
+ # res = Net::HTTP.post_form(URI.parse(gateway), options.stringify_keys)
207
+ # data = XmlSimple.xml_in(res.body)
208
+ # res = ResponseData.new(data)
209
+ #
210
+ # # clean up top level arrays so that we can do
211
+ # # search("poker").articles
212
+ # # instead of
213
+ # # search("poker"").articles[0].article
214
+ # res.keys.each do |k|
215
+ # ks = k.singularize
216
+ # if res[k][0] && res[k][0].is_a?(Hash) && res[k][0].keys.include?(ks)
217
+ # res[k] = res[k][0][ks]
218
+ # else
219
+ # res[k] = res[k][0]
220
+ # end
221
+ # end
222
+ # # ensure there's something there for everthing
223
+ # ["articles", "images", "keywords", "categories"].each do |k|
224
+ # res[k] ||= []
225
+ # end
226
+ # # fix markup section
227
+ # if res["markup"]["links"] == [{}]
228
+ # res["markup"]["links"] = []
229
+ # else
230
+ # res["markup"]["links"] = res.markup.links.first.link
231
+ # res["markup"]["links"].each_with_index do |link, index|
232
+ # res["markup"]["links"][index]["targets"] = res["markup"]["links"][index]["target"]
233
+ # end
234
+ # end
235
+ # return res
236
+ # end
237
+ #
238
+ # # ResponseData modified from the rbing project https://raw.github.com/mikedemers/rbing/master/lib/rbing.rb
239
+ # class ResponseData < Hash
240
+ #
241
+ # def save(filename)
242
+ # File.open(filename, 'w') do |out|
243
+ # YAML.dump(self, out)
244
+ # end
245
+ # end
246
+ #
247
+ # private
248
+ #
249
+ # def initialize(data={})
250
+ # data.each_pair {|k,v| self[k.to_s] = deep_parse(v) }
251
+ # end
252
+ #
253
+ # def deep_parse(data)
254
+ # case data
255
+ # when Hash
256
+ # self.class.new(data)
257
+ # when Array
258
+ # data.map {|v| deep_parse(v) }
259
+ # else
260
+ # data
261
+ # end
262
+ # end
263
+ #
264
+ # def method_missing(*args)
265
+ # name = args[0].to_s
266
+ # res = nil
267
+ # if has_key? name
268
+ # res = self[name]
269
+ # else
270
+ # camelname = name.split('_').map {|w| "#{w[0,1].upcase}#{w[1..-1]}" }.join("")
271
+ # if has_key? camelname
272
+ # res = self[camelname]
273
+ # else
274
+ # super *args
275
+ # end
276
+ # end
277
+ # if res.nil?
278
+ # super *args
279
+ # else
280
+ # # Zemanta returns all final values as arrays... get rid of this so, for example
281
+ # # res.status = "ok" and not ["ok"]
282
+ # if res.is_a?(Array) && res.size == 1 && res.first.is_a?(String) == true
283
+ # return res.first
284
+ # else
285
+ # return res
286
+ # end
287
+ # end
288
+ # end
289
+ #
290
+ # end
291
+ #
292
+ # #
293
+ # class Parameters
294
+ # OPTION_KEYS = [:parameter, :description, :required, :possible_values, :default_value]
295
+ # OPTIONS = [
296
+ # [:method, "Method on the server", true, "zemanta.suggest", "zemanta.suggest"],
297
+ # [:api_key, "Your API key", true, "string", nil],
298
+ # [:text, "Input text (clear text or HTML)", true, "string", nil],
299
+ # [:format, "requested output format", true, ["xml", "json", "wnjson", "rdfxml"], "xml"],
300
+ # [:return_rdf_links, "return URIs of Linking Open Data entities", false, [0, 1], nil],
301
+ # [:return_categories, "categorize into specified categorization scheme", false, ["dmoz","partner ID"], "dmoz"],
302
+ # [:return_images, "return related images (default is yes) This can cause dramatic performance improvements", false, [0, 1], "yes"],
303
+ # [:return_keywords, "return keywords (default is yes) This can affect performance slightly positively", false, [0, 1], "yes"],
304
+ # [:emphasis, %(terms to "emphasise", even when not present in text. All related articles are then required to have this term.), false, "string", nil],
305
+ # [:text_title, "[NEW since August 2010] Title of the text you are sending. Helps the text understanding algorithm.", false, "string", nil],
306
+ # [:personal_scope, "return only personalized related articles and images", false, [0, 1], nil],
307
+ # [:markup_limit, "Number of in-text links to return (default: depending on the number of input words, 1 per each 10 words, and it maxes out at 10)", false, "number", 10],
308
+ # [:images_limit, "Number of images to return (default:24)", false, "number", 24],
309
+ # [:articles_limit, "Number of articles to return (default:10)", false, "number", 10],
310
+ # [:articles_max_age_days, "Maximum age of returned articles (default: no limit)", false, "number", nil],
311
+ # [:articles_highlight, "[NEW since August 2010] Should a highlighted search snippet for each article be returned, where available (default: no)", false, "number", 0],
312
+ # [:image_max_w, "Maximum image width (default: 300)", false, "number", 300],
313
+ # [:image_max_h, "Maximum image height (default: 300)", false, "number", 300],
314
+ # [:sourcefeed_ids, "ID for personalized related articles", false, nil],
315
+ # [:flickr_user_id, "flickr ID of the user", false, nil],
316
+ # [:pixie, "the chosen Zemanta signature icon", false, nil]
317
+ # ]
318
+ # end
319
+ #
320
+ # end