avvo_api 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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