teachstreet 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,6 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
5
+ *.swp
6
+ rdoc/*
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in teachstreet.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2011 Scott Windsor & TeachStreet, Inc
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.
data/README.rdoc ADDED
@@ -0,0 +1,37 @@
1
+ = teachstreet-ruby
2
+
3
+ This is a Ruby client for the TeachStreet API
4
+
5
+ For the specific documentation on APIs (and the full list of parameters) see:
6
+
7
+ http://www.teachstreet.com/api/docs
8
+
9
+ == Usage
10
+
11
+ To create a new client, use your API key
12
+
13
+ >> client = Teachstreet.new('YOUR API KEY')
14
+
15
+ Then, make calls
16
+ >> listings = client.search_listings(:what => 'yoga', :where => 'Seattle, WA', :rpp => 1, :type => 'full')
17
+ => [#<Teachstreet::Listing:0x7f5be3e15028 @attrs={"average_rating"=>4, "subcategory"=>"Yoga", "price_aggregates"=>{"session_count"=>"1", "max_price"=>"78", "has_free"=>"0", "min_price"=>"78"}, "uri"=>"http://www.teachstreet.com:80/yoga/stay-young-with-yoga/li-3e1vivdvr4", "category"=>"Health & Fitness", "title"=>"Stay Young With YOGA", "listing_sessions"=>[{"location"=>{"lon"=>-122.28756, "address"=>"2811 Mt Rainier Dr S, Seattle, WA, 98144", "lat"=>47.577783}, "title"=>"Yoga for Re-charging", "price_amount"=>78.0, "id"=>"cl-kje72a8uao", "teacher_id"=>"us-1lanqsg9zk", "when"=>["March 09, 2011 - June 27, 2011", " 6:15 PM - 7:30 PM"], "date_created"=>Tue Jul 20 15:22:52 -0700 2010}], "id"=>"li-3e1vivdvr4", "owner_id"=>"us-1lanqsg9zk", "rating_count"=>28, "category_id"=>502, "img_url"=>"http://images2.teachst.com/image/view?e=cr-100-100&id=im-3d0uo54v3k&reference_id=ir-30x29hh1r4", "description"=>"Would you benefit from recharging? Yoga can help. \r\n\r\nReaching your full potential requires mental and physical flexibility. Whether tight muscles come from intense athletic performance or from sitting at a desk all day, inflexibility limits your health, zaps your energy and constrains your freedom of movement. Yoga postures will inform you about which muscles are storing tension and about how to release them. And in this yoga class, you'll practice the body's natural mechanism for moving from anxiety to relaxation, deep breathing \342\200\223 and gain the bi-product of relaxing - mental flexibility. \r\nThis class is especially for \342\200\230baby-boomers, people without yoga training, & yoga veterans wanting a heart-centered experience, this class is accessible to everyone but deep in its impact. You\342\200\231ll be stretched and strengthened, your ability to focus will be enhanced and you\342\200\231ll come away feeling rejuvenated and ready to continue your day with new gusto. And you\342\200\231ll benefit from the side-effect of this practice, an upping of serotonin levels which boosts happiness! \r\nCertified Kripalu teacher. \r\n\r\n", "subcategory_id"=>514, "date_created"=>Tue Mar 03 13:40:26 -0800 2009}]
18
+ >> listings.first.title
19
+ => "Stay Young With YOGA"
20
+ >> listings.first.listing_sessions.first
21
+ => #<Teachstreet::ListingSession:0x7f5be3dba2e0 @attrs={"location"=>{"lon"=>-122.28756, "address"=>"2811 Mt Rainier Dr S, Seattle, WA, 98144", "lat"=>47.577783}, "title"=>"Yoga for Re-charging", "price_amount"=>78.0, "id"=>"cl-kje72a8uao", "teacher_id"=>"us-1lanqsg9zk", "when"=>["March 09, 2011 - June 27, 2011", " 6:15 PM - 7:30 PM"], "date_created"=>Tue Jul 20 15:22:52 -0700 2010}
22
+
23
+ JSON results are deserialized into classes: Listing, ListingSession, Location, Deal, Category, Subcategory, & PriceAggregates
24
+
25
+ == Note on Patches/Pull Requests
26
+
27
+ * Fork the project.
28
+ * Make your feature addition or bug fix.
29
+ * Add tests for it. This is important so I don't break it in a
30
+ future version unintentionally.
31
+ * Commit, do not mess with rakefile, version, or history.
32
+ (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
33
+ * Send me a pull request. Bonus points for topic branches.
34
+
35
+ == Copyright
36
+
37
+ Copyright (c) 2011 Scott Windsor & TeachStreet, Inc. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,23 @@
1
+ require 'bundler'
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require 'rspec/core/rake_task'
5
+
6
+ RSpec::Core::RakeTask.new('spec')
7
+
8
+ # If you want to make this the default task
9
+ task :default => :spec
10
+
11
+ gem 'hanna'
12
+ require 'hanna/rdoctask'
13
+
14
+ Rake::RDocTask.new do |rdoc|
15
+ version = File.exist?('VERSION') ? File.read('VERSION') : ""
16
+
17
+ rdoc.rdoc_dir = 'rdoc'
18
+ rdoc.title = "teachstreet #{version}"
19
+ rdoc.rdoc_files.include('README*')
20
+ rdoc.rdoc_files.include('LICENSE')
21
+ rdoc.rdoc_files.include('lib/**/*.rb')
22
+
23
+ end
@@ -0,0 +1,3 @@
1
+ module Teachstreet
2
+ VERSION = "0.0.1"
3
+ end
@@ -0,0 +1,148 @@
1
+ require 'httparty'
2
+ require 'facets/string'
3
+ require 'facets/memoizable'
4
+
5
+ module Teachstreet
6
+
7
+ class Error < StandardError
8
+ attr_reader :message, :code
9
+
10
+ def initialize(body)
11
+ parsed = Crack::XML.parse(body)
12
+ if parsed['wsvError']
13
+ @message = parsed['wsvError']['message']
14
+ @code = parsed['wsvError']['code']
15
+ end
16
+ end
17
+
18
+ def to_s
19
+ "#{code}: #{message}"
20
+ end
21
+
22
+ end
23
+
24
+ class Result
25
+ include Memoizable
26
+
27
+ def self.has_one(attr_name)
28
+ attr_sym = attr_name.to_sym
29
+ attr_string = attr_name.to_s
30
+ define_method attr_sym do
31
+ if @attrs.key?(attr_string)
32
+ Teachstreet.const_get(attr_string.camelcase).new(@attrs[attr_string])
33
+ end
34
+ end
35
+ memoize attr_sym
36
+ end
37
+
38
+ def self.has_many(attr_name)
39
+ attr_sym = attr_name.to_sym
40
+ attr_string = attr_name.to_s
41
+ define_method attr_sym do
42
+ if @attrs.key?(attr_string)
43
+ @attrs[attr_string].map do |a|
44
+ Teachstreet.const_get(attr_string.gsub(/s$/i, '').camelcase).new(a)
45
+ end
46
+ end
47
+ end
48
+ memoize attr_sym
49
+ end
50
+
51
+ def initialize(attrs = {})
52
+ @attrs = attrs
53
+ (class << self; self; end).class_eval do
54
+ attrs.keys.each do |key|
55
+ if (!method_defined?(key) || key.to_s == 'id')
56
+ define_method key.to_sym do
57
+ @attrs[key]
58
+ end
59
+ end # end if
60
+ end # end each
61
+ end # end class_eval
62
+ end
63
+ end
64
+
65
+ class Category < Result
66
+ end
67
+
68
+ class Subcategory < Result
69
+ end
70
+
71
+ class Listing < Result
72
+ has_many :listing_sessions
73
+ has_one :price_aggregates
74
+ end
75
+
76
+ class PriceAggregates < Result
77
+ end
78
+
79
+ class ListingSession < Result
80
+ has_one :location
81
+ end
82
+
83
+ class Location < Result
84
+ end
85
+
86
+ class Deal < Result
87
+ end
88
+
89
+ class Client
90
+ include HTTParty
91
+
92
+ base_uri 'api.teachstreet.com'
93
+ format :json
94
+
95
+ # create a new client with your API key
96
+ def initialize(api_key)
97
+ self.class.default_params :wsvKey => api_key
98
+ end
99
+
100
+ # search listings local & online classes
101
+ def search_listings(options={})
102
+ process(self.class.get("/search/listings", :query => options)).map do |l|
103
+ Listing.new(l)
104
+ end
105
+ end
106
+
107
+ # look up a listing by id
108
+ def listing(id, options={})
109
+ Listing.new(process(self.class.get("/listing", :query => {:id => id}.merge(options))))
110
+ end
111
+
112
+ # find all categories
113
+ def categories
114
+ process(self.class.get("/categories")).map do |c|
115
+ Category.new(c)
116
+ end
117
+ end
118
+
119
+ # find all subscategories, or substring search by name
120
+ def subcategories(options = {})
121
+ process(self.class.get("/subcategories", :query => options)).map do |c|
122
+ Subcategory.new(c)
123
+ end
124
+ end
125
+
126
+ # find all deals
127
+ def deals(options ={})
128
+ process(self.class.get("/deals", :query => options))['deals'].map do |c|
129
+ Deal.new(c)
130
+ end
131
+ end
132
+
133
+ # look up deal by id
134
+ def deal(id, options={})
135
+ Deal.new(process(self.class.get("/deal/#{id}", options))["deal"])
136
+ end
137
+
138
+ private
139
+
140
+ def process(result)
141
+ if result.response.code == "200"
142
+ result.parsed_response
143
+ else
144
+ raise Teachstreet::Error, result.body
145
+ end
146
+ end
147
+ end
148
+ end
data/spec/api_key.rb ADDED
@@ -0,0 +1,3 @@
1
+ module Teachstreet
2
+ API_KEY = 'YOUR API KEY' # replace for testing
3
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'bundler/setup'
3
+
4
+ require 'lib/teachstreet'
5
+
6
+ RSpec.configure do |config|
7
+ # some (optional) config here
8
+ end
@@ -0,0 +1,130 @@
1
+ require 'spec_helper'
2
+ require 'api_key'
3
+
4
+ describe Teachstreet do
5
+ before(:all) do
6
+ @client = Teachstreet::Client.new(Teachstreet::API_KEY)
7
+ end
8
+
9
+ it "lists all categories" do
10
+ result = @client.categories
11
+ result.should_not be_empty
12
+ result.first.name.should_not be_nil
13
+ result.first.url.should_not be_nil
14
+ result.first.id.should_not be_nil
15
+ end
16
+
17
+ it "lists all subcategories" do
18
+ result = @client.subcategories
19
+ result.should_not be_empty
20
+ result.first.name.should_not be_nil
21
+ result.first.url.should_not be_nil
22
+ result.first.id.should_not be_nil
23
+ end
24
+
25
+ it "list all subscategories for location" do
26
+ result = @client.subcategories(:where => 'Seattle, WA')
27
+ result.should_not be_empty
28
+ result.first.name.should_not be_nil
29
+ result.first.url.should_not be_nil
30
+ result.first.url.should match("seattle")
31
+ result.first.id.should_not be_nil
32
+ end
33
+
34
+ it "search for subcategory" do
35
+ result = @client.subcategories(:name => 'Programming')
36
+ result.should_not be_empty
37
+ result.first.name.should eql("Programming")
38
+ result.first.id.should eql(303)
39
+ result.first.url.should match("/programming/online-classes/303")
40
+ end
41
+
42
+ it "basic search listings for yoga in Seattle" do
43
+ result = @client.search_listings(:what => 'yoga', :where => 'Seattle, WA')
44
+ result.should_not be_empty
45
+ listing = result.first
46
+ listing.id.should_not be_nil
47
+ listing.title.should_not be_nil
48
+ listing.subcategory.should_not be_nil
49
+ listing.subcategory_id.should_not be_nil
50
+ listing.category.should_not be_nil
51
+ listing.category_id.should_not be_nil
52
+ listing.owner_id.should_not be_nil
53
+ listing.description.should_not be_nil
54
+ price_aggregates = listing.price_aggregates
55
+ price_aggregates.should_not be_nil
56
+ price_aggregates.should be_kind_of Teachstreet::PriceAggregates
57
+ price_aggregates.session_count.should_not be_nil
58
+ price_aggregates.max_price.should_not be_nil
59
+ price_aggregates.min_price.should_not be_nil
60
+ price_aggregates.has_free.should_not be_nil
61
+ end
62
+
63
+ it "full search listings for yoga in Seattle" do
64
+ result = @client.search_listings(:type => 'full', :what => 'yoga', :where => 'Seattle, WA')
65
+ result.should_not be_empty
66
+ listing = result.first
67
+ listing.id.should_not be_nil
68
+ listing.title.should_not be_nil
69
+ listing.subcategory.should_not be_nil
70
+ listing.subcategory_id.should_not be_nil
71
+ listing.category.should_not be_nil
72
+ listing.category_id.should_not be_nil
73
+ listing.owner_id.should_not be_nil
74
+ listing.description.should_not be_nil
75
+ listing.listing_sessions.should_not be_empty
76
+ listing_session = listing.listing_sessions.first
77
+ listing_session.should be_kind_of Teachstreet::ListingSession
78
+ listing_session.id.should_not be_nil
79
+ listing_session.title.should_not be_nil
80
+ listing_session.teacher_id.should_not be_nil
81
+ listing_session.location.should_not be_nil
82
+ location = listing_session.location
83
+ location.should be_kind_of Teachstreet::Location
84
+ price_aggregates = listing.price_aggregates
85
+ price_aggregates.should_not be_nil
86
+ price_aggregates.should be_kind_of Teachstreet::PriceAggregates
87
+ price_aggregates.session_count.should_not be_nil
88
+ price_aggregates.max_price.should_not be_nil
89
+ price_aggregates.min_price.should_not be_nil
90
+ price_aggregates.has_free.should_not be_nil
91
+ end
92
+
93
+ it "find basic listing by id" do
94
+ result = @client.search_listings(:what => 'yoga', :where => 'Seattle, WA')
95
+ result.should_not be_empty
96
+ listing = result.first
97
+ listing.id.should_not be_nil
98
+ listing = @client.listing(listing.id)
99
+ listing.should_not be_nil
100
+ listing.id.should_not be_nil
101
+ listing.title.should_not be_nil
102
+ end
103
+
104
+ it "find full listing by id" do
105
+ result = @client.search_listings(:what => 'yoga', :where => 'Seattle, WA')
106
+ result.should_not be_empty
107
+ listing = result.first
108
+ listing.id.should_not be_nil
109
+ listing = @client.listing(listing.id, :type => 'full')
110
+ listing.should_not be_nil
111
+ listing.id.should_not be_nil
112
+ listing.title.should_not be_nil
113
+ end
114
+
115
+ it "find all deals" do
116
+ deals = @client.deals
117
+ deals.should_not be_empty
118
+ deal = deals.first
119
+ deal.id.should_not be_nil
120
+ end
121
+
122
+ it "find deal by id" do
123
+ deals = @client.deals
124
+ deals.should_not be_empty
125
+ deal = @client.deal(deals.first.id)
126
+ deal.should_not be_nil
127
+ deal.id.should_not be_nil
128
+ end
129
+
130
+ end
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "teachstreet/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "teachstreet"
7
+ s.version = Teachstreet::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Scott Windsor"]
10
+ s.email = ["swindsor@teachstreet.com"]
11
+ s.homepage = "http://github.com/TeachStreet/teachstreet-ruby"
12
+ s.summary = %q{Client library for accessing TeachStreet's APIs}
13
+ s.description = %q{Client library for accessing TeachSTreet's APIs. Uses httparty for parsing.}
14
+
15
+ s.add_dependency("httparty", [">= 0.7.4"])
16
+ s.add_dependency("facets", [">= 2.9.1"])
17
+ s.add_development_dependency "rspec"
18
+ s.add_development_dependency "rdoc"
19
+ s.add_development_dependency "hanna"
20
+
21
+ s.files = `git ls-files`.split("\n")
22
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
23
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
24
+ s.require_paths = ["lib"]
25
+ end
metadata ADDED
@@ -0,0 +1,151 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: teachstreet
3
+ version: !ruby/object:Gem::Version
4
+ hash: 29
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 0
9
+ - 1
10
+ version: 0.0.1
11
+ platform: ruby
12
+ authors:
13
+ - Scott Windsor
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2011-04-11 00:00:00 -07:00
19
+ default_executable:
20
+ dependencies:
21
+ - !ruby/object:Gem::Dependency
22
+ name: httparty
23
+ prerelease: false
24
+ requirement: &id001 !ruby/object:Gem::Requirement
25
+ none: false
26
+ requirements:
27
+ - - ">="
28
+ - !ruby/object:Gem::Version
29
+ hash: 11
30
+ segments:
31
+ - 0
32
+ - 7
33
+ - 4
34
+ version: 0.7.4
35
+ type: :runtime
36
+ version_requirements: *id001
37
+ - !ruby/object:Gem::Dependency
38
+ name: facets
39
+ prerelease: false
40
+ requirement: &id002 !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ">="
44
+ - !ruby/object:Gem::Version
45
+ hash: 41
46
+ segments:
47
+ - 2
48
+ - 9
49
+ - 1
50
+ version: 2.9.1
51
+ type: :runtime
52
+ version_requirements: *id002
53
+ - !ruby/object:Gem::Dependency
54
+ name: rspec
55
+ prerelease: false
56
+ requirement: &id003 !ruby/object:Gem::Requirement
57
+ none: false
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ hash: 3
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ type: :development
66
+ version_requirements: *id003
67
+ - !ruby/object:Gem::Dependency
68
+ name: rdoc
69
+ prerelease: false
70
+ requirement: &id004 !ruby/object:Gem::Requirement
71
+ none: false
72
+ requirements:
73
+ - - ">="
74
+ - !ruby/object:Gem::Version
75
+ hash: 3
76
+ segments:
77
+ - 0
78
+ version: "0"
79
+ type: :development
80
+ version_requirements: *id004
81
+ - !ruby/object:Gem::Dependency
82
+ name: hanna
83
+ prerelease: false
84
+ requirement: &id005 !ruby/object:Gem::Requirement
85
+ none: false
86
+ requirements:
87
+ - - ">="
88
+ - !ruby/object:Gem::Version
89
+ hash: 3
90
+ segments:
91
+ - 0
92
+ version: "0"
93
+ type: :development
94
+ version_requirements: *id005
95
+ description: Client library for accessing TeachSTreet's APIs. Uses httparty for parsing.
96
+ email:
97
+ - swindsor@teachstreet.com
98
+ executables: []
99
+
100
+ extensions: []
101
+
102
+ extra_rdoc_files: []
103
+
104
+ files:
105
+ - .gitignore
106
+ - Gemfile
107
+ - LICENSE
108
+ - README.rdoc
109
+ - Rakefile
110
+ - lib/teachstreet.rb
111
+ - lib/teachstreet/version.rb
112
+ - spec/api_key.rb
113
+ - spec/spec_helper.rb
114
+ - spec/teachstreet_spec.rb
115
+ - teachstreet.gemspec
116
+ has_rdoc: true
117
+ homepage: http://github.com/TeachStreet/teachstreet-ruby
118
+ licenses: []
119
+
120
+ post_install_message:
121
+ rdoc_options: []
122
+
123
+ require_paths:
124
+ - lib
125
+ required_ruby_version: !ruby/object:Gem::Requirement
126
+ none: false
127
+ requirements:
128
+ - - ">="
129
+ - !ruby/object:Gem::Version
130
+ hash: 3
131
+ segments:
132
+ - 0
133
+ version: "0"
134
+ required_rubygems_version: !ruby/object:Gem::Requirement
135
+ none: false
136
+ requirements:
137
+ - - ">="
138
+ - !ruby/object:Gem::Version
139
+ hash: 3
140
+ segments:
141
+ - 0
142
+ version: "0"
143
+ requirements: []
144
+
145
+ rubyforge_project:
146
+ rubygems_version: 1.4.1
147
+ signing_key:
148
+ specification_version: 3
149
+ summary: Client library for accessing TeachStreet's APIs
150
+ test_files: []
151
+