real_savvy 0.0.3

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.
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: []