avvo_api 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/.gitignore ADDED
@@ -0,0 +1,4 @@
1
+ pkg/*
2
+ *.gem
3
+ .bundle
4
+ doc/*
data/Gemfile ADDED
@@ -0,0 +1,6 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in avvo_api.gemspec
4
+ gemspec
5
+
6
+ gem "rake"
data/Gemfile.lock ADDED
@@ -0,0 +1,31 @@
1
+ PATH
2
+ remote: .
3
+ specs:
4
+ avvo_api (0.1.0)
5
+ reactive_resource (~> 0.5.0)
6
+
7
+ GEM
8
+ remote: http://rubygems.org/
9
+ specs:
10
+ activeresource (2.3.10)
11
+ activesupport (= 2.3.10)
12
+ activesupport (2.3.10)
13
+ addressable (2.2.2)
14
+ crack (0.1.8)
15
+ rake (0.8.7)
16
+ reactive_resource (0.5.0)
17
+ activeresource (~> 2.3.10)
18
+ shoulda (2.11.3)
19
+ webmock (1.6.2)
20
+ addressable (>= 2.2.2)
21
+ crack (>= 0.1.7)
22
+
23
+ PLATFORMS
24
+ ruby
25
+
26
+ DEPENDENCIES
27
+ avvo_api!
28
+ rake
29
+ reactive_resource (~> 0.5.0)
30
+ shoulda (~> 2.11.3)
31
+ webmock (~> 1.6.1)
data/README.rdoc ADDED
@@ -0,0 +1,63 @@
1
+ = Avvo API Client
2
+
3
+ This gem provides an
4
+ {ActiveResource}[http://api.rubyonrails.org/classes/ActiveResource/Base.html]-based
5
+ client to information on {Avvo}[http://www.avvo.com], a directory of lawyers and loctors.
6
+
7
+ == Requirements
8
+
9
+ Apart from the gems installed as dependencies, this gem requires an
10
+ account on Avvo associated with an API key. Visit the {API
11
+ Documentation}[http://api.avvo.com] for details.
12
+
13
+ == Usage
14
+
15
+ Somewhere during your app's initialization, you should include the gem
16
+ and set it up with your Avvo credentials:
17
+
18
+ require 'avvo_api'
19
+ AvvoApi.setup('user@avvo.com', 'password')
20
+
21
+ For the most part, the models supplied by this gem should act like
22
+ ActiveRecord models. These models parallel the resources listed on
23
+ http://api.avvo.com, and everything accessible from the Avvo API is
24
+ accessible using this gem.
25
+
26
+ == Examples
27
+
28
+ Details about the specific information returned by these calls can be
29
+ found in the documentation at http://api.avvo.com. An example of using
30
+ the API in a command-line program can be found in the +examples+
31
+ subdirectory.
32
+
33
+ === Find a lawyer with a known ID
34
+
35
+ l = AvvoApi::Lawyer.find(28995)
36
+
37
+ === Find a lawyer based on known attributes, like email, zip code, etc.
38
+
39
+ l = AvvoApi::Lawyer.resolve(:name => 'Mark Britton', :zip_code => '98101')
40
+
41
+ === Search for lawyers matching a keyword in a specific location
42
+
43
+ AvvoApi::Lawyer.search(:q => 'criminal defense', :loc => 'seattle')
44
+
45
+ === Retrieve the headshot URL for a lawyer
46
+
47
+ AvvoApi::Lawyer.find(28995).headshot.headshot_url
48
+
49
+ or
50
+
51
+ AvvoApi::Headshot.find(:one, :params => {:lawyer_id => 28995}).headshot_url
52
+
53
+ === Getting a list of addresses for a doctor
54
+
55
+ addresses = AvvoApi::Doctor.find(1).addresses
56
+
57
+ or
58
+
59
+ addresses = AvvoApi::Address.find(:all, :params => {:doctor_id => doctor.id})
60
+
61
+ === Getting the main address for a doctor
62
+
63
+ main_address = AvvoApi::Address.main(:doctor_id => doctor.id)
data/Rakefile ADDED
@@ -0,0 +1,19 @@
1
+ require 'bundler'
2
+ require 'rake/testtask'
3
+ require 'rake/rdoctask'
4
+ Bundler::GemHelper.install_tasks
5
+
6
+ task :default => :test
7
+ task :build => :test
8
+
9
+ Rake::TestTask.new do |t|
10
+ t.libs << "test"
11
+ t.test_files = FileList['test/**/*_test.rb']
12
+ t.verbose = true
13
+ end
14
+
15
+ Rake::RDocTask.new do |rd|
16
+ rd.main = "README.rdoc"
17
+ rd.rdoc_files.include("README.rdoc", "lib/**/*.rb")
18
+ rd.rdoc_dir = 'doc'
19
+ end
data/avvo_api.gemspec ADDED
@@ -0,0 +1,25 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "avvo_api/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "avvo_api"
7
+ s.version = AvvoApi::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ["Justin Weiss"]
10
+ s.email = ["jweiss@avvo.com"]
11
+ s.homepage = "http://api.avvo.com"
12
+ s.summary = %q{An ActiveResource client to the Avvo API}
13
+ s.description = %q{An ActiveResource client to the Avvo API}
14
+
15
+ s.add_dependency "reactive_resource", '~> 0.5.0'
16
+ s.add_development_dependency "shoulda", '~> 2.11.3'
17
+ s.add_development_dependency "webmock", '~> 1.6.1'
18
+
19
+ s.rubyforge_project = "avvo_api"
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
@@ -0,0 +1,74 @@
1
+ #!/usr/bin/env ruby
2
+ #
3
+ # A command-line interface to the Avvo API, as an example of how the
4
+ # API can be used. Before using the API, you must create a YAML file
5
+ # in ~/.avvo containing your email and password.
6
+ require 'optparse'
7
+ require 'avvo_api'
8
+
9
+ professional_klass = nil
10
+ professional_param = nil
11
+
12
+ opts = OptionParser.new("Usage: avvo_cli.rb [options] ID")
13
+ opts.on("-l", "--lawyer", "Get details about a lawyer") { professional_klass = AvvoApi::Lawyer; professional_param = :lawyer_id }
14
+ opts.on("-d", "--doctor", "Get details about a doctor") { professional_klass = AvvoApi::Doctor; professional_param = :doctor_id }
15
+ rest = opts.parse ARGV
16
+
17
+ if !professional_klass
18
+ puts "You must specify either --lawyer or --doctor"
19
+ puts opts
20
+ exit(1)
21
+ elsif !rest.first
22
+ puts "You must specify the ID of the professional you are looking for"
23
+ puts opts
24
+ exit(1)
25
+ else
26
+ begin
27
+ config = YAML.load(File.read(File.expand_path("~/.avvo")))
28
+ rescue
29
+ puts "Please put your Avvo API credentials in ~/.avvo. This is a simple yaml file, which should look like:
30
+ email: email@domain.com
31
+ password: your_avvo_password"
32
+ exit(1)
33
+ end
34
+ AvvoApi.setup(config["email"], config["password"])
35
+ AvvoApi::Base.site = 'http://localhost.local:3000'
36
+
37
+ professional = professional_klass.find(rest.first)
38
+
39
+ address = AvvoApi::Address.main(professional_param => professional.id)
40
+ phones = address.phones
41
+ specialties = professional.specialties
42
+ reviews = professional.reviews
43
+
44
+ format = "%12s %s\n"
45
+ puts
46
+ printf format, "ID:", professional.id
47
+ printf format, "Name:", [professional.firstname, professional.middlename, professional.lastname].join(' ')
48
+ printf format, "Website:", professional.website_url if professional.website_url
49
+ printf format, "Profile URL:", professional.profile_url
50
+
51
+ printf format, "Address:", address.address_line1
52
+ printf format, "", address.address_line2 if address.address_line2
53
+ printf format, "", address.city + ", " + address.state + " " + address.postal_code
54
+
55
+ phones.each do |phone|
56
+ printf format, "#{phone.phone_type}:", phone.phone_number
57
+ end
58
+
59
+ specialties.each_with_index do |specialty, i|
60
+ header = i == 0 ? "Specialties:" : ""
61
+ printf format, header, "#{specialty.specialty_name.strip} (#{specialty.specialty_percent}%)"
62
+ end
63
+
64
+ puts
65
+ printf format, "Reviews ", ''
66
+ reviews.each do |review|
67
+ printf format, "Rating:", review.overall_rating
68
+ printf format, "Title:", review.title
69
+ printf format, "URL:", review.url
70
+ printf format, "By:", review.posted_by
71
+ puts
72
+ end
73
+
74
+ end
data/lib/avvo_api.rb ADDED
@@ -0,0 +1,28 @@
1
+ require 'avvo_api/base'
2
+ require 'avvo_api/professional_methods'
3
+
4
+ # The Avvo API Client. All API models live in this module.
5
+ module AvvoApi
6
+
7
+ autoload :Lawyer, 'avvo_api/lawyer'
8
+ autoload :Doctor, 'avvo_api/doctor'
9
+ autoload :School, 'avvo_api/school'
10
+ autoload :Address, 'avvo_api/address'
11
+ autoload :Phone, 'avvo_api/phone'
12
+ autoload :Language, 'avvo_api/language'
13
+ autoload :Specialty, 'avvo_api/specialty'
14
+ autoload :Headshot, 'avvo_api/headshot'
15
+ autoload :AdvancedTraining, 'avvo_api/advanced_training'
16
+ autoload :Review, 'avvo_api/review'
17
+
18
+ # Tells this client to use +email+ and +password+ to authenticate to
19
+ # the Avvo API.
20
+ def self.setup(email, password)
21
+ AvvoApi::Base.password = password
22
+ AvvoApi::Base.user = email
23
+ end
24
+ end
25
+
26
+ # Post parameters as <tt>{:lawyer => {...params...}}</tt> so the server
27
+ # can separate the object's params from the request params
28
+ ActiveResource::Base.include_root_in_json = true
@@ -0,0 +1,35 @@
1
+ # Represents an address. One of the following attributes MUST
2
+ # be set when using this model:
3
+ #
4
+ # * doctor_id
5
+ # * lawyer_id
6
+ #
7
+ # This model has the following attributes:
8
+ #
9
+ # * id
10
+ # * address_line1
11
+ # * address_line2
12
+ # * city
13
+ # * state
14
+ # * postal_code
15
+ # * latitude
16
+ # * longitude
17
+ #
18
+ class AvvoApi::Address < AvvoApi::Base
19
+ belongs_to :lawyer
20
+ belongs_to :doctor
21
+ has_many :phones
22
+
23
+ # Returns the 'main' address associated with the passed in
24
+ # professional. This is usually the address you want to
25
+ # use. +params+ is a hash of <tt>{:lawyer_id => lawyer.id}</tt> or
26
+ # <tt>{:doctor_id => doctor.id}</tt>
27
+ def self.main(params)
28
+ response = self.get(:main, params)
29
+ if response && response["id"]
30
+ new(params.merge(response))
31
+ elsif response && response["address"]
32
+ new(params.merge(response["address"]))
33
+ end
34
+ end
35
+ end
@@ -0,0 +1,35 @@
1
+ # Constants representing the possible values of the
2
+ # advanced_training_type_id parameter of AvvoApi::AdvancedTraining
3
+ module AvvoApi::AdvancedTrainingType
4
+
5
+ # Unknown training type
6
+ UNKNOWN = 1
7
+
8
+ # Represents an internship
9
+ INTERNSHIP = 2
10
+
11
+ # Represents a residency
12
+ RESIDENCY = 3
13
+
14
+ # Represents a fellowship
15
+ FELLOWSHIP = 4
16
+ end
17
+
18
+ # Represents advanced training, like residencies, for doctors. This
19
+ # model is only applicable to doctors. The following attributes MUST
20
+ # be set when using this model:
21
+ #
22
+ # * doctor_id
23
+ #
24
+ # This model has the following attributes:
25
+ #
26
+ # * id - The model's id
27
+ # * advanced_training_type_id - an AvvoApi::AdvancedTrainingType constant
28
+ # * specialty_name - The name of the specialty this advanced training is in
29
+ # * hospital_name - The normalized name of the hospital. This will be
30
+ # resolved by Avvo when it is set by this client.
31
+ # * graduation_date - The date this training was completed
32
+ #
33
+ class AvvoApi::AdvancedTraining < AvvoApi::Base
34
+ belongs_to :doctor
35
+ end
@@ -0,0 +1,18 @@
1
+ require 'reactive_resource'
2
+
3
+
4
+ module AvvoApi
5
+ # The class that all AvvoApi resources inherit from. This sets up the
6
+ # base URL and URL structure that the rest of the models use to hit
7
+ # Avvo.
8
+ class Base < ReactiveResource::Base
9
+
10
+ # The current version of the Avvo API
11
+ API_VERSION = 1
12
+
13
+ self.site = "https://api.avvo.com/"
14
+ self.prefix = "/api/#{API_VERSION}/"
15
+ self.format = :json
16
+
17
+ end
18
+ end
@@ -0,0 +1,22 @@
1
+ # Represents a doctor on Avvo. Attributes include:
2
+ #
3
+ # * id: The id of this doctor
4
+ # * firstname: the first name of this doctor
5
+ # * middlename: the middle name of this doctor
6
+ # * lastname: the last name of this doctor
7
+ # * suffix: the suffix of the doctor's name
8
+ # * avvo_rating: The doctor's Avvo Rating, from 0.0 to 10.0
9
+ # * email_address
10
+ # * website_url
11
+ # * profile_url
12
+ #
13
+ class AvvoApi::Doctor < AvvoApi::Base
14
+ has_many :addresses
15
+ has_many :reviews
16
+ has_many :schools
17
+ has_many :languages
18
+ has_many :specialties
19
+ has_many :advanced_trainings
20
+ has_one :headshot
21
+ include AvvoApi::ProfessionalMethods
22
+ end
@@ -0,0 +1,20 @@
1
+ # Represents a professional's headshot. Each professional only has one
2
+ # headshot, so finding a headshot should happen with the following call:
3
+ #
4
+ # AvvoApi::Headshot.find(:one, :lawyer_id => l.id)
5
+ #
6
+ # When using this model, one of the following attributes MUST be set:
7
+ #
8
+ # * doctor_id
9
+ # * lawyer_id
10
+ #
11
+ # This model has the following attribute:
12
+ #
13
+ # * headshot_url: The url to the standard-size headshot.
14
+ #
15
+ class AvvoApi::Headshot < AvvoApi::Base
16
+ singleton
17
+
18
+ belongs_to :lawyer
19
+ belongs_to :doctor
20
+ end
@@ -0,0 +1,16 @@
1
+ # Represents a language. One of the following attributes MUST
2
+ # be set when using this model:
3
+ #
4
+ # * doctor_id
5
+ # * lawyer_id
6
+ #
7
+ # This model has the following attributes:
8
+ #
9
+ # * id
10
+ # * name: The language name.
11
+ # * specialty_id: The language id. 'name' takes priority over this if both are set.
12
+ #
13
+ class AvvoApi::Language < AvvoApi::Base
14
+ belongs_to :lawyer
15
+ belongs_to :doctor
16
+ end
@@ -0,0 +1,20 @@
1
+ # Represents a lawyer on Avvo. Attributes include:
2
+ #
3
+ # * id: The id of this lawyer
4
+ # * firstname: the first name of this lawyer
5
+ # * middlename: the middle name of this lawyer
6
+ # * lastname: the last name of this lawyer
7
+ # * suffix: the suffix of the lawyer's name
8
+ # * email_address
9
+ # * website_url
10
+ #
11
+ class AvvoApi::Lawyer < AvvoApi::Base
12
+
13
+ has_many :addresses
14
+ has_many :reviews
15
+ has_many :schools
16
+ has_many :languages
17
+ has_many :specialties
18
+ has_one :headshot
19
+ include AvvoApi::ProfessionalMethods
20
+ end
@@ -0,0 +1,37 @@
1
+ # Constants representing the various values for +phone_type_id+ in AvvoApi::Phone
2
+ module AvvoApi::PhoneType
3
+
4
+ # There is no type specified for this number
5
+ UNKNOWN = 1
6
+
7
+ # This is an office number
8
+ OFFICE = 2
9
+
10
+ # This is a fax number
11
+ FAX = 3
12
+
13
+ # This is a mobile number
14
+ MOBILE = 4
15
+ end
16
+
17
+ # Represents a phone number tied to an address. One of the
18
+ # following attributes MUST be set when using this model:
19
+ #
20
+ # * doctor_id
21
+ # * lawyer_id
22
+ #
23
+ # Additionally, the following attribute MUST be set when using this model:
24
+ #
25
+ # * address_id
26
+ #
27
+ # This model has the following attributes:
28
+ #
29
+ # * id
30
+ # * phone_number: The phone number. Will be normalized by Avvo.
31
+ # * phone_type_id: The type of the phone number, as an AvvoApi::PhoneType
32
+ # constant. (Only applicable when creating or updating records)
33
+ # * phone_type: A string representation of the phone type
34
+ #
35
+ class AvvoApi::Phone < AvvoApi::Base
36
+ belongs_to :address
37
+ end