tourets 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +19 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +97 -0
- data/Rakefile +2 -0
- data/lib/tourets.rb +61 -0
- data/lib/tourets/exceptions.rb +7 -0
- data/lib/tourets/extensions/hash.rb +20 -0
- data/lib/tourets/photo.rb +53 -0
- data/lib/tourets/property.rb +84 -0
- data/lib/tourets/rails.rb +10 -0
- data/lib/tourets/rails/engine.rb +6 -0
- data/lib/tourets/rails/railtie.rb +8 -0
- data/lib/tourets/rails/version.rb +6 -0
- data/lib/tourets/search.rb +19 -0
- data/lib/tourets/utilities.rb +138 -0
- data/lib/tourets/vrimage.rb +30 -0
- data/tourets.gemspec +22 -0
- metadata +136 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
Copyright (c) 2012 Jeremy Woertink & Justin Mitchell
|
2
|
+
|
3
|
+
MIT License
|
4
|
+
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
a copy of this software and associated documentation files (the
|
7
|
+
"Software"), to deal in the Software without restriction, including
|
8
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
the following conditions:
|
12
|
+
|
13
|
+
The above copyright notice and this permission notice shall be
|
14
|
+
included in all copies or substantial portions of the Software.
|
15
|
+
|
16
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,97 @@
|
|
1
|
+
# TouRETS
|
2
|
+
|
3
|
+
The name came from a play on Tourette's and RETS. Because when you work with RETS you feel like you have Tourette's.
|
4
|
+
The goal of this gem is to make a really clean and familiar API for connecting to a RETS server. This gem was designed to be used with rails, so it takes a lot of the API that rails uses.
|
5
|
+
|
6
|
+
## Installation
|
7
|
+
|
8
|
+
Add this line to your application's Gemfile:
|
9
|
+
|
10
|
+
gem 'tourets', :github => 'jwoertink/tourets'
|
11
|
+
|
12
|
+
Add a rets_config.yml to the config directory of your rails app
|
13
|
+
|
14
|
+
```yaml
|
15
|
+
-
|
16
|
+
mls: 'GLVAR'
|
17
|
+
url: 'http://las.rets.interealty.com/Login.asmx/Login'
|
18
|
+
username: 'user'
|
19
|
+
password: 'secret'
|
20
|
+
rets_version: '1.8'
|
21
|
+
auth_mode: :digest
|
22
|
+
useragent:
|
23
|
+
name: 'some_user_connector'
|
24
|
+
```
|
25
|
+
|
26
|
+
And then execute:
|
27
|
+
|
28
|
+
$ bundle
|
29
|
+
|
30
|
+
Or install it yourself as:
|
31
|
+
|
32
|
+
$ gem install tourets
|
33
|
+
|
34
|
+
## Usage
|
35
|
+
(since this is still new, this usage may change often)
|
36
|
+
|
37
|
+
```ruby
|
38
|
+
begin
|
39
|
+
TouRETS.establish_connection('GLVAR')
|
40
|
+
# Get a list of properties with 3 bedrooms and 2 bathrooms
|
41
|
+
@properties = TouRETS::Property.where(:bedrooms => 3, :bathrooms => 2)
|
42
|
+
# Grab all the photos for the first property
|
43
|
+
@photos = @properties.first.photos
|
44
|
+
# Iterate through all those photos, save them into tempfiles, and then do stuff?
|
45
|
+
@photos.each do |photo|
|
46
|
+
begin
|
47
|
+
tmp = Tempfile.new(photo.filename)
|
48
|
+
tmp.write(photo.image)
|
49
|
+
# you have an actual photo now. Maybe push to S3?
|
50
|
+
ensure
|
51
|
+
tmp.close
|
52
|
+
tmp.unlink
|
53
|
+
end
|
54
|
+
end
|
55
|
+
ensure
|
56
|
+
TouRETS.close_connection
|
57
|
+
end
|
58
|
+
```
|
59
|
+
|
60
|
+
Before doing anything, you must make your first initial connection to your MLS server.
|
61
|
+
```ruby
|
62
|
+
if TouRETS.current_connection?
|
63
|
+
# Get the sysid for the last property in that instance array
|
64
|
+
property_id = @properties.last.id
|
65
|
+
puts property_id #=> 1234567
|
66
|
+
# Grab the second picture for that property
|
67
|
+
picture = TouRETS::Photo.find(property_id, :id => 2)
|
68
|
+
puts picture.content_type #=> image/jpeg
|
69
|
+
puts picture.filename #=> 1234567-2.jpg
|
70
|
+
puts picture.id #=> 2
|
71
|
+
# This returns the binary string data that gets written to a file
|
72
|
+
puts picture.image.class #=> String
|
73
|
+
end
|
74
|
+
```
|
75
|
+
|
76
|
+
## ruby-rets
|
77
|
+
This gem relies heavily on the work done by Zachary Anker (zanker) with the [ruby-rets](https://github.com/Placester/ruby-rets) gem.
|
78
|
+
There is a `TouRETS::Search#find` class which just makes a direct call to the `RETS::Base::Core#search`. This gives you the option to still use
|
79
|
+
that gem inside of this one.
|
80
|
+
|
81
|
+
## TODO (in no particular order)
|
82
|
+
1. Add in other Objects like VRImage, Thumbnail, Map, Video, Audio
|
83
|
+
2. Add in other Resources like Agent, Office, LotsAndLand
|
84
|
+
3. CLEAN CODE!!!!!
|
85
|
+
4. Add in limits, and selects to searches
|
86
|
+
5. TEST TEST TEST TEST
|
87
|
+
6. Add some passing specs.
|
88
|
+
7. Document the hell out of this thing
|
89
|
+
|
90
|
+
|
91
|
+
## Contributing
|
92
|
+
|
93
|
+
1. Fork it
|
94
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
95
|
+
3. Commit your changes (`git commit -am 'Added some feature'`)
|
96
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
97
|
+
5. Create new Pull Request
|
data/Rakefile
ADDED
data/lib/tourets.rb
ADDED
@@ -0,0 +1,61 @@
|
|
1
|
+
require 'ruby-rets'
|
2
|
+
require 'tourets/rails'
|
3
|
+
require 'tourets/utilities'
|
4
|
+
require 'tourets/exceptions'
|
5
|
+
require 'tourets/extensions/hash' # This should go away after Rails 4.0
|
6
|
+
require 'tourets/search'
|
7
|
+
require 'tourets/photo'
|
8
|
+
require 'tourets/property'
|
9
|
+
|
10
|
+
module TouRETS
|
11
|
+
include Utilities
|
12
|
+
|
13
|
+
class << self
|
14
|
+
attr_accessor :current_connection
|
15
|
+
|
16
|
+
# This will take the specific MLS you want to connect to
|
17
|
+
# There must be a rets_config.yml file in the :rails_root/config directory
|
18
|
+
#
|
19
|
+
def establish_connection(mls)
|
20
|
+
config_file = File.join(app_root, 'config', 'rets_config.yml')
|
21
|
+
if File.exists?(config_file)
|
22
|
+
connections = YAML.load_file(config_file)
|
23
|
+
conn = connections.select { |conn| conn['mls'] == mls }.first
|
24
|
+
if conn.nil?
|
25
|
+
raise ConfigurationError, "Missing or incorrect MLS key `#{mls}`."
|
26
|
+
else
|
27
|
+
conn.recursive_symbolize_keys!
|
28
|
+
conn.delete(:mls)
|
29
|
+
self.current_connection = RETS::Client.login(conn)
|
30
|
+
end
|
31
|
+
else
|
32
|
+
raise ConfigurationError, "Couldn't find Config File in #{config_file}."
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# Closes the current connection to the RETS server
|
37
|
+
def close_connection
|
38
|
+
current_connection.logout if current_connection?
|
39
|
+
current_connection = nil
|
40
|
+
end
|
41
|
+
|
42
|
+
def ensure_connected!
|
43
|
+
raise ConnectionError, "You must establish a connection first." unless current_connection?
|
44
|
+
end
|
45
|
+
|
46
|
+
def current_connection?
|
47
|
+
!current_connection.nil?
|
48
|
+
end
|
49
|
+
|
50
|
+
# The root of the application using this gem
|
51
|
+
def app_root
|
52
|
+
if defined?(Rails)
|
53
|
+
::Rails.root
|
54
|
+
else
|
55
|
+
Dir.pwd
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
end
|
60
|
+
|
61
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# This is only a temporary fix until it's patched in Rails
|
2
|
+
class Hash
|
3
|
+
|
4
|
+
def recursive_symbolize_keys!
|
5
|
+
symbolize_keys!
|
6
|
+
|
7
|
+
values.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash)}
|
8
|
+
values.select{|v| v.is_a?(Array)}.flatten.each{|h| h.recursive_symbolize_keys! if h.is_a?(Hash)}
|
9
|
+
self
|
10
|
+
end
|
11
|
+
|
12
|
+
#In case for some reason this isn't picked up from Rails
|
13
|
+
def symbolize_keys!
|
14
|
+
keys.each do |key|
|
15
|
+
self[(key.to_sym rescue key) || key] = delete(key)
|
16
|
+
end
|
17
|
+
self
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module TouRETS
|
2
|
+
class Photo
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
# Find the photo
|
7
|
+
# Use find("1234", :id => 1) to find the photo with ID 1 in the 1234 group
|
8
|
+
# Default it to return all of the photos.
|
9
|
+
def find(sysid, opts={})
|
10
|
+
limit = opts[:id] || "*"
|
11
|
+
[].tap do |photos|
|
12
|
+
TouRETS.current_connection.get_object(:resource => opts[:resource], :type => :Photo, :location => false, :id => "#{sysid}:#{limit}") do |headers, content|
|
13
|
+
photos << new(headers, content)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
attr_accessor :id, :resource_id, :content_type, :content
|
21
|
+
|
22
|
+
# id is the ID of the photo
|
23
|
+
# resource_id is the ID of the resource it belongs to. Properties will probably be sysid everytime
|
24
|
+
# content_type is the Image content_type
|
25
|
+
# content is the Binary string that can be written to a file to display the image.
|
26
|
+
def initialize(headers, content)
|
27
|
+
self.id = headers["object-id"]
|
28
|
+
self.resource_id = headers["content-id"]
|
29
|
+
self.content_type = headers["content-type"]
|
30
|
+
self.content = content
|
31
|
+
end
|
32
|
+
|
33
|
+
# Use this method to get the binary string to write to a file.
|
34
|
+
# Sometimes the string will contin ASCII-8BIT characters.
|
35
|
+
# Forcing to UTF-8 will make it write to a file easier.
|
36
|
+
def image
|
37
|
+
content.to_s.force_encoding("UTF-8")
|
38
|
+
end
|
39
|
+
|
40
|
+
# Returns a filename based on the resource_id and id of the photo
|
41
|
+
# should have proper extension on it.
|
42
|
+
def filename
|
43
|
+
ext = case content_type
|
44
|
+
when /jpeg$/, /jpg$/ then "jpg"
|
45
|
+
when /png$/ then "png"
|
46
|
+
when /gif$/ then "gif"
|
47
|
+
else "jpg"
|
48
|
+
end
|
49
|
+
"#{resource_id}-#{id}.#{ext}"
|
50
|
+
end
|
51
|
+
|
52
|
+
end
|
53
|
+
end
|
@@ -0,0 +1,84 @@
|
|
1
|
+
module TouRETS
|
2
|
+
class Property
|
3
|
+
include Utilities
|
4
|
+
extend Utilities
|
5
|
+
|
6
|
+
SEARCH_QUERY_DEFAULTS = {:active_properties => "ER,EA,C", :idx_display => "Y", :internet_display => "Y"}
|
7
|
+
# This class searches for ResidentialProperty, Condo, SingleFamily, Rental
|
8
|
+
# Some MLS use "1", some use :RES... Will need to decide which way is to be used.
|
9
|
+
SEARCH_CONFIG_DEFAULTS = {:search_type => :Property, :class => "1"}
|
10
|
+
|
11
|
+
class << self
|
12
|
+
|
13
|
+
# Returns an array of all of the properties
|
14
|
+
# Property.all
|
15
|
+
def all
|
16
|
+
where
|
17
|
+
end
|
18
|
+
|
19
|
+
# Returns an array of property results.
|
20
|
+
# Property.where(:bedrooms => 7, :bathrooms => 4, :list_price => 200000..300000)
|
21
|
+
# Property.where(:property_type => {:not => ['CONDO', 'TOWNHOME']}, :area => {:or => ['South West', 'North West']})
|
22
|
+
# Property.where(:area => ['South West', 'North West']) # This is like 'AND'
|
23
|
+
def where(search_params = {})
|
24
|
+
TouRETS.ensure_connected!
|
25
|
+
[].tap do |properties|
|
26
|
+
search_params = map_search_params(SEARCH_QUERY_DEFAULTS.merge(search_params))
|
27
|
+
search_config = SEARCH_CONFIG_DEFAULTS.merge({:query => hash_to_rets_query_string(search_params)})
|
28
|
+
Search.find(search_config) do |property|
|
29
|
+
properties << self.new(property)
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
# # Propert.where(:bedrooms => 3).limit(10) #not implemented
|
35
|
+
# def limit(limit_number = 5000)
|
36
|
+
# SEARCH_CONFIG_DEFAULTS.merge!(:limit => limit_number)
|
37
|
+
# self
|
38
|
+
# end
|
39
|
+
#
|
40
|
+
# # Property.where(:bedrooms => 3).count #not implemented
|
41
|
+
# def count
|
42
|
+
# SEARCH_CONFIG_DEFAULTS.merge!(:count_mode => :only)
|
43
|
+
# self
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
# # Property.select(['SystemName', 'LongName']).where(:bedrooms => 3) #not implemented
|
47
|
+
# # select is to limit which fields actually get returned. This could help with mapping
|
48
|
+
# def select(fields=[])
|
49
|
+
# {:select => fields}
|
50
|
+
# self
|
51
|
+
# end
|
52
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
attr_accessor :attributes
|
56
|
+
|
57
|
+
def initialize(args = {})
|
58
|
+
self.attributes = args
|
59
|
+
end
|
60
|
+
|
61
|
+
# Return an array of the photo objects that belong to a particular property
|
62
|
+
def photos
|
63
|
+
@photos ||= grab_photos
|
64
|
+
end
|
65
|
+
|
66
|
+
def method_missing(method_name, *args, &block)
|
67
|
+
val = attributes[key_map[method_name.to_sym]]
|
68
|
+
if val.nil?
|
69
|
+
super
|
70
|
+
else
|
71
|
+
return val
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
private
|
76
|
+
|
77
|
+
def grab_photos
|
78
|
+
[].tap do |pics|
|
79
|
+
pics << TouRETS::Photo.find(attributes['sysid'], :resource => :Property)
|
80
|
+
end.flatten
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
84
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module TouRETS
|
2
|
+
|
3
|
+
class Search
|
4
|
+
|
5
|
+
class << self
|
6
|
+
|
7
|
+
# This works as a raw search. This give the developer a chance
|
8
|
+
# to customize how they want to search.
|
9
|
+
def find(search_params = {}, &block)
|
10
|
+
raise ArgumentError, "No block passed" unless block_given?
|
11
|
+
TouRETS.ensure_connected!
|
12
|
+
TouRETS.current_connection.search(search_params, &block)
|
13
|
+
end
|
14
|
+
|
15
|
+
end
|
16
|
+
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
@@ -0,0 +1,138 @@
|
|
1
|
+
module TouRETS
|
2
|
+
module Utilities
|
3
|
+
|
4
|
+
# Convert a key value pair into a RETS formatted query string.
|
5
|
+
# TODO: Take values that are arrays, ranges, or hashes, and convert those properly
|
6
|
+
def hash_to_rets_query_string(hash)
|
7
|
+
[].tap do |str|
|
8
|
+
hash.each_pair do |k,v|
|
9
|
+
val = value_map(v)
|
10
|
+
str << "(#{k.to_s.camelize}=#{val})"
|
11
|
+
end
|
12
|
+
end.join(',')
|
13
|
+
end
|
14
|
+
|
15
|
+
# This takes a hash of search parameters, and modifies
|
16
|
+
# the hash to have the correct key types for the current RETS server
|
17
|
+
def map_search_params(search_params)
|
18
|
+
Hash[search_params.map {|k, v| [key_map[k], v] }]
|
19
|
+
end
|
20
|
+
|
21
|
+
# Giant Hash.
|
22
|
+
# TODO: OPTIMIZE!!!! ZOMG! O_o
|
23
|
+
# Maybe break this into a YAML file that will pick which keymap to use based on the current_connection?
|
24
|
+
# I'm thinking maybe like a dictionary lookup. Figure out what each RETS server uses.
|
25
|
+
# Also good to note that there are different data types, but they all are strings.
|
26
|
+
# We could figure out a way to convert to Integer, or DateTime objects, etc... depending.
|
27
|
+
def key_map
|
28
|
+
{
|
29
|
+
:id => "sysid", #String
|
30
|
+
:property_type => "1", #String
|
31
|
+
:acreage => "2", #Float
|
32
|
+
:zip_code => "10", #String
|
33
|
+
:address => "13", #String
|
34
|
+
:partial_flag => "17", #String
|
35
|
+
:close_date => "25", #DateTime
|
36
|
+
:agent_name => "26", #String
|
37
|
+
:annual_property_tax => "28", #Integer
|
38
|
+
:has_dishwasher => "30", #Boolean
|
39
|
+
:has_disposal => "31", #Boolean
|
40
|
+
:has_refrigerator => "33", #Boolean
|
41
|
+
:dryer_hookup => "34", #String
|
42
|
+
:area => "37", #String
|
43
|
+
:association_fee => "39", #Integer
|
44
|
+
#1st Encumbr Assumption Desc => "43" # Like the mortgage...
|
45
|
+
:three_quarter_baths => "60", #Integer
|
46
|
+
:bathrooms => "61", #Integer
|
47
|
+
:half_baths => "62", #Integer
|
48
|
+
:total_baths => "63", #Integer
|
49
|
+
:downstairs_bath_desc => "63",#String
|
50
|
+
:bedrooms => "68", #Integer
|
51
|
+
:built_desc => "72", #String
|
52
|
+
:carport_desc => "73", #String
|
53
|
+
:carports => "74", #Integer
|
54
|
+
:comp_days_on_market => "81", #Integer (this is nil sometimes)
|
55
|
+
:contingency_desc => "84", #String
|
56
|
+
:contract_date => "85", #DateTime
|
57
|
+
:cooling_fuel_desc => "86", #String
|
58
|
+
:county => "87", #String
|
59
|
+
:second_bed_dim => "89", #String
|
60
|
+
:third_bed_dim => "90", #String
|
61
|
+
:fourth_bed_dim => "91", #String
|
62
|
+
:dining_room_dim => "92", #String
|
63
|
+
:family_room_dim => "93", #String
|
64
|
+
:fifth_bed_dim => "94", #String
|
65
|
+
:living_room_dim => "95", #String
|
66
|
+
:master_bed_dim => "96", #String
|
67
|
+
:fifth_bed_desc => "97", #String
|
68
|
+
:days_on_market => "101", #Integer
|
69
|
+
:entry_date => "104", #DateTime
|
70
|
+
:fence => "112", #String
|
71
|
+
:fireplaces => "113", #Integer
|
72
|
+
:converted_garage? => "120", #Boolean
|
73
|
+
:garages => "122", #Integer
|
74
|
+
:ground_mounted? => "125", #Boolean
|
75
|
+
:images => "129", #Integer
|
76
|
+
:internet_display => "130", #Boolean
|
77
|
+
:land_use => "132", #Integer
|
78
|
+
:last_transaction_code => "134", #String
|
79
|
+
:last_transaction_at => "135",#DateTime
|
80
|
+
:list_office_code => "137", #String
|
81
|
+
:listed_on => "138", #DateTime
|
82
|
+
:agentcode => "143", #String
|
83
|
+
:list_price => "144", #Float
|
84
|
+
:agent_member_id => "145", #String
|
85
|
+
:lot_sqft => "154", #Integer
|
86
|
+
:community => "155", #String
|
87
|
+
:listing_number => "163", #String
|
88
|
+
:occupancy_desc => "170", #String
|
89
|
+
:listing_office => "171", #String
|
90
|
+
:listing_office_phone => "172", #String
|
91
|
+
:original_list_price => "173",#Float
|
92
|
+
:parcel_number => "176", #String
|
93
|
+
:photo_instructions => "182", #String
|
94
|
+
:pools => "184", #Integer
|
95
|
+
:property_condition => "202", #String
|
96
|
+
:has_pool => "203", #Boolean
|
97
|
+
:record_deleted_at => "205", #DateTime
|
98
|
+
:record_deleted => "207", #Boolean
|
99
|
+
:buyer_broker => "211", #String
|
100
|
+
:elementary_school_2 => "213",#String
|
101
|
+
:highschool => "214", #String
|
102
|
+
:middle_school => "215", #String
|
103
|
+
:year_round_school => "216", #String
|
104
|
+
:buyer_agentcode => "218", #String
|
105
|
+
:sewer => "219", #String
|
106
|
+
# #Loft => "231", #Integer
|
107
|
+
:has_spa => "236", #Boolean
|
108
|
+
:active_properties => "242",
|
109
|
+
:idx_display => "1809",
|
110
|
+
:sqft => "2361"
|
111
|
+
}
|
112
|
+
end
|
113
|
+
|
114
|
+
# Take values like true and false, convert them to "Y" or "N". make collections into joint strings.
|
115
|
+
def value_map(value)
|
116
|
+
v = case value.class
|
117
|
+
when Array
|
118
|
+
value.join(',')
|
119
|
+
when Range
|
120
|
+
"#{value.first}-#{value.last}"
|
121
|
+
when Hash
|
122
|
+
if value.has_key?(:or)
|
123
|
+
"|#{value[:or].join(',')}"
|
124
|
+
elsif value.has_key?(:not)
|
125
|
+
"~#{value[:not].join(',')}"
|
126
|
+
end
|
127
|
+
when TrueClass
|
128
|
+
"Y" # TODO: figure out if this should be Y or Yes
|
129
|
+
when FalseClass
|
130
|
+
"N" # TODO: figure out if this should be N or No
|
131
|
+
else
|
132
|
+
value
|
133
|
+
end
|
134
|
+
v
|
135
|
+
end
|
136
|
+
|
137
|
+
end
|
138
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
# NOTE: This class is not really implemented yet.
|
2
|
+
|
3
|
+
module TouRETS
|
4
|
+
|
5
|
+
# VRImage is a multiple-view, possibly-interactive image related to the :resource
|
6
|
+
class VRImage
|
7
|
+
|
8
|
+
class << self
|
9
|
+
|
10
|
+
# Find the vrimage
|
11
|
+
# Use find("1234", :id => 1) to find the photo with ID 1 in the 1234 group
|
12
|
+
# Default it to return all of the photos.
|
13
|
+
def find(sysid, opts={})
|
14
|
+
limit = opts[:id] || "*"
|
15
|
+
[].tap do |photos|
|
16
|
+
TouRETS.current_connection.get_object(:resource => opts[:resource], :type => :VRImage, :location => false, :id => "#{sysid}:#{limit}") do |headers, content|
|
17
|
+
photos << new(headers, content)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
def initialize(headers, content)
|
26
|
+
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
30
|
+
end
|
data/tourets.gemspec
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
require File.expand_path('../lib/tourets/rails/version', __FILE__)
|
3
|
+
|
4
|
+
Gem::Specification.new do |gem|
|
5
|
+
gem.authors = ["Jeremy Woertink", "Justin Mitchell"]
|
6
|
+
gem.email = ["jeremywoertink@gmail.com", "jmitchell4140@gmail.com"]
|
7
|
+
gem.description = "TouRETS is a rails gem used to interface with multiple RETS using the ruby-rets gem"
|
8
|
+
gem.summary = "Use RETS with a LOT less hassle"
|
9
|
+
gem.homepage = ""
|
10
|
+
|
11
|
+
gem.files = `git ls-files`.split($\)
|
12
|
+
gem.executables = gem.files.grep(%r{^bin/}).map{ |f| File.basename(f) }
|
13
|
+
gem.test_files = gem.files.grep(%r{^(test|spec|features)/})
|
14
|
+
gem.name = "tourets"
|
15
|
+
gem.require_paths = ["lib"]
|
16
|
+
gem.version = TouRETS::Rails::VERSION
|
17
|
+
|
18
|
+
gem.add_dependency('ruby-rets', '2.0.5')
|
19
|
+
gem.add_dependency('railties', '>= 3.1')
|
20
|
+
gem.add_development_dependency('rspec')
|
21
|
+
gem.add_development_dependency('rails', '>= 3.1')
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,136 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tourets
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Jeremy Woertink
|
9
|
+
- Justin Mitchell
|
10
|
+
autorequire:
|
11
|
+
bindir: bin
|
12
|
+
cert_chain: []
|
13
|
+
date: 2012-11-16 00:00:00.000000000 Z
|
14
|
+
dependencies:
|
15
|
+
- !ruby/object:Gem::Dependency
|
16
|
+
name: ruby-rets
|
17
|
+
requirement: !ruby/object:Gem::Requirement
|
18
|
+
none: false
|
19
|
+
requirements:
|
20
|
+
- - '='
|
21
|
+
- !ruby/object:Gem::Version
|
22
|
+
version: 2.0.5
|
23
|
+
type: :runtime
|
24
|
+
prerelease: false
|
25
|
+
version_requirements: !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - '='
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
version: 2.0.5
|
31
|
+
- !ruby/object:Gem::Dependency
|
32
|
+
name: railties
|
33
|
+
requirement: !ruby/object:Gem::Requirement
|
34
|
+
none: false
|
35
|
+
requirements:
|
36
|
+
- - ! '>='
|
37
|
+
- !ruby/object:Gem::Version
|
38
|
+
version: '3.1'
|
39
|
+
type: :runtime
|
40
|
+
prerelease: false
|
41
|
+
version_requirements: !ruby/object:Gem::Requirement
|
42
|
+
none: false
|
43
|
+
requirements:
|
44
|
+
- - ! '>='
|
45
|
+
- !ruby/object:Gem::Version
|
46
|
+
version: '3.1'
|
47
|
+
- !ruby/object:Gem::Dependency
|
48
|
+
name: rspec
|
49
|
+
requirement: !ruby/object:Gem::Requirement
|
50
|
+
none: false
|
51
|
+
requirements:
|
52
|
+
- - ! '>='
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
type: :development
|
56
|
+
prerelease: false
|
57
|
+
version_requirements: !ruby/object:Gem::Requirement
|
58
|
+
none: false
|
59
|
+
requirements:
|
60
|
+
- - ! '>='
|
61
|
+
- !ruby/object:Gem::Version
|
62
|
+
version: '0'
|
63
|
+
- !ruby/object:Gem::Dependency
|
64
|
+
name: rails
|
65
|
+
requirement: !ruby/object:Gem::Requirement
|
66
|
+
none: false
|
67
|
+
requirements:
|
68
|
+
- - ! '>='
|
69
|
+
- !ruby/object:Gem::Version
|
70
|
+
version: '3.1'
|
71
|
+
type: :development
|
72
|
+
prerelease: false
|
73
|
+
version_requirements: !ruby/object:Gem::Requirement
|
74
|
+
none: false
|
75
|
+
requirements:
|
76
|
+
- - ! '>='
|
77
|
+
- !ruby/object:Gem::Version
|
78
|
+
version: '3.1'
|
79
|
+
description: TouRETS is a rails gem used to interface with multiple RETS using the
|
80
|
+
ruby-rets gem
|
81
|
+
email:
|
82
|
+
- jeremywoertink@gmail.com
|
83
|
+
- jmitchell4140@gmail.com
|
84
|
+
executables: []
|
85
|
+
extensions: []
|
86
|
+
extra_rdoc_files: []
|
87
|
+
files:
|
88
|
+
- .gitignore
|
89
|
+
- Gemfile
|
90
|
+
- LICENSE
|
91
|
+
- README.md
|
92
|
+
- Rakefile
|
93
|
+
- lib/tourets.rb
|
94
|
+
- lib/tourets/exceptions.rb
|
95
|
+
- lib/tourets/extensions/hash.rb
|
96
|
+
- lib/tourets/photo.rb
|
97
|
+
- lib/tourets/property.rb
|
98
|
+
- lib/tourets/rails.rb
|
99
|
+
- lib/tourets/rails/engine.rb
|
100
|
+
- lib/tourets/rails/railtie.rb
|
101
|
+
- lib/tourets/rails/version.rb
|
102
|
+
- lib/tourets/search.rb
|
103
|
+
- lib/tourets/utilities.rb
|
104
|
+
- lib/tourets/vrimage.rb
|
105
|
+
- tourets.gemspec
|
106
|
+
homepage: ''
|
107
|
+
licenses: []
|
108
|
+
post_install_message:
|
109
|
+
rdoc_options: []
|
110
|
+
require_paths:
|
111
|
+
- lib
|
112
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
113
|
+
none: false
|
114
|
+
requirements:
|
115
|
+
- - ! '>='
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
segments:
|
119
|
+
- 0
|
120
|
+
hash: 3840694011043471350
|
121
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
122
|
+
none: false
|
123
|
+
requirements:
|
124
|
+
- - ! '>='
|
125
|
+
- !ruby/object:Gem::Version
|
126
|
+
version: '0'
|
127
|
+
segments:
|
128
|
+
- 0
|
129
|
+
hash: 3840694011043471350
|
130
|
+
requirements: []
|
131
|
+
rubyforge_project:
|
132
|
+
rubygems_version: 1.8.24
|
133
|
+
signing_key:
|
134
|
+
specification_version: 3
|
135
|
+
summary: Use RETS with a LOT less hassle
|
136
|
+
test_files: []
|