apartment_ratings 0.0.1 → 1.0.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/Gemfile CHANGED
@@ -1,7 +1,9 @@
1
1
  source 'http://rubygems.org'
2
2
 
3
- gem 'hashie', git: 'https://github.com/intridea/hashie.git', branch: :master
3
+ gem 'hashie', '~> 3.3.1'
4
+ gem 'tnt', '~> 0.1.0'
4
5
  gem 'faraday', '~> 0.9.0'
6
+ gem 'faraday_middleware', '~> 0.9.0'
5
7
 
6
8
  group :development do
7
9
  gem 'pry'
@@ -1,10 +1,3 @@
1
- GIT
2
- remote: https://github.com/intridea/hashie.git
3
- revision: 8b4ffbd6aa2ff9e6aeccd8181c82a85ffd1eea7a
4
- branch: master
5
- specs:
6
- hashie (3.1.1)
7
-
8
1
  GEM
9
2
  remote: http://rubygems.org/
10
3
  specs:
@@ -18,6 +11,8 @@ GEM
18
11
  docile (1.1.5)
19
12
  faraday (0.9.0)
20
13
  multipart-post (>= 1.2, < 3)
14
+ faraday_middleware (0.9.1)
15
+ faraday (>= 0.7.4, < 0.10)
21
16
  git (1.2.7)
22
17
  github_api (0.11.3)
23
18
  addressable (~> 2.3)
@@ -27,6 +22,7 @@ GEM
27
22
  multi_json (>= 1.7.5, < 2.0)
28
23
  nokogiri (~> 1.6.0)
29
24
  oauth2
25
+ hashie (3.3.1)
30
26
  highline (1.6.21)
31
27
  jeweler (2.0.1)
32
28
  builder
@@ -92,6 +88,7 @@ GEM
92
88
  simplecov-html (0.8.0)
93
89
  slop (3.5.0)
94
90
  thread_safe (0.3.4)
91
+ tnt (0.1.0)
95
92
 
96
93
  PLATFORMS
97
94
  ruby
@@ -99,7 +96,8 @@ PLATFORMS
99
96
  DEPENDENCIES
100
97
  bundler (~> 1.0)
101
98
  faraday (~> 0.9.0)
102
- hashie!
99
+ faraday_middleware (~> 0.9.0)
100
+ hashie (~> 3.3.1)
103
101
  jeweler (~> 2.0.1)
104
102
  pry
105
103
  rdoc (~> 3.12)
@@ -107,3 +105,4 @@ DEPENDENCIES
107
105
  rspec (~> 3.0)
108
106
  rubocop (>= 0.21.0)
109
107
  simplecov
108
+ tnt (~> 0.1.0)
data/README.md CHANGED
@@ -1,5 +1,7 @@
1
1
  # ApartmentRatings [![Build Status](https://travis-ci.org/gregory/apartment_ratings.svg)](https://travis-ci.org/gregory/apartment_ratings)
2
2
 
3
+ ## THIS IS A WIP, WATING FOR CREDENTIALS TO TEST :)
4
+
3
5
  Description goes here.
4
6
 
5
7
  ## Contributing to apartment_ratings
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.1
1
+ 1.0.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "apartment_ratings"
8
- s.version = "0.0.1"
8
+ s.version = "1.0.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["gregory"]
12
- s.date = "2014-07-08"
12
+ s.date = "2014-09-25"
13
13
  s.description = "Ruby client for ApartmentRating API"
14
14
  s.email = "greg2502@gmail.com"
15
15
  s.extra_rdoc_files = [
@@ -33,6 +33,7 @@ Gem::Specification.new do |s|
33
33
  "lib/apartment_ratings/client.rb",
34
34
  "lib/apartment_ratings/complex.rb",
35
35
  "lib/apartment_ratings/configuration.rb",
36
+ "lib/apartment_ratings/errors.rb",
36
37
  "lib/apartment_ratings/review.rb",
37
38
  "lib/apartment_ratings/reviews/rating.rb",
38
39
  "lib/apartment_ratings/reviews/response.rb",
@@ -43,6 +44,7 @@ Gem::Specification.new do |s|
43
44
  "spec/apartment_ratings/reviews/rating_spec.rb",
44
45
  "spec/apartment_ratings/reviews/response_spec.rb",
45
46
  "spec/apartment_ratings_spec.rb",
47
+ "spec/spec.yml.sample",
46
48
  "spec/spec_helper.rb"
47
49
  ]
48
50
  s.homepage = "http://github.com/gregory/apartment_ratings"
@@ -55,8 +57,10 @@ Gem::Specification.new do |s|
55
57
  s.specification_version = 3
56
58
 
57
59
  if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
58
- s.add_runtime_dependency(%q<hashie>, [">= 0"])
60
+ s.add_runtime_dependency(%q<hashie>, ["~> 3.3.1"])
61
+ s.add_runtime_dependency(%q<tnt>, ["~> 0.1.0"])
59
62
  s.add_runtime_dependency(%q<faraday>, ["~> 0.9.0"])
63
+ s.add_runtime_dependency(%q<faraday_middleware>, ["~> 0.9.0"])
60
64
  s.add_development_dependency(%q<pry>, [">= 0"])
61
65
  s.add_development_dependency(%q<rr>, ["~> 1.1.2"])
62
66
  s.add_development_dependency(%q<rspec>, ["~> 3.0"])
@@ -66,8 +70,10 @@ Gem::Specification.new do |s|
66
70
  s.add_development_dependency(%q<simplecov>, [">= 0"])
67
71
  s.add_development_dependency(%q<rubocop>, [">= 0.21.0"])
68
72
  else
69
- s.add_dependency(%q<hashie>, [">= 0"])
73
+ s.add_dependency(%q<hashie>, ["~> 3.3.1"])
74
+ s.add_dependency(%q<tnt>, ["~> 0.1.0"])
70
75
  s.add_dependency(%q<faraday>, ["~> 0.9.0"])
76
+ s.add_dependency(%q<faraday_middleware>, ["~> 0.9.0"])
71
77
  s.add_dependency(%q<pry>, [">= 0"])
72
78
  s.add_dependency(%q<rr>, ["~> 1.1.2"])
73
79
  s.add_dependency(%q<rspec>, ["~> 3.0"])
@@ -78,8 +84,10 @@ Gem::Specification.new do |s|
78
84
  s.add_dependency(%q<rubocop>, [">= 0.21.0"])
79
85
  end
80
86
  else
81
- s.add_dependency(%q<hashie>, [">= 0"])
87
+ s.add_dependency(%q<hashie>, ["~> 3.3.1"])
88
+ s.add_dependency(%q<tnt>, ["~> 0.1.0"])
82
89
  s.add_dependency(%q<faraday>, ["~> 0.9.0"])
90
+ s.add_dependency(%q<faraday_middleware>, ["~> 0.9.0"])
83
91
  s.add_dependency(%q<pry>, [">= 0"])
84
92
  s.add_dependency(%q<rr>, ["~> 1.1.2"])
85
93
  s.add_dependency(%q<rspec>, ["~> 3.0"])
@@ -1,4 +1,5 @@
1
1
  require 'hashie'
2
+ require 'tnt'
2
3
 
3
4
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), 'apartment_ratings'))
4
5
 
@@ -8,6 +9,7 @@ module ApartmentRatings
8
9
  autoload :Address, 'address'
9
10
  autoload :Complex, 'complex'
10
11
  autoload :Review, 'review'
12
+ autoload :Errors, 'errors'
11
13
 
12
14
  module Reviews
13
15
  autoload :Rating, 'reviews/rating'
@@ -22,12 +24,44 @@ module ApartmentRatings
22
24
  @config = Configuration.new.tap { |configuration| yield(configuration) }
23
25
  end
24
26
 
27
+ def self.credentials
28
+ if config.nil?
29
+ fail InvalidConfig
30
+ else
31
+ config.select { |key, _| [:username, :password].include?(key) }
32
+ end
33
+ end
34
+
25
35
  def self.client
26
- options = {
27
- username: config.username,
28
- password: config.password,
29
- api_base_path: config.api_base_path
36
+ @client ||= begin
37
+ fail Errors::InvalidConfig if config.nil?
38
+ options = {
39
+ api_base_path: config.api_base_path
40
+ }
41
+ Client.new(options)
42
+ end
43
+ end
44
+
45
+ def self.post(url = nil, params = {}, headers = nil, errors_opts = { token: 0 }, &block)
46
+ payload = default_params.merge(params)
47
+ json_result = client.connection.post(url, payload, headers).body
48
+ result = JSON.parse json_result
49
+
50
+ if !result['errors'].nil? && !result['errors']['serviceToken'].nil?
51
+ # Mostlikely the token expired, lets try to refresh it
52
+ fail Errors::InvalidToken unless errors_opts[:token] < ApartmentRatings.config.max_token_retry
53
+
54
+ client.refresh_token
55
+ return post(url, params, headers, { token: (errors_opts[:token] + 1) }, &block)
56
+ else
57
+ block.call(result)
58
+ end
59
+ end
60
+
61
+ def self.default_params
62
+ {
63
+ serviceToken: client.token,
64
+ username: credentials[:username]
30
65
  }
31
- Client.new(options)
32
66
  end
33
67
  end
@@ -1,5 +1,7 @@
1
1
  module ApartmentRatings
2
2
  class Address < Hashie::Trash
3
+ include Hashie::Extensions::IndifferentAccess
4
+
3
5
  property :full_address
4
6
 
5
7
  def self.coerce(raw_address)
@@ -1,31 +1,38 @@
1
1
  require 'faraday'
2
+ require 'faraday_middleware'
2
3
 
3
4
  module ApartmentRatings
4
5
  class Client
6
+ attr_reader :connection
7
+
5
8
  def initialize(options = {})
6
9
  path = options.fetch(:api_base_path)
7
- params = {
8
- username: options.fetch(:username),
9
- password: options.fetch(:password)
10
- }
11
10
 
12
- @client = Faraday.new(path, params) do |faraday|
13
- faraday.response :json, content_type: /\bjson\z/
11
+ @connection = Faraday.new(path) do |faraday|
12
+ faraday.request :url_encoded # Unfortunately, we need to encode post and put params
13
+ faraday.request :json
14
+
15
+ # NOTE: Unfortunately, the response content type is not json... But we know it is.
16
+ faraday.response :json, content_type: /\Atext\/html;charset=ISO-8859-1\z/
14
17
  faraday.response :logger if ApartmentRatings.config.debug
15
18
 
16
19
  faraday.adapter ApartmentRatings.config.faraday_adapter || Faraday.default_adapter
17
20
  end
18
21
  end
19
22
 
20
- def complexes
21
- result = @client.get('index')
22
- # TODO: store the result and hangle unsuccessful response
23
- result['complexes'].map { |complex_json| Complex.new complex_json }
23
+ def token
24
+ @token ||= refresh_token
24
25
  end
25
26
 
26
- def complex(id)
27
- result = @client.get('complex', complexId: id)
28
- Complex.new result
27
+ def refresh_token
28
+ @token = nil
29
+ result = JSON.parse @connection.post('login', ApartmentRatings.credentials.merge(format: 'json')).body
30
+
31
+ if result['success']
32
+ @token = result['response']
33
+ else
34
+ fail Errors::InvalidToken
35
+ end
29
36
  end
30
37
  end
31
38
  end
@@ -1,5 +1,6 @@
1
1
  module ApartmentRatings
2
2
  class Complex < Hashie::Trash
3
+ include Hashie::Extensions::IndifferentAccess
3
4
  include Hashie::Extensions::IgnoreUndeclared
4
5
  include Hashie::Extensions::Coercion
5
6
 
@@ -8,6 +9,7 @@ module ApartmentRatings
8
9
  property :address, from: :propertyAddress
9
10
  property :propertyAddress
10
11
  property :feedUrl
12
+ property :url, from: :propertyUrl
11
13
 
12
14
  property :apartmentRating
13
15
  property :averageRating
@@ -17,5 +19,26 @@ module ApartmentRatings
17
19
  coerce_key :address, Address
18
20
  coerce_key :averageRating, Hash[String => Reviews::Rating]
19
21
  coerce_key :reviews, Set[Review]
22
+
23
+ def self.all
24
+ ApartmentRatings.post('index') do |result|
25
+ if result['success']
26
+ result['complexes'].map { |complex_json| new complex_json }
27
+ else
28
+ fail StandardError
29
+ end
30
+ end
31
+ end
32
+
33
+ def self.find(id)
34
+ ApartmentRatings.post('complex', complexId: id) do |result|
35
+ if result['success']
36
+ default_options = { id: id }
37
+ new default_options.merge(result)
38
+ else
39
+ fail Errors::InvalidComplexId.new(id, result['errorMessage'])
40
+ end
41
+ end
42
+ end
20
43
  end
21
44
  end
@@ -2,12 +2,17 @@ module ApartmentRatings
2
2
  class Configuration < Hashie::Dash
3
3
  DEFAULTS = {
4
4
  format: 'json',
5
+ debug: false,
5
6
  api_base_path: 'https://services.apartmentratings.com/services/rms/v1/',
6
- hours_before_token_expiration: 48
7
+ hours_before_token_expiration: 48,
8
+ max_token_retry: 2
7
9
  }.freeze
8
10
 
9
11
  property :username
10
12
  property :password
13
+ property :debug, default: DEFAULTS[:debug]
14
+ property :faraday_adapter
15
+ property :max_token_retry, default: DEFAULTS[:max_token_retry]
11
16
  property :format, default: DEFAULTS[:format]
12
17
  property :api_base_path, default: DEFAULTS[:api_base_path]
13
18
  property :hours_before_token_expiration, default: DEFAULTS[:hours_before_token_expiration]
@@ -0,0 +1,19 @@
1
+ module ApartmentRatings
2
+ module Errors
3
+ InvalidToken = Tnt.boom do
4
+ credentials = ApartmentRatings.credentials.map { |k, v| "#{k} => #{v}" }.join(', ')
5
+ "Unable to retrieve token for the following credentials: #{credentials}"
6
+ end
7
+
8
+ InvalidConfig = Tnt.boom do
9
+ %s(
10
+ Please provide valid credentials. Ex:
11
+ > ApartmentRatings.configure { |c| c.username = 'username'; c.password= 'bar'; }
12
+ )
13
+ end
14
+
15
+ InvalidComplexId = Tnt.boom do |id, msg|
16
+ "Invalid Complex id (#{id}) : #{msg}"
17
+ end
18
+ end
19
+ end
@@ -1,5 +1,6 @@
1
1
  module ApartmentRatings
2
2
  class Review < Hashie::Trash
3
+ include Hashie::Extensions::IndifferentAccess
3
4
  include Hashie::Extensions::Coercion
4
5
 
5
6
  property :datePosted
@@ -7,6 +8,7 @@ module ApartmentRatings
7
8
  property :responses
8
9
  property :author, from: :reviewerScreenName
9
10
  property :rating, from: :starRatings
11
+ property :updated_at, from: :lastUpdatedDate
10
12
  property :url
11
13
 
12
14
  coerce_key :responses, Set[Reviews::Response]
@@ -1,6 +1,7 @@
1
1
  module ApartmentRatings
2
2
  module Reviews
3
3
  class Rating < Hashie::Trash
4
+ include Hashie::Extensions::IndifferentAccess
4
5
  property :value
5
6
 
6
7
  def self.coerce(raw_rating)
@@ -0,0 +1,3 @@
1
+ credentials:
2
+ username: foo@bar.com
3
+ password: password
@@ -19,6 +19,7 @@ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
19
19
  $LOAD_PATH.unshift(File.dirname(__FILE__))
20
20
 
21
21
  require 'rspec'
22
+ require 'yaml'
22
23
  require 'apartment_ratings'
23
24
 
24
25
  # Requires supporting files with custom matchers and macros, etc,
@@ -27,7 +28,15 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
27
28
 
28
29
  RSpec.configure do |config|
29
30
  config.before :suite do
30
- ApartmentRatings.configure do
31
+ ApartmentRatings.configure do |conf|
32
+ credentials = settings['credentials']
33
+
34
+ conf.username = credentials['username']
35
+ conf.password = credentials['password']
31
36
  end
32
37
  end
38
+
39
+ def settings
40
+ @settings ||= YAML.load_file(File.join(File.dirname(File.expand_path(__FILE__)), 'spec.yml'))
41
+ end
33
42
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: apartment_ratings
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 1.0.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -9,24 +9,40 @@ authors:
9
9
  autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
- date: 2014-07-08 00:00:00.000000000 Z
12
+ date: 2014-09-25 00:00:00.000000000 Z
13
13
  dependencies:
14
14
  - !ruby/object:Gem::Dependency
15
15
  name: hashie
16
16
  requirement: !ruby/object:Gem::Requirement
17
17
  none: false
18
18
  requirements:
19
- - - ! '>='
19
+ - - ~>
20
20
  - !ruby/object:Gem::Version
21
- version: '0'
21
+ version: 3.3.1
22
22
  type: :runtime
23
23
  prerelease: false
24
24
  version_requirements: !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ! '>='
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- version: '0'
29
+ version: 3.3.1
30
+ - !ruby/object:Gem::Dependency
31
+ name: tnt
32
+ requirement: !ruby/object:Gem::Requirement
33
+ none: false
34
+ requirements:
35
+ - - ~>
36
+ - !ruby/object:Gem::Version
37
+ version: 0.1.0
38
+ type: :runtime
39
+ prerelease: false
40
+ version_requirements: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ~>
44
+ - !ruby/object:Gem::Version
45
+ version: 0.1.0
30
46
  - !ruby/object:Gem::Dependency
31
47
  name: faraday
32
48
  requirement: !ruby/object:Gem::Requirement
@@ -43,6 +59,22 @@ dependencies:
43
59
  - - ~>
44
60
  - !ruby/object:Gem::Version
45
61
  version: 0.9.0
62
+ - !ruby/object:Gem::Dependency
63
+ name: faraday_middleware
64
+ requirement: !ruby/object:Gem::Requirement
65
+ none: false
66
+ requirements:
67
+ - - ~>
68
+ - !ruby/object:Gem::Version
69
+ version: 0.9.0
70
+ type: :runtime
71
+ prerelease: false
72
+ version_requirements: !ruby/object:Gem::Requirement
73
+ none: false
74
+ requirements:
75
+ - - ~>
76
+ - !ruby/object:Gem::Version
77
+ version: 0.9.0
46
78
  - !ruby/object:Gem::Dependency
47
79
  name: pry
48
80
  requirement: !ruby/object:Gem::Requirement
@@ -195,6 +227,7 @@ files:
195
227
  - lib/apartment_ratings/client.rb
196
228
  - lib/apartment_ratings/complex.rb
197
229
  - lib/apartment_ratings/configuration.rb
230
+ - lib/apartment_ratings/errors.rb
198
231
  - lib/apartment_ratings/review.rb
199
232
  - lib/apartment_ratings/reviews/rating.rb
200
233
  - lib/apartment_ratings/reviews/response.rb
@@ -205,6 +238,7 @@ files:
205
238
  - spec/apartment_ratings/reviews/rating_spec.rb
206
239
  - spec/apartment_ratings/reviews/response_spec.rb
207
240
  - spec/apartment_ratings_spec.rb
241
+ - spec/spec.yml.sample
208
242
  - spec/spec_helper.rb
209
243
  homepage: http://github.com/gregory/apartment_ratings
210
244
  licenses:
@@ -221,7 +255,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
221
255
  version: '0'
222
256
  segments:
223
257
  - 0
224
- hash: 1571250886427044213
258
+ hash: -426309642446831234
225
259
  required_rubygems_version: !ruby/object:Gem::Requirement
226
260
  none: false
227
261
  requirements: