livingsocial2 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- 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
|