real_savvy 0.0.3

Sign up to get free protection for your applications and to get access to all the features.
Files changed (44) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -0
  3. data/Gemfile +4 -0
  4. data/LICENSE.txt +21 -0
  5. data/bin/console +14 -0
  6. data/bin/setup +8 -0
  7. data/client.rb +38 -0
  8. data/lib/real_savvy/adapter/agent.rb +6 -0
  9. data/lib/real_savvy/adapter/agent_profile.rb +6 -0
  10. data/lib/real_savvy/adapter/base.rb +19 -0
  11. data/lib/real_savvy/adapter/broker_office.rb +6 -0
  12. data/lib/real_savvy/adapter/collection.rb +30 -0
  13. data/lib/real_savvy/adapter/markets.rb +9 -0
  14. data/lib/real_savvy/adapter/open_house.rb +6 -0
  15. data/lib/real_savvy/adapter/property.rb +17 -0
  16. data/lib/real_savvy/adapter/saved_search.rb +11 -0
  17. data/lib/real_savvy/adapter/site.rb +7 -0
  18. data/lib/real_savvy/adapter/user.rb +13 -0
  19. data/lib/real_savvy/adapter.rb +8 -0
  20. data/lib/real_savvy/attributes.rb +4 -0
  21. data/lib/real_savvy/client.rb +85 -0
  22. data/lib/real_savvy/concern/complex_show_for_adapter.rb +6 -0
  23. data/lib/real_savvy/concern/create_for_adapter.rb +5 -0
  24. data/lib/real_savvy/concern/delegate_to_connection.rb +21 -0
  25. data/lib/real_savvy/concern/destroy_for_adapter.rb +5 -0
  26. data/lib/real_savvy/concern/index_for_adapter.rb +7 -0
  27. data/lib/real_savvy/concern/invites_actions_for_adapter.rb +13 -0
  28. data/lib/real_savvy/concern/show_for_adapter.rb +5 -0
  29. data/lib/real_savvy/concern/update_for_adapter.rb +5 -0
  30. data/lib/real_savvy/concern.rb +5 -0
  31. data/lib/real_savvy/connection.rb +29 -0
  32. data/lib/real_savvy/document.rb +60 -0
  33. data/lib/real_savvy/links.rb +4 -0
  34. data/lib/real_savvy/meta.rb +4 -0
  35. data/lib/real_savvy/resource/base.rb +95 -0
  36. data/lib/real_savvy/resource/collection.rb +4 -0
  37. data/lib/real_savvy/resource/property.rb +3 -0
  38. data/lib/real_savvy/resource/saved_search.rb +4 -0
  39. data/lib/real_savvy/resource/user.rb +3 -0
  40. data/lib/real_savvy/resource.rb +6 -0
  41. data/lib/real_savvy/version.rb +3 -0
  42. data/lib/real_savvy.rb +14 -0
  43. data/real_savvy.gemspec +31 -0
  44. metadata +171 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 4ec995c778fa1380bda1308281b30d8d143ad78a
4
+ data.tar.gz: a87ce301ef34291b8c1679c2c9c01cad51453631
5
+ SHA512:
6
+ metadata.gz: 2ba195c43226ec745e1d345675cd5ebaa00c0b0c08e6e1536e5dce6f8dcddf695bb89974b9f1e3e2ab02c6d4897ac715097c0a905af49f3c6d3c7145dcd8ca63
7
+ data.tar.gz: 02c061df9794ec1ba497fbda7e593c9fc80e5dae445b5517a902a49f86cf00fbee24ca091de265de77449365a2d1ce78c28e7f61ebb20b5c4dafe0bfae18bf85
data/.gitignore ADDED
@@ -0,0 +1,14 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
10
+
11
+ # rspec failure tracking
12
+ .rspec_status
13
+
14
+ *.gem
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in realsavvy.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2017 Andrew Rove
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/bin/console ADDED
@@ -0,0 +1,14 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require "bundler/setup"
4
+ require "real_savvy"
5
+
6
+ # You can add fixtures and/or initialization code here to make experimenting
7
+ # with your gem easier. You can also use a different console, if you like.
8
+
9
+ # (If you use this, don't forget to add pry to your Gemfile!)
10
+ # require "pry"
11
+ # Pry.start
12
+
13
+ require "irb"
14
+ IRB.start(__FILE__)
data/bin/setup ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+ IFS=$'\n\t'
4
+ set -vx
5
+
6
+ appraisal install
7
+
8
+ # Do any other automated setup that you need to do here
data/client.rb ADDED
@@ -0,0 +1,38 @@
1
+ require 'real_savvy/connection'
2
+ require 'real_savvy/concern'
3
+ require 'real_savvy/adapter'
4
+
5
+ Dir[File.dirname(__FILE__) + '/adapaters/*.rb'].each {|file| require file }
6
+
7
+ class RealSavvy::Client
8
+ def initialize(token:, logger: nil)
9
+ @token = token
10
+ @logger = logger
11
+ end
12
+
13
+ def connection
14
+ @connection ||= RealSavvy::Connection.new(client: self)
15
+ end
16
+
17
+ def logger
18
+ @logger
19
+ end
20
+
21
+ def logging?
22
+ !!@logging
23
+ end
24
+
25
+ def token
26
+ @token
27
+ end
28
+
29
+ def properties
30
+ resource_adapaters[:properties] ||= RealSavvy::Adapter::Property.new(connection: connection)
31
+ end
32
+
33
+ private
34
+
35
+ def resource_adapaters
36
+ @resource_adapaters ||= {}
37
+ end
38
+ end
@@ -0,0 +1,6 @@
1
+ class RealSavvy::Adapter::Agent < RealSavvy::Adapter::Base
2
+ path_prefix_is 'agents'
3
+
4
+ include RealSavvy::Concern::ShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ end
@@ -0,0 +1,6 @@
1
+ class RealSavvy::Adapter::AgentProfile < RealSavvy::Adapter::Base
2
+ path_prefix_is 'agent_profiles'
3
+
4
+ include RealSavvy::Concern::ComplexShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ end
@@ -0,0 +1,19 @@
1
+ class RealSavvy::Adapter::Base
2
+ include RealSavvy::Concern::DelegateToConnection
3
+
4
+ def self.path_prefix_is path_prefix
5
+ @path_prefix = path_prefix
6
+ end
7
+
8
+ def self.path_prefix
9
+ @path_prefix
10
+ end
11
+
12
+ def path_prefix
13
+ self.class.path_prefix
14
+ end
15
+
16
+ def initialize(connection:)
17
+ @connection = connection
18
+ end
19
+ end
@@ -0,0 +1,6 @@
1
+ class RealSavvy::Adapter::BrokerOffice < RealSavvy::Adapter::Base
2
+ path_prefix_is 'broker_offices'
3
+
4
+ include RealSavvy::Concern::ComplexShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ end
@@ -0,0 +1,30 @@
1
+ class RealSavvy::Adapter::Collection < RealSavvy::Adapter::Base
2
+ path_prefix_is 'collections'
3
+
4
+ include RealSavvy::Concern::ShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ include RealSavvy::Concern::CreateForAdapter
7
+ include RealSavvy::Concern::UpdateForAdapter
8
+ include RealSavvy::Concern::DestroyForAdapter
9
+ include RealSavvy::Concern::InvitesActionsForAdapter
10
+
11
+ def add(id:, property_ids:)
12
+ put("./api/v3/#{path_prefix}/#{id}/add", {property_ids: property_ids})
13
+ end
14
+
15
+ def remove(id:, property_ids:)
16
+ delete("./api/v3/#{path_prefix}/#{id}/remove", {property_ids: property_ids})
17
+ end
18
+
19
+ def search(id:, filter: {}, market_id: nil, page_size: nil, page_number: nil, page: {})
20
+ page[:size] ||= page_size
21
+ page[:number] ||= page_number
22
+ post("./api/v3/#{path_prefix}/#{id}/properties/search", {filter: filter, market_id: market_id, page: page})
23
+ end
24
+
25
+ def cluster(id:, filter: {}, market_id: nil, page_size: nil, page_number: nil, page: {}, precision: nil)
26
+ page[:size] ||= page_size
27
+ page[:number] ||= page_number
28
+ post("./api/v3/#{path_prefix}/#{id}/properties/map/clusters", {filter: filter, market_id: market_id, page: page, precision: precision})
29
+ end
30
+ end
@@ -0,0 +1,9 @@
1
+ class RealSavvy::Adapter::Market < RealSavvy::Adapter::Base
2
+ path_prefix_is 'markets'
3
+
4
+ include RealSavvy::Concern::ShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ include RealSavvy::Concern::CreateForAdapter
7
+ include RealSavvy::Concern::UpdateForAdapter
8
+ include RealSavvy::Concern::DestroyForAdapter
9
+ end
@@ -0,0 +1,6 @@
1
+ class RealSavvy::Adapter::OpenHouse < RealSavvy::Adapter::Base
2
+ path_prefix_is 'open_houses'
3
+
4
+ include RealSavvy::Concern::IndexForAdapter
5
+ include RealSavvy::Concern::ComplexShowForAdapter
6
+ end
@@ -0,0 +1,17 @@
1
+ class RealSavvy::Adapter::Property < RealSavvy::Adapter::Base
2
+ path_prefix_is 'properties'
3
+
4
+ include RealSavvy::Concern::ComplexShowForAdapter
5
+
6
+ def search(filter: {}, market_id: nil, page_size: nil, page_number: nil, page: {})
7
+ page[:size] ||= page_size
8
+ page[:number] ||= page_number
9
+ post("./api/v3/#{path_prefix}/search", {filter: filter, market_id: market_id, page: page})
10
+ end
11
+
12
+ def cluster(filter: {}, market_id: nil, page_size: nil, page_number: nil, page: {}, precision: nil)
13
+ page[:size] ||= page_size
14
+ page[:number] ||= page_number
15
+ post("./api/v3/#{path_prefix}/map/clusters", {filter: filter, market_id: market_id, page: page, precision: precision})
16
+ end
17
+ end
@@ -0,0 +1,11 @@
1
+ class RealSavvy::Adapter::SavedSearch < RealSavvy::Adapter::Base
2
+ path_prefix_is 'saved_searches'
3
+
4
+ include RealSavvy::Concern::ShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ include RealSavvy::Concern::CreateForAdapter
7
+ include RealSavvy::Concern::UpdateForAdapter
8
+ include RealSavvy::Concern::DestroyForAdapter
9
+
10
+ include RealSavvy::Concern::InvitesActionsForAdapter
11
+ end
@@ -0,0 +1,7 @@
1
+ class RealSavvy::Adapter::Site < RealSavvy::Adapter::Base
2
+ path_prefix_is 'sites'
3
+
4
+ def me
5
+ get("./api/v3/#{path_prefix}/me")
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ class RealSavvy::Adapter::User < RealSavvy::Adapter::Base
2
+ path_prefix_is 'users'
3
+
4
+ include RealSavvy::Concern::ShowForAdapter
5
+ include RealSavvy::Concern::IndexForAdapter
6
+ include RealSavvy::Concern::CreateForAdapter
7
+ include RealSavvy::Concern::UpdateForAdapter
8
+ include RealSavvy::Concern::DestroyForAdapter
9
+
10
+ def me
11
+ get("./api/v3/#{path_prefix}/me")
12
+ end
13
+ end
@@ -0,0 +1,8 @@
1
+ require 'real_savvy/document'
2
+
3
+ module RealSavvy::Adapter
4
+
5
+ end
6
+
7
+ require 'real_savvy/adapter/base'
8
+ Dir[File.dirname(__FILE__) + '/adapter/*.rb'].each {|file| require file }
@@ -0,0 +1,4 @@
1
+ require 'ostruct'
2
+ class RealSavvy::Attributes < OpenStruct
3
+
4
+ end
@@ -0,0 +1,85 @@
1
+ require 'real_savvy/connection'
2
+ require 'real_savvy/concern'
3
+ require 'real_savvy/adapter'
4
+
5
+ class RealSavvy::Client
6
+ ADAPTER_LOOKUP = {
7
+ agent_profiles: RealSavvy::Adapter::AgentProfile,
8
+ agents: RealSavvy::Adapter::Agent,
9
+ broker_offices: RealSavvy::Adapter::BrokerOffice,
10
+ collections: RealSavvy::Adapter::Collection,
11
+ markets: RealSavvy::Adapter::Market,
12
+ open_houses: RealSavvy::Adapter::OpenHouse,
13
+ properties: RealSavvy::Adapter::Property,
14
+ listings: RealSavvy::Adapter::Property,
15
+ saved_searches: RealSavvy::Adapter::SavedSearch,
16
+ site: RealSavvy::Adapter::Site,
17
+ sites: RealSavvy::Adapter::Site,
18
+ users: RealSavvy::Adapter::User,
19
+ user: RealSavvy::Adapter::User,
20
+ }.freeze
21
+
22
+ def initialize(token:, api_url: 'https://api.realsavvy.com', logger: nil, impersonated_user_id: nil)
23
+ @token = token
24
+ @api_url = api_url
25
+ @logger = logger
26
+ @impersonated_user_id = impersonated_user_id
27
+ end
28
+
29
+ def connection
30
+ @connection ||= RealSavvy::Connection.new(client: self)
31
+ end
32
+
33
+ def logger
34
+ @logger
35
+ end
36
+
37
+ def logging?
38
+ !!@logging
39
+ end
40
+
41
+ def token
42
+ @token
43
+ end
44
+
45
+ def api_url
46
+ @api_url
47
+ end
48
+
49
+ def impersonated_user_id
50
+ @impersonated_user_id
51
+ end
52
+
53
+ class AdapterProxy
54
+ attr_reader :adapter
55
+
56
+ def initialize(adapter)
57
+ @adapter = adapter
58
+ end
59
+
60
+ private
61
+
62
+ def method_missing(method, *args, &block)
63
+ response = @adapter.send(method, *args, &block)
64
+ RealSavvy::Document.new(response.body, status: response.status)
65
+ end
66
+ end
67
+
68
+ def get_adapter(name)
69
+ resource_adapaters[name] ||= AdapterProxy.new(ADAPTER_LOOKUP[name].new(connection: connection))
70
+ end
71
+
72
+ private
73
+
74
+ def resource_adapaters
75
+ @resource_adapaters ||= {}
76
+ end
77
+
78
+ def method_missing(m, *args, &block)
79
+ if ADAPTER_LOOKUP[m]
80
+ get_adapter(m)
81
+ else
82
+ super
83
+ end
84
+ end
85
+ end
@@ -0,0 +1,6 @@
1
+ module RealSavvy::Concern::ComplexShowForAdapter
2
+ def show(complex_id: nil, feed: nil, key: nil)
3
+ feed, key = complex_id.split('~') if complex_id && feed.nil? && key.nil?
4
+ get("./api/v3/#{path_prefix}/#{feed}/#{key}")
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module RealSavvy::Concern::CreateForAdapter
2
+ def create(attributes: {})
3
+ post("./api/v3/#{path_prefix}", {data: {attributes: attributes}})
4
+ end
5
+ end
@@ -0,0 +1,21 @@
1
+ module RealSavvy::Concern::DelegateToConnection
2
+ def connection
3
+ @connection
4
+ end
5
+
6
+ def get(*args)
7
+ connection.get(*args)
8
+ end
9
+
10
+ def post(*args)
11
+ connection.post(*args)
12
+ end
13
+
14
+ def put(*args)
15
+ connection.put(*args)
16
+ end
17
+
18
+ def delete(*args)
19
+ connection.delete(*args)
20
+ end
21
+ end
@@ -0,0 +1,5 @@
1
+ module RealSavvy::Concern::DestroyForAdapter
2
+ def destroy(id:)
3
+ delete("./api/v3/#{path_prefix}/#{id}")
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ module RealSavvy::Concern::IndexForAdapter
2
+ def index(page_size: nil, page_number: nil, page: {})
3
+ page[:size] ||= page_size
4
+ page[:number] ||= page_number
5
+ get("./api/v3/#{path_prefix}", {page: page})
6
+ end
7
+ end
@@ -0,0 +1,13 @@
1
+ module RealSavvy::Concern::InvitesActionsForAdapter
2
+ def invite(id:, email:)
3
+ put("./api/v3/#{path_prefix}/#{id}/invite", {email: email})
4
+ end
5
+
6
+ def accept_invite(id:, given:)
7
+ put("./api/v3/#{path_prefix}/#{id}/accept_invite", {given: given})
8
+ end
9
+
10
+ def uninvite(id:, email:)
11
+ delete("./api/v3/#{path_prefix}/#{id}/uninvite", {email: email})
12
+ end
13
+ end
@@ -0,0 +1,5 @@
1
+ module RealSavvy::Concern::ShowForAdapter
2
+ def show(id:)
3
+ get("./api/v3/#{path_prefix}/#{id}")
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module RealSavvy::Concern::UpdateForAdapter
2
+ def update(id:, attributes: {})
3
+ put("./api/v3/#{path_prefix}/#{id}", {data: {attributes: attributes}})
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ module RealSavvy::Concern
2
+
3
+ end
4
+
5
+ Dir[File.dirname(__FILE__) + '/concern/*.rb'].each {|file| require file }
@@ -0,0 +1,29 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ class RealSavvy::Connection
5
+ attr_reader :faraday
6
+
7
+ def initialize(client:)
8
+ @faraday = ::Faraday.new(client.api_url) do |faraday|
9
+ faraday.request :json
10
+ faraday.response :json
11
+
12
+ faraday.response :logger, client.logger if client.logging?
13
+ faraday.adapter Faraday.default_adapter
14
+
15
+ faraday.headers['Authorization'] = "Bearer #{client.token}"
16
+ faraday.params['impersonated_user_id'] = client.impersonated_user_id if client.impersonated_user_id
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def delegate(m, *args, &block)
23
+ faraday.send(m, *args, &block)
24
+ end
25
+
26
+ def method_missing(m, *args, &block)
27
+ delegate(m, *args, &block)
28
+ end
29
+ end
@@ -0,0 +1,60 @@
1
+ require 'real_savvy/meta'
2
+ require 'real_savvy/resource'
3
+
4
+ class RealSavvy::Document
5
+
6
+ attr_reader :document
7
+
8
+ TYPE_TO_RESOURCE = {
9
+ 'properties' => RealSavvy::Resource::Property,
10
+ 'listings' => RealSavvy::Resource::Property,
11
+ 'collections' => RealSavvy::Resource::Collection,
12
+ 'saved_searches' => RealSavvy::Resource::SavedSearch,
13
+ 'users' => RealSavvy::Resource::User,
14
+ }.tap do |lookup|
15
+ lookup.default = RealSavvy::Resource::Base
16
+ end.freeze
17
+
18
+ def initialize(document, status: nil)
19
+ @document = document
20
+ @status = status
21
+ end
22
+
23
+ def data
24
+ @data ||= self.class.process_resources(document['data'], self)
25
+ end
26
+
27
+ alias results data
28
+
29
+ def result
30
+ data[0]
31
+ end
32
+
33
+ def included
34
+ @included ||= self.class.process_resources(document['included'], self)
35
+ end
36
+
37
+ def meta
38
+ @meta ||= RealSavvy::Meta.new(document['meta'] || {})
39
+ end
40
+
41
+ def errors
42
+ @errors ||= document['errors'] || {}
43
+ end
44
+
45
+ def status
46
+ @status
47
+ end
48
+
49
+ def objects_lookup
50
+ @objects_lookup ||= (data + included).each_with_object({}) { |resource, result| result[resource.hash] = resource }
51
+ end
52
+
53
+ def inspect
54
+ document.inspect
55
+ end
56
+
57
+ def self.process_resources(resources, document=nil)
58
+ ::RealSavvy.safe_wrap(resources).map { |object| TYPE_TO_RESOURCE[object['type']].new(object, document) }
59
+ end
60
+ end
@@ -0,0 +1,4 @@
1
+ require 'ostruct'
2
+ class RealSavvy::Links < OpenStruct
3
+
4
+ end
@@ -0,0 +1,4 @@
1
+ require 'ostruct'
2
+ class RealSavvy::Meta < OpenStruct
3
+
4
+ end
@@ -0,0 +1,95 @@
1
+ require 'set'
2
+ require 'real_savvy/attributes'
3
+ require 'real_savvy/links'
4
+
5
+ class RealSavvy::Resource::Base
6
+ attr_reader :json, :document
7
+
8
+ def initialize(json, document)
9
+ @json = json
10
+ @document = document
11
+ end
12
+
13
+ def hash
14
+ {id: id, type: type}.to_json.hash
15
+ end
16
+
17
+ def id
18
+ json['id']
19
+ end
20
+
21
+ def type
22
+ json['type']
23
+ end
24
+
25
+ def attributes
26
+ @attributes ||= RealSavvy::Attributes.new(json['attributes'] || {})
27
+ end
28
+
29
+ def links
30
+ @links ||= RealSavvy::Links.new(json['links'] || {})
31
+ end
32
+
33
+ def meta
34
+ @meta ||= RealSavvy::Meta.new(json['meta'] || {})
35
+ end
36
+
37
+ def relationships
38
+ self
39
+ end
40
+
41
+ def inspect
42
+ json.inspect
43
+ end
44
+
45
+ def self.relationships
46
+ @relationships ||= {}
47
+ end
48
+
49
+ def self.has_one relationship
50
+ relationships[relationship.to_s] ||= {}
51
+ relationships[relationship.to_s].merge!(single: true)
52
+ end
53
+
54
+ def self.belongs_to relationship
55
+ has_one relationship
56
+ end
57
+
58
+ # Do nothing default behavior
59
+ def self.has_many relationship
60
+
61
+ end
62
+
63
+ private
64
+
65
+ def objects_lookup
66
+ document&.objects_lookup || {}
67
+ end
68
+
69
+ def loaded_relationships
70
+ @loaded_relationships ||= {}
71
+ end
72
+
73
+ def has_relationship(relationship)
74
+ possible_relation_ship = json['relationships']&.[](relationship.to_s)
75
+ possible_relation_ship && possible_relation_ship.length > 0
76
+ end
77
+
78
+ def build_relationship(relationship)
79
+ relationship_raw = json['relationships']&.[](relationship.to_s)&.[]('data')
80
+ relationship_processed = ::RealSavvy::Document.process_resources(relationship_raw)
81
+ end
82
+
83
+ def load_relationship_with_lookup(relationship)
84
+ loaded_relationships[relationship] ||= build_relationship(relationship).map { |resource| objects_lookup[resource.hash] || resource }
85
+ self.class.relationships[relationship.to_s]&.[](:single) ? loaded_relationships[relationship].first : loaded_relationships[relationship]
86
+ end
87
+
88
+ def method_missing(m, *args, &block)
89
+ if has_relationship(m)
90
+ load_relationship_with_lookup(m)
91
+ else
92
+ super
93
+ end
94
+ end
95
+ end
@@ -0,0 +1,4 @@
1
+ class RealSavvy::Resource::Collection < RealSavvy::Resource::Base
2
+ belongs_to :user
3
+ belongs_to :site
4
+ end
@@ -0,0 +1,3 @@
1
+ class RealSavvy::Resource::Property < RealSavvy::Resource::Base
2
+
3
+ end
@@ -0,0 +1,4 @@
1
+ class RealSavvy::Resource::SavedSearch < RealSavvy::Resource::Base
2
+ belongs_to :user
3
+ belongs_to :site
4
+ end
@@ -0,0 +1,3 @@
1
+ class RealSavvy::Resource::User < RealSavvy::Resource::Base
2
+
3
+ end
@@ -0,0 +1,6 @@
1
+ module RealSavvy::Resource
2
+
3
+ end
4
+
5
+ require 'real_savvy/resource/base'
6
+ Dir[File.dirname(__FILE__) + '/resource/*.rb'].each {|file| require file }
@@ -0,0 +1,3 @@
1
+ module RealSavvy
2
+ VERSION = [0,0,3]
3
+ end
data/lib/real_savvy.rb ADDED
@@ -0,0 +1,14 @@
1
+ module RealSavvy
2
+ # From the rails Array.wrap method
3
+ def self.safe_wrap(object)
4
+ if object.nil?
5
+ []
6
+ elsif object.respond_to?(:to_ary)
7
+ object.to_ary || [object]
8
+ else
9
+ [object]
10
+ end
11
+ end
12
+ end
13
+
14
+ require 'real_savvy/client'
@@ -0,0 +1,31 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'real_savvy/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'real_savvy'
8
+ spec.version = RealSavvy::VERSION.join('.')
9
+ spec.authors = ["Ryan Rauh","Michael Bastos","Andrew Rove"]
10
+ spec.email = 'andrew@realsavvy.com'
11
+
12
+ spec.summary = %q{RealSavvy API Gem}
13
+ spec.description = %q{A gem for connecting to RealSavvy V3 API}
14
+ spec.homepage = 'http://rubygems.org/gems/realsavvy'
15
+ spec.license = 'MIT'
16
+
17
+ spec.files = `git ls-files -z`.split("\x0").reject do |f|
18
+ f.match(%r{^(test|spec|features|gemfiles)/})
19
+ end
20
+ spec.bindir = "exe"
21
+ spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
22
+ spec.require_paths = ["lib"]
23
+
24
+ spec.add_runtime_dependency 'faraday', ">= 0.10.0"
25
+ spec.add_runtime_dependency 'faraday_middleware', ">= 0.10.0"
26
+
27
+ spec.add_development_dependency "bundler", "~> 1.14"
28
+ spec.add_development_dependency "rake", "~> 10.0"
29
+ spec.add_development_dependency "rspec", "~> 3.0"
30
+ spec.add_development_dependency "pry", "~> 0.10"
31
+ end
metadata ADDED
@@ -0,0 +1,171 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: real_savvy
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.3
5
+ platform: ruby
6
+ authors:
7
+ - Ryan Rauh
8
+ - Michael Bastos
9
+ - Andrew Rove
10
+ autorequire:
11
+ bindir: exe
12
+ cert_chain: []
13
+ date: 2018-02-12 00:00:00.000000000 Z
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: faraday
17
+ requirement: !ruby/object:Gem::Requirement
18
+ requirements:
19
+ - - ">="
20
+ - !ruby/object:Gem::Version
21
+ version: 0.10.0
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: !ruby/object:Gem::Requirement
25
+ requirements:
26
+ - - ">="
27
+ - !ruby/object:Gem::Version
28
+ version: 0.10.0
29
+ - !ruby/object:Gem::Dependency
30
+ name: faraday_middleware
31
+ requirement: !ruby/object:Gem::Requirement
32
+ requirements:
33
+ - - ">="
34
+ - !ruby/object:Gem::Version
35
+ version: 0.10.0
36
+ type: :runtime
37
+ prerelease: false
38
+ version_requirements: !ruby/object:Gem::Requirement
39
+ requirements:
40
+ - - ">="
41
+ - !ruby/object:Gem::Version
42
+ version: 0.10.0
43
+ - !ruby/object:Gem::Dependency
44
+ name: bundler
45
+ requirement: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - "~>"
48
+ - !ruby/object:Gem::Version
49
+ version: '1.14'
50
+ type: :development
51
+ prerelease: false
52
+ version_requirements: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - "~>"
55
+ - !ruby/object:Gem::Version
56
+ version: '1.14'
57
+ - !ruby/object:Gem::Dependency
58
+ name: rake
59
+ requirement: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - "~>"
62
+ - !ruby/object:Gem::Version
63
+ version: '10.0'
64
+ type: :development
65
+ prerelease: false
66
+ version_requirements: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - "~>"
69
+ - !ruby/object:Gem::Version
70
+ version: '10.0'
71
+ - !ruby/object:Gem::Dependency
72
+ name: rspec
73
+ requirement: !ruby/object:Gem::Requirement
74
+ requirements:
75
+ - - "~>"
76
+ - !ruby/object:Gem::Version
77
+ version: '3.0'
78
+ type: :development
79
+ prerelease: false
80
+ version_requirements: !ruby/object:Gem::Requirement
81
+ requirements:
82
+ - - "~>"
83
+ - !ruby/object:Gem::Version
84
+ version: '3.0'
85
+ - !ruby/object:Gem::Dependency
86
+ name: pry
87
+ requirement: !ruby/object:Gem::Requirement
88
+ requirements:
89
+ - - "~>"
90
+ - !ruby/object:Gem::Version
91
+ version: '0.10'
92
+ type: :development
93
+ prerelease: false
94
+ version_requirements: !ruby/object:Gem::Requirement
95
+ requirements:
96
+ - - "~>"
97
+ - !ruby/object:Gem::Version
98
+ version: '0.10'
99
+ description: A gem for connecting to RealSavvy V3 API
100
+ email: andrew@realsavvy.com
101
+ executables: []
102
+ extensions: []
103
+ extra_rdoc_files: []
104
+ files:
105
+ - ".gitignore"
106
+ - Gemfile
107
+ - LICENSE.txt
108
+ - bin/console
109
+ - bin/setup
110
+ - client.rb
111
+ - lib/real_savvy.rb
112
+ - lib/real_savvy/adapter.rb
113
+ - lib/real_savvy/adapter/agent.rb
114
+ - lib/real_savvy/adapter/agent_profile.rb
115
+ - lib/real_savvy/adapter/base.rb
116
+ - lib/real_savvy/adapter/broker_office.rb
117
+ - lib/real_savvy/adapter/collection.rb
118
+ - lib/real_savvy/adapter/markets.rb
119
+ - lib/real_savvy/adapter/open_house.rb
120
+ - lib/real_savvy/adapter/property.rb
121
+ - lib/real_savvy/adapter/saved_search.rb
122
+ - lib/real_savvy/adapter/site.rb
123
+ - lib/real_savvy/adapter/user.rb
124
+ - lib/real_savvy/attributes.rb
125
+ - lib/real_savvy/client.rb
126
+ - lib/real_savvy/concern.rb
127
+ - lib/real_savvy/concern/complex_show_for_adapter.rb
128
+ - lib/real_savvy/concern/create_for_adapter.rb
129
+ - lib/real_savvy/concern/delegate_to_connection.rb
130
+ - lib/real_savvy/concern/destroy_for_adapter.rb
131
+ - lib/real_savvy/concern/index_for_adapter.rb
132
+ - lib/real_savvy/concern/invites_actions_for_adapter.rb
133
+ - lib/real_savvy/concern/show_for_adapter.rb
134
+ - lib/real_savvy/concern/update_for_adapter.rb
135
+ - lib/real_savvy/connection.rb
136
+ - lib/real_savvy/document.rb
137
+ - lib/real_savvy/links.rb
138
+ - lib/real_savvy/meta.rb
139
+ - lib/real_savvy/resource.rb
140
+ - lib/real_savvy/resource/base.rb
141
+ - lib/real_savvy/resource/collection.rb
142
+ - lib/real_savvy/resource/property.rb
143
+ - lib/real_savvy/resource/saved_search.rb
144
+ - lib/real_savvy/resource/user.rb
145
+ - lib/real_savvy/version.rb
146
+ - real_savvy.gemspec
147
+ homepage: http://rubygems.org/gems/realsavvy
148
+ licenses:
149
+ - MIT
150
+ metadata: {}
151
+ post_install_message:
152
+ rdoc_options: []
153
+ require_paths:
154
+ - lib
155
+ required_ruby_version: !ruby/object:Gem::Requirement
156
+ requirements:
157
+ - - ">="
158
+ - !ruby/object:Gem::Version
159
+ version: '0'
160
+ required_rubygems_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - ">="
163
+ - !ruby/object:Gem::Version
164
+ version: '0'
165
+ requirements: []
166
+ rubyforge_project:
167
+ rubygems_version: 2.6.13
168
+ signing_key:
169
+ specification_version: 4
170
+ summary: RealSavvy API Gem
171
+ test_files: []