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