retailigence_ruby 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c402bae87c9588519c02a8854a8fda6c3d1cc539
4
+ data.tar.gz: db26dab02b2f714a992e690fefd75caf6613426a
5
+ SHA512:
6
+ metadata.gz: f9217ceddba1ff48fde254d1d8adaf4855ad1189ea1c1a390ef1dc5d6ea6f26f09d2230dfc5cb86da0d71e4f0393c7c8df0daa09af5858b4ee5491ec8d5fc26a
7
+ data.tar.gz: 048892f901ad61f3155cfe7c864b0cb7db1d3bd22e5b25590b99193f90fc67cd3e3b504f0dac669edc8c1639587b646ed509fea45da0d68fcb43f49bb5417fb5
data/.gitignore ADDED
@@ -0,0 +1,17 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in retailigence_ruby.gemspec
4
+ gemspec
data/LICENSE.txt ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Drew Tempelmeyer
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,81 @@
1
+ # Retailigence
2
+
3
+ Ruby library for interacting with [Retailigence](http://retailigence.com) API v2.1.
4
+
5
+ **NOTE:** You'll need an API key from Retailigence. You can [request one from here](http://www.retailigence.com/developers/request-key/).
6
+
7
+ ## Installation
8
+
9
+ Add this line to your application's Gemfile:
10
+
11
+ gem 'retailigence_ruby'
12
+
13
+ And then execute:
14
+
15
+ $ bundle
16
+
17
+ Or install it yourself as:
18
+
19
+ $ gem install retailigence_ruby
20
+
21
+ ## Configuring
22
+
23
+ Configuration only needs to be defined once.
24
+
25
+ ```
26
+ Retailigence.configure do |config|
27
+ config.api_key = 'your-api-key'
28
+ # config.production = false # Uncomment this line if you want to use the test environment
29
+ end
30
+ ```
31
+
32
+ If you're using Rails, it's recommended you place the above code in an initializer such as `config/initializers/retailigence.rb`.
33
+
34
+ ## Searching Products
35
+
36
+ Searching products will return a `SearchResult` with a collection of `Retailigence::Product` for the results. See the `Product` model for available attributes and methods.
37
+
38
+ ```
39
+ search_results = Retailigence::Product.search(
40
+ userlocation: '37.3323,-122.0312',
41
+ requestorid: 'test',
42
+ name: 'Xbox One'
43
+ )
44
+
45
+ search_results.each do |product|
46
+ puts product.name
47
+ end
48
+
49
+ # => "Xbox One - Console"
50
+ # => "FIFA 2014 (Xbox One)"
51
+ ```
52
+
53
+ ## Searching Locations
54
+
55
+ Searching locations will return a `SearchResult` with a collection of `Retailigence::Retailer` for the results. Locations are embedded within the retailer and can be accessed by calling `retailer.locations`. See the `Retailer` and `Location` models available attributes and methods.
56
+
57
+ ```
58
+ search_results = Retailigence::Location.search(
59
+ userlocation: '37.3323,-122.0312',
60
+ requestorid: 'test',
61
+ keywords: 'Best Buy'
62
+ )
63
+
64
+ search_results.each do |retailer|
65
+ puts retailer.name
66
+ puts retailer.locations
67
+ end
68
+
69
+ # => "Best Buy"
70
+ # => #<Retailigence::Location>
71
+ # => #<Retailigence::Location>
72
+ ```
73
+
74
+
75
+ ## Contributing
76
+
77
+ 1. Fork it ( https://github.com/drewtempelmeyer/retailigence_ruby/fork )
78
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
79
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
80
+ 4. Push to the branch (`git push origin my-new-feature`)
81
+ 5. Create new Pull Request
data/Rakefile ADDED
@@ -0,0 +1,25 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rdoc/task'
3
+ require 'rake/testtask'
4
+ require 'rubocop/rake_task'
5
+
6
+ Rubocop::RakeTask.new(:rubocop)
7
+
8
+ Rake::TestTask.new(:test) do |test|
9
+ test.libs << 'lib' << 'test'
10
+ test.pattern = 'test/test_*.rb'
11
+ test.verbose = false
12
+ end
13
+
14
+ task :console do
15
+ require 'irb'
16
+ require 'irb/completion'
17
+ require 'retailigence_ruby' # You know what to do.
18
+ ARGV.clear
19
+ IRB.start
20
+ end
21
+
22
+ RDoc::Task.new do |rdoc|
23
+ rdoc.main = 'README.md'
24
+ rdoc.rdoc_files.include('README.md', 'lib/**/*.rb')
25
+ end
@@ -0,0 +1,33 @@
1
+ require 'retailigence/version'
2
+ require 'retailigence/configuration'
3
+ require 'retailigence/exceptions'
4
+ require 'retailigence/model'
5
+ require 'retailigence/search_result'
6
+ require 'retailigence/product'
7
+ require 'retailigence/distance'
8
+ require 'retailigence/location'
9
+ require 'retailigence/retailer'
10
+ require 'retailigence/address'
11
+ require 'retailigence/image'
12
+ require 'retailigence/inventory'
13
+
14
+ module Retailigence
15
+ # Retailigence's API Version
16
+ API_VERSION = '2.1'
17
+
18
+ class << self
19
+ # Stores the current Retailigence Configuration
20
+ attr_accessor :configuration
21
+
22
+ # Configure Retailigence. See Configuration for available configuration options
23
+ #
24
+ # === Example
25
+ # Retailigence.configure do |config|
26
+ # config.api_key = 'your-retailigence-api-key'
27
+ # end
28
+ def configure
29
+ @configuration ||= Configuration.new
30
+ yield @configuration
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,14 @@
1
+ module Retailigence #:nodoc:
2
+ # Represents an address returned from Retailigence. The address is normally
3
+ # embedded within a Location object.
4
+ #
5
+ # === Attributes
6
+ # * <tt>address1</tt> - The street address of the Location
7
+ # * <tt>city</tt> - The city of the Location
8
+ # * <tt>state</tt> - The state of the Location
9
+ # * <tt>postal</tt> - The postal code (ZIP code) of the Location
10
+ # * <tt>country</tt> - The country of the Location
11
+ class Address < Model
12
+ attributes :address1, :city, :state, :postal, :country
13
+ end
14
+ end
@@ -0,0 +1,26 @@
1
+ module Retailigence #:nodoc:
2
+ # Configure Retailigence with your credentials.
3
+ #
4
+ # === Example
5
+ # Retailigence.configure do |config|
6
+ # config.api_key = 'yourapikeyhere'
7
+ # config.production = false # Use the test route
8
+ # end
9
+ class Configuration
10
+ # The API key issued to you by Retailigence
11
+ attr_accessor :api_key
12
+
13
+ # Wether or not to use the production Retailigence API
14
+ attr_writer :production
15
+
16
+ # Returns true if using the production API
17
+ def production?
18
+ @production == true
19
+ end
20
+
21
+ # Returns true if using the test API
22
+ def test?
23
+ !production?
24
+ end
25
+ end
26
+ end
@@ -0,0 +1,11 @@
1
+ module Retailigence #:nodoc:
2
+ # Representation of the distance from the <tt>userlocation</tt> and the
3
+ # respective Product or Location
4
+ #
5
+ # === Attributes
6
+ # * <tt>distance</tt> - A float value based on the distance <tt>units</tt>
7
+ # * <tt>units</tt> - String of distance measurement. Example: "miles", "meters", etc.
8
+ class Distance < Model
9
+ attributes :distance, :units
10
+ end
11
+ end
@@ -0,0 +1,5 @@
1
+ module Retailigence #:nodoc:
2
+ # Raised when Retailigence has not yet be configured.
3
+ # See Retailigence::configure.
4
+ class NotConfigured < StandardError; end
5
+ end
@@ -0,0 +1,10 @@
1
+ module Retailigence #:nodoc:
2
+ # A product image returned by the API
3
+ #
4
+ # === Attributes
5
+ # * <tt>image_name</tt> - The image name. Normally either "IMAGESMALL" or "IMAGELARGE"
6
+ # * <tt>link</tt> - The URL of the image
7
+ class Image < Model
8
+ attributes :imageName, :link
9
+ end
10
+ end
@@ -0,0 +1,33 @@
1
+ module Retailigence #:nodoc:
2
+ # Retrieve the inventory for a product at a specific location.
3
+ #
4
+ # === Attributes
5
+ # * <tt>product_id</tt> - The Product#id
6
+ # * <tt>retailer_id</tt> - The Retailer#id
7
+ # * <tt>location_id</tt> - The Location#id
8
+ # * <tt>price</tt> - The price
9
+ # * <tt>currency</tt> - The price's respective currency
10
+ # * <tt>quantity</tt> - Number of items in stock
11
+ # * <tt>quantity_text</tt> - Detail about the current stock
12
+ # * <tt>product_name</tt> - The Product#name
13
+ class Inventory < Model
14
+ attributes :product_id, :retailer_id, :location_id, :price, :currency,
15
+ :quantity, :quantityText, :productName
16
+
17
+ # Retrieve the inventory information for the provided <tt>product_id</tt>
18
+ # and <tt>location_id</tt>
19
+ #
20
+ # === Returns
21
+ # Inventory
22
+ def self.fetch(product_id = nil, location_id = nil)
23
+ params = {
24
+ productId: product_id,
25
+ locationId: location_id
26
+ }
27
+
28
+ results = get('inventory', params)['RetailigenceAPIResult']['results']
29
+
30
+ Inventory.new(results.first['ProductLocation'])
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,61 @@
1
+ module Retailigence #:nodoc:
2
+ # A location result from the Retailigence API
3
+ #
4
+ # === Attributes
5
+ # * <tt>id</tt> - Unique identifier for the location
6
+ # * <tt>timezone</tt> - Timezone of the location
7
+ # * <tt>distance</tt> - Distance object calculated based off the <tt>userlocation</tt> param
8
+ # * <tt>phone</tt> - Location's phone number
9
+ # * <tt>t_nav_link</tt> - URL to get directions from your current position to the location's position
10
+ # * <tt>location</tt> - Contains the latitude and longitude for the location. Using the <tt>latitude</tt> and <tt>longitude</tt> attributes are preferred
11
+ # * <tt>address</tt> - An Address object containing the physical postal address
12
+ # * <tt>hours</tt> - Colon separated operating hours
13
+ # * <tt>map_link</tt> - Google Maps URL for the location's address
14
+ # * <tt>name</tt> - Name of the location
15
+ # * <tt>retailer</tt> - Retailer
16
+ # * <tt>retlocationid</tt> - External location ID provided by the Retailer
17
+ # * <tt>latitude</tt> - The location's latitude
18
+ # * <tt>longitide</tt> - The location's longitude
19
+ class Location < Model
20
+ attributes :id, :timezone, :distance, :phone, :tNavLink, :location,
21
+ :address, :hours, :mapLink, :name, :retailer, :retlocationid, :latitude,
22
+ :longitude
23
+
24
+ # Search locations and retailers based on the <tt>params</tt> passed.
25
+ #
26
+ # === Params
27
+ # See the documentation from Retailigence for all possible parameters
28
+ #
29
+ # === Returns
30
+ # SearchResult with <tt>results</tt> being an array of Retailer
31
+ def self.search(params = {})
32
+ results = get('locations', params)
33
+
34
+ retailers = results['RetailigenceAPIResult']['results'].map do |result|
35
+ Retailer.new(result['Retailer'])
36
+ end
37
+
38
+ SearchResult.new(retailers)
39
+ end
40
+
41
+ def retailer=(retailer) #:nodoc:
42
+ @retailer = Retailer.new(retailer)
43
+ end
44
+
45
+ def distance=(distance) #:nodoc:
46
+ @distance = Distance.new(distance)
47
+ end
48
+
49
+ def address=(address) #:nodoc:
50
+ @address = Address.new(address)
51
+ end
52
+
53
+ # Convert the locations hash to latitude and longitude
54
+ def location=(location) #:nodoc:
55
+ @latitude = location['latitude']
56
+ @longitude = location['longitude']
57
+ @location = location
58
+ end
59
+
60
+ end
61
+ end
@@ -0,0 +1,84 @@
1
+ require 'typhoeus'
2
+ require 'json'
3
+
4
+ module Retailigence #:nodoc:
5
+ # The base for all API requests and models throughout the Retailigence library.
6
+ class Model
7
+ # Initialize an object with the provided <tt>params</tt>. For the available
8
+ # <tt>params</tt>, see the model's <tt>Attributes</tt>.
9
+ def initialize(params = {})
10
+ params.each do |key, value|
11
+ mapped_key = underscore(key)
12
+ send("#{mapped_key}=".to_sym, value) if safe_attribute?(mapped_key)
13
+ end
14
+ end
15
+
16
+ class << self
17
+ # Attributes safe for initialization
18
+ attr_accessor :safe_attributes
19
+
20
+ # Creates a list of safe attributes for assign using #initialize.
21
+ def attributes(*attrs)
22
+ @safe_attributes ||= []
23
+
24
+ attrs.each do |attr_name|
25
+ name = underscore(attr_name.to_s).to_sym
26
+
27
+ attr_accessor name
28
+ @safe_attributes << name
29
+ end
30
+ end
31
+
32
+ # Perform a request using Typhoeus.
33
+ #
34
+ # === Arguments
35
+ # * <tt>method</tt> - Symbol for the request method.
36
+ # * <tt>action</tt> - The path to request
37
+ # * <tt>params</tt> - Hash of params to send with the request
38
+ def request(method = :get, action = nil, params = {})
39
+ params[:apikey] = Retailigence.configuration.api_key
40
+ params[:format] = 'JSON'
41
+
42
+ url = "http://#{host}/v#{Retailigence::API_VERSION}/#{action}"
43
+
44
+ response = Typhoeus.send(method, url, params: params)
45
+ JSON.parse response.body
46
+ end
47
+
48
+ # Convenience method for performing a GET request. See #request
49
+ def get(action = nil, params = {})
50
+ request(:get, action, params)
51
+ end
52
+
53
+ # Convert the camelCase to its underscore/snake_case equivalent.
54
+ def underscore(word)
55
+ word.gsub(/([A-Z]+)([A-Z][a-z])/, '\1_\2')
56
+ .gsub(/([a-z\d])([A-Z])/, '\1_\2')
57
+ .tr('-', '_').downcase
58
+ end
59
+
60
+ private
61
+
62
+ def host
63
+ host =
64
+ if Retailigence.configuration.production?
65
+ 'api'
66
+ else
67
+ 'apitest'
68
+ end
69
+
70
+ "#{host}.retailigence.com"
71
+ end
72
+ end
73
+
74
+ private
75
+
76
+ def underscore(word)
77
+ self.class.underscore(word.to_s).to_sym
78
+ end
79
+
80
+ def safe_attribute?(key)
81
+ self.class.safe_attributes.include?(key)
82
+ end
83
+ end
84
+ end