livingsocial2 0.0.3 → 0.0.4
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/.DS_Store +0 -0
- data/README.md +31 -2
- data/lib/.DS_Store +0 -0
- data/lib/livingsocial2/deal.rb +66 -0
- data/lib/livingsocial2/mongo.rb +43 -0
- data/lib/livingsocial2/version.rb +1 -1
- data/lib/livingsocial2.rb +4 -5
- data/livingsocial2.gemspec +2 -1
- data/spec/deal_spec.rb +54 -0
- data/spec/spec_helper.rb +1 -0
- metadata +29 -13
- data/lib/livingsocial2/client.rb +0 -27
- data/lib/livingsocial2/daily_deal.rb +0 -31
- data/lib/livingsocial2/national_deal.rb +0 -31
data/.DS_Store
ADDED
Binary file
|
data/README.md
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
# Livingsocial2
|
2
2
|
|
3
|
-
|
3
|
+
This is the official unoffical ruby gem for Livingsocial. The gem is a wrapper for livingsocial's atom feed. We scrape the atom feed every 3 hours, so the deals should be current. There are some inconsistency with info on some deals, but this stems from inconsistencies within the atom feed - not much we can do there! The gem is very lightweight with only two files - Mongo.rb and Deal.rb. Mongo creates a connection to the mongo db that stores the gathered deals and Deal returns deal instances based on your entered criteria.
|
4
|
+
|
4
5
|
|
5
6
|
## Installation
|
6
7
|
|
@@ -18,7 +19,35 @@ Or install it yourself as:
|
|
18
19
|
|
19
20
|
## Usage
|
20
21
|
|
21
|
-
|
22
|
+
There are currently 2 class level methods for interacting with the gem.
|
23
|
+
### Method 1
|
24
|
+
Livingsocial2::Deal.find_by_ls_market(deal_type, market) #=> returns a collection of deals objects that match both the deal_type and the LS market of interest.
|
25
|
+
|
26
|
+
### Example call
|
27
|
+
Livingsocial2::Deal.find_by_ls_market(:local, 'Buffalo')
|
28
|
+
|
29
|
+
### Method 2
|
30
|
+
Livingsocial2::Deal.find_near(deal_type, lat, long, distance) #=> returns a collection of deal objects that match the deal type and that are within the specified distance of the lat and long passed in.
|
31
|
+
|
32
|
+
### Example call
|
33
|
+
Livingsocial2::Deal.find_near(:all, 40.7518481, -73.97551399999999, 1)
|
34
|
+
|
35
|
+
Distance is the radius desired, measured in miles. For example, the above example is asking for all the deals within a 1 mile radius of the passed in location (Lexington, NY).
|
36
|
+
|
37
|
+
If no distance is specified - it will default to 3 miles.
|
38
|
+
### What's the deal with deal_type
|
39
|
+
deal_type allows you to specify what LS vertical you are interested in. Currently, the atom feed supplies 4 types of deals.
|
40
|
+
#### 1. Local Deals
|
41
|
+
#### 2. At Home Deals
|
42
|
+
#### 3. Families Deals
|
43
|
+
#### 4. Gourmet Deals
|
44
|
+
|
45
|
+
### To specify a deal_type pass in one of the following symbols
|
46
|
+
#### 1. :local #=> local deals
|
47
|
+
#### 2. :at_home #=> at home deals
|
48
|
+
#### 3. :family #=> family deals
|
49
|
+
#### 4. :gourmet #=> gourmet deals
|
50
|
+
#### 5. :all #=> combination of all the above
|
22
51
|
|
23
52
|
## Contributing
|
24
53
|
|
data/lib/.DS_Store
ADDED
Binary file
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Livingsocial2
|
2
|
+
class Deal
|
3
|
+
DEAL_TYPES = { family: 'FamiliesDeal',
|
4
|
+
local: 'LocalDeal',
|
5
|
+
at_home: 'AtHomeDeal',
|
6
|
+
gourmet: 'GourmetDeal',
|
7
|
+
all: 'all' }
|
8
|
+
|
9
|
+
attr_accessor :ls_id, :published, :link, :title, :long_title, :deal_type,
|
10
|
+
:merchandise_type, :market_id, :market_name, :market_location,
|
11
|
+
:featureType, :country_code, :subtitle, :offer_ends_at,
|
12
|
+
:price, :value, :savings, :order_count, :merchant_type,
|
13
|
+
:image_url, :categories, :sold_out, :national, :description,
|
14
|
+
:details, :content, :merchant
|
15
|
+
|
16
|
+
def initialize(attributes)
|
17
|
+
self.ls_id = attributes['ls_id']
|
18
|
+
self.published = attributes['published']
|
19
|
+
self.link = attributes['link']
|
20
|
+
self.title = attributes['title']
|
21
|
+
self.long_title = attributes['long_title']
|
22
|
+
self.deal_type = attributes['deal_type']
|
23
|
+
self.merchandise_type = attributes['merchandise_type']
|
24
|
+
self.market_id = attributes['market_id']
|
25
|
+
self.market_name = attributes['market_name']
|
26
|
+
self.market_location = attributes['market_location']
|
27
|
+
self.featureType = attributes['featureType']
|
28
|
+
self.country_code = attributes['country_code']
|
29
|
+
self.subtitle = attributes['subtitle']
|
30
|
+
self.offer_ends_at = attributes['offer_ends_at']
|
31
|
+
self.price = attributes['price']
|
32
|
+
self.value = attributes['value']
|
33
|
+
self.savings = attributes['savings']
|
34
|
+
self.order_count = attributes['order_count']
|
35
|
+
self.merchant_type = attributes['merchant_type']
|
36
|
+
self.image_url = attributes['image_url']
|
37
|
+
self.categories = attributes['categories']
|
38
|
+
self.sold_out = attributes['sold_out']
|
39
|
+
self.national = attributes['national']
|
40
|
+
self.description = attributes['description']
|
41
|
+
self.details = attributes['details']
|
42
|
+
self.content = attributes['content']
|
43
|
+
self.merchant = attributes['merchant']
|
44
|
+
end
|
45
|
+
|
46
|
+
def self.find_deals_for(deal_type)
|
47
|
+
if deal_type == 'all'
|
48
|
+
LivingSocialDeal
|
49
|
+
else
|
50
|
+
LivingSocialDeal.where(deal_type: deal_type)
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
def self.find_by_ls_market(deal_type, market)
|
55
|
+
valid_deals = find_deals_for(DEAL_TYPES[deal_type]).where(title: market.capitalize)
|
56
|
+
valid_deals.map { |deal| new(deal.attributes) }
|
57
|
+
end
|
58
|
+
|
59
|
+
def self.find_near(deal_type, lat, long, distance=3)
|
60
|
+
valid_deals = find_deals_for(DEAL_TYPES[deal_type]).where(:market_location => { "$near" => [lat, long], "$maxDistance" => distance.fdiv(69) })
|
61
|
+
valid_deals.map { |deal| new(deal.attributes) }
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
|
@@ -0,0 +1,43 @@
|
|
1
|
+
require 'mongoid'
|
2
|
+
Mongoid::Config.from_hash({ "database" => 'app4574678',
|
3
|
+
'host' => 'pearl.mongohq.com',
|
4
|
+
'username' => 'ha',
|
5
|
+
'password' => 'hungry',
|
6
|
+
'port' => '27019' })
|
7
|
+
|
8
|
+
class LivingSocialDeal
|
9
|
+
include Mongoid::Document
|
10
|
+
|
11
|
+
field :ls_id
|
12
|
+
field :published
|
13
|
+
field :link
|
14
|
+
field :title
|
15
|
+
field :long_title
|
16
|
+
field :deal_type
|
17
|
+
field :merchandise_type
|
18
|
+
field :market_id
|
19
|
+
field :market_name
|
20
|
+
field :market_location, type: Array
|
21
|
+
field :featureType
|
22
|
+
field :country_code
|
23
|
+
field :subtitle
|
24
|
+
field :offer_ends_at
|
25
|
+
field :price
|
26
|
+
field :value
|
27
|
+
field :savings
|
28
|
+
field :order_count
|
29
|
+
field :merchant_type
|
30
|
+
field :image_url
|
31
|
+
field :categories
|
32
|
+
field :sold_out
|
33
|
+
field :national
|
34
|
+
field :description
|
35
|
+
field :details
|
36
|
+
field :content
|
37
|
+
field :merchant
|
38
|
+
|
39
|
+
index(
|
40
|
+
[[:market_location, Mongo::GEO2D]], background: true
|
41
|
+
)
|
42
|
+
|
43
|
+
end
|
data/lib/livingsocial2.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
|
+
require "livingsocial2/mongo"
|
1
2
|
require "livingsocial2/version"
|
2
|
-
require "livingsocial2/
|
3
|
-
require
|
4
|
-
|
5
|
-
require 'faraday'
|
6
|
-
require 'json'
|
3
|
+
require "livingsocial2/deal"
|
4
|
+
require 'mongoid'
|
5
|
+
|
data/livingsocial2.gemspec
CHANGED
@@ -15,6 +15,7 @@ Gem::Specification.new do |gem|
|
|
15
15
|
gem.require_paths = ["lib"]
|
16
16
|
gem.version = Livingsocial2::VERSION
|
17
17
|
|
18
|
-
gem.add_runtime_dependency("faraday")
|
19
18
|
gem.add_development_dependency('rspec')
|
19
|
+
gem.add_development_dependency('mongoid')
|
20
|
+
gem.add_development_dependency('bson_ext')
|
20
21
|
end
|
data/spec/deal_spec.rb
ADDED
@@ -0,0 +1,54 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Livingsocial2::Deal do
|
4
|
+
context 'When searching for a deal' do
|
5
|
+
describe '.find_deals_for(deal_type)' do
|
6
|
+
it 'returns an array of matching mongoid objects' do
|
7
|
+
deals = Livingsocial2::Deal.find_deals_for("AtHomeDeal")
|
8
|
+
deals.class.should be(Mongoid::Criteria)
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
describe '.find_by_ls_market(deal_type, market)' do
|
13
|
+
it 'returns an array of Livingsocial2::Deal objects' do
|
14
|
+
deals = Livingsocial2::Deal.find_by_ls_market(:all, 'Buffalo')
|
15
|
+
deals.first.class.should be(Livingsocial2::Deal)
|
16
|
+
end
|
17
|
+
|
18
|
+
it 'returns an empty array if invalide deal_type is entered' do
|
19
|
+
deals = Livingsocial2::Deal.find_by_ls_market(:happy_days, 'Buffalo')
|
20
|
+
deals.should be_empty
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'returns an empty array if invalide market is entered' do
|
24
|
+
deals = Livingsocial2::Deal.find_by_ls_market(:all, 'Icelandia')
|
25
|
+
deals.should be_empty
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
describe '.find_near(deal_type, lat, long, distance)' do
|
30
|
+
it 'returns Livingsocial2::Deal instances that are within the given distance' do
|
31
|
+
deals = Livingsocial2::Deal.find_near(:all, 40.7518481, -73.97551399999999, 1)
|
32
|
+
deals.first.class.should be(Livingsocial2::Deal)
|
33
|
+
end
|
34
|
+
|
35
|
+
it 'returns an empty array if no deals match given criteria' do
|
36
|
+
deals = Livingsocial2::Deal.find_near(:all, 39.904214, 116.407413, 1)
|
37
|
+
deals.should be_empty
|
38
|
+
end
|
39
|
+
|
40
|
+
it 'returns an empty array if lat and long are passed in as strings' do
|
41
|
+
deals = Livingsocial2::Deal.find_near(:all, "40.7518481", "-73.97551399999999", 1)
|
42
|
+
deals.should be_empty
|
43
|
+
end
|
44
|
+
|
45
|
+
context "when no distance is given, it defaults to a radius of 3 miles" do
|
46
|
+
it 'returns an array of Livingsocial2::Deal objects' do
|
47
|
+
deals = Livingsocial2::Deal.find_near(:all, 40.7518481, -73.97551399999999)
|
48
|
+
deals.first.class.should be(Livingsocial2::Deal)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require './lib/livingsocial2'
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: livingsocial2
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.4
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,22 +9,33 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-07-07 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
|
-
name:
|
16
|
-
requirement: &
|
15
|
+
name: rspec
|
16
|
+
requirement: &70181352393960 !ruby/object:Gem::Requirement
|
17
17
|
none: false
|
18
18
|
requirements:
|
19
19
|
- - ! '>='
|
20
20
|
- !ruby/object:Gem::Version
|
21
21
|
version: '0'
|
22
|
-
type: :
|
22
|
+
type: :development
|
23
23
|
prerelease: false
|
24
|
-
version_requirements: *
|
24
|
+
version_requirements: *70181352393960
|
25
25
|
- !ruby/object:Gem::Dependency
|
26
|
-
name:
|
27
|
-
requirement: &
|
26
|
+
name: mongoid
|
27
|
+
requirement: &70181352393280 !ruby/object:Gem::Requirement
|
28
|
+
none: false
|
29
|
+
requirements:
|
30
|
+
- - ! '>='
|
31
|
+
- !ruby/object:Gem::Version
|
32
|
+
version: '0'
|
33
|
+
type: :development
|
34
|
+
prerelease: false
|
35
|
+
version_requirements: *70181352393280
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: bson_ext
|
38
|
+
requirement: &70181352392840 !ruby/object:Gem::Requirement
|
28
39
|
none: false
|
29
40
|
requirements:
|
30
41
|
- - ! '>='
|
@@ -32,7 +43,7 @@ dependencies:
|
|
32
43
|
version: '0'
|
33
44
|
type: :development
|
34
45
|
prerelease: false
|
35
|
-
version_requirements: *
|
46
|
+
version_requirements: *70181352392840
|
36
47
|
description: Wrapper for the livingsocial atom feed
|
37
48
|
email:
|
38
49
|
- michael.v.verdi@gmail.com
|
@@ -40,17 +51,20 @@ executables: []
|
|
40
51
|
extensions: []
|
41
52
|
extra_rdoc_files: []
|
42
53
|
files:
|
54
|
+
- .DS_Store
|
43
55
|
- .gitignore
|
44
56
|
- Gemfile
|
45
57
|
- LICENSE
|
46
58
|
- README.md
|
47
59
|
- Rakefile
|
60
|
+
- lib/.DS_Store
|
48
61
|
- lib/livingsocial2.rb
|
49
|
-
- lib/livingsocial2/
|
50
|
-
- lib/livingsocial2/
|
51
|
-
- lib/livingsocial2/national_deal.rb
|
62
|
+
- lib/livingsocial2/deal.rb
|
63
|
+
- lib/livingsocial2/mongo.rb
|
52
64
|
- lib/livingsocial2/version.rb
|
53
65
|
- livingsocial2.gemspec
|
66
|
+
- spec/deal_spec.rb
|
67
|
+
- spec/spec_helper.rb
|
54
68
|
homepage: ''
|
55
69
|
licenses: []
|
56
70
|
post_install_message:
|
@@ -75,4 +89,6 @@ rubygems_version: 1.8.17
|
|
75
89
|
signing_key:
|
76
90
|
specification_version: 3
|
77
91
|
summary: Wrapper for the livingsocial atom feed
|
78
|
-
test_files:
|
92
|
+
test_files:
|
93
|
+
- spec/deal_spec.rb
|
94
|
+
- spec/spec_helper.rb
|
data/lib/livingsocial2/client.rb
DELETED
@@ -1,27 +0,0 @@
|
|
1
|
-
require 'faraday'
|
2
|
-
require 'json'
|
3
|
-
|
4
|
-
module Livingsocial2Api
|
5
|
-
class Client
|
6
|
-
BASE_URL = "http://50.116.44.82:3000"
|
7
|
-
|
8
|
-
attr_reader :connection
|
9
|
-
|
10
|
-
def initialize
|
11
|
-
@connection = Faraday.new(BASE_URL)
|
12
|
-
end
|
13
|
-
|
14
|
-
def data(location)
|
15
|
-
response = @connection.get do |req|
|
16
|
-
req.url "/api/v1/deals"
|
17
|
-
req.headers['Accepts'] = 'application/json'
|
18
|
-
req.params['division_name'] = clean_location(location)
|
19
|
-
end
|
20
|
-
JSON.parse(response.body)
|
21
|
-
end
|
22
|
-
|
23
|
-
def clean_location(location)
|
24
|
-
location.gsub("-", " ")
|
25
|
-
end
|
26
|
-
end
|
27
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Livingsocial2Api
|
2
|
-
class DailyDeal
|
3
|
-
attr_accessor :image_url, :url, :description, :title, :deal_price, :original_price
|
4
|
-
|
5
|
-
def initialize(attributes)
|
6
|
-
self.image_url = attributes[:image_url]
|
7
|
-
self.url = attributes[:url]
|
8
|
-
self.description = attributes[:description]
|
9
|
-
self.title = attributes[:title]
|
10
|
-
self.deal_price = attributes[:deal_price]
|
11
|
-
self.original_price = attributes[:original_price]
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.client
|
15
|
-
Livingsocial2Api::Client.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.deal_for(location)
|
19
|
-
client.data(location).map do |deal|
|
20
|
-
attributes = { image_url: deal['image_url'],
|
21
|
-
url: deal['original_url'],
|
22
|
-
description: deal['subtitle'],
|
23
|
-
title: deal['title'],
|
24
|
-
deal_price: deal['price_cents'],
|
25
|
-
original_price: deal['value_cents'],
|
26
|
-
}
|
27
|
-
new(attributes)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|
@@ -1,31 +0,0 @@
|
|
1
|
-
module Livingsocial2Api
|
2
|
-
class NationalDeal
|
3
|
-
attr_accessor :image_url, :url, :description, :title, :deal_price, :original_price
|
4
|
-
|
5
|
-
def initialize(attributes)
|
6
|
-
self.image_url = attributes[:image_url]
|
7
|
-
self.url = attributes[:url]
|
8
|
-
self.description = attributes[:description]
|
9
|
-
self.title = attributes[:title]
|
10
|
-
self.deal_price = attributes[:deal_price]
|
11
|
-
self.original_price = attributes[:original_price]
|
12
|
-
end
|
13
|
-
|
14
|
-
def self.client
|
15
|
-
Livingsocial2Api::Client.new
|
16
|
-
end
|
17
|
-
|
18
|
-
def self.deal(location='Nationwide')
|
19
|
-
client.data(location).map do |deal|
|
20
|
-
attributes = { image_url: deal['image_url'],
|
21
|
-
url: deal['original_url'],
|
22
|
-
description: deal['subtitle'],
|
23
|
-
title: deal['title'],
|
24
|
-
deal_price: deal['price_cents'],
|
25
|
-
original_price: deal['value_cents'],
|
26
|
-
}
|
27
|
-
new(attributes)
|
28
|
-
end
|
29
|
-
end
|
30
|
-
end
|
31
|
-
end
|