hungry 0.0.1 → 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.
- checksums.yaml +7 -0
- data/.gitignore +0 -1
- data/.rspec +1 -1
- data/.ruby-version +1 -0
- data/.travis.yml +19 -0
- data/Gemfile +7 -1
- data/Gemfile.lock +104 -0
- data/Rakefile +14 -0
- data/hungry.gemspec +0 -5
- data/lib/hungry.rb +20 -8
- data/lib/hungry/collection.rb +43 -9
- data/lib/hungry/collection/pagination.rb +17 -0
- data/lib/hungry/geolocation.rb +22 -2
- data/lib/hungry/location.rb +13 -8
- data/lib/hungry/menu.rb +53 -0
- data/lib/hungry/menu/category.rb +22 -0
- data/lib/hungry/menu/dish.rb +22 -0
- data/lib/hungry/menu/option.rb +9 -0
- data/lib/hungry/resource.rb +80 -12
- data/lib/hungry/response.rb +17 -0
- data/lib/hungry/review.rb +6 -6
- data/lib/hungry/site.rb +20 -6
- data/lib/hungry/tag.rb +6 -7
- data/lib/hungry/user.rb +77 -0
- data/lib/hungry/util.rb +44 -4
- data/lib/hungry/venue.rb +39 -18
- data/lib/hungry/venue/collection.rb +9 -0
- data/spec/hungry/geolocation_spec.rb +43 -43
- data/spec/hungry/util_spec.rb +18 -18
- data/spec/spec_helper.rb +0 -1
- metadata +20 -63
@@ -0,0 +1,22 @@
|
|
1
|
+
module Hungry
|
2
|
+
class Menu
|
3
|
+
class Category < Resource
|
4
|
+
|
5
|
+
attr_accessor :id, :name, :dishes, :menu
|
6
|
+
|
7
|
+
def dishes
|
8
|
+
@dishes ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def dishes=(new_dishes)
|
12
|
+
@dishes = new_dishes.map do |attributes|
|
13
|
+
dish = Menu::Dish.new(attributes)
|
14
|
+
dish.category = self
|
15
|
+
dish.data_source = data_source
|
16
|
+
dish
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Hungry
|
2
|
+
class Menu
|
3
|
+
class Dish < Resource
|
4
|
+
|
5
|
+
attr_accessor :name, :price, :description, :options, :photos, :category
|
6
|
+
|
7
|
+
def options
|
8
|
+
@options ||= []
|
9
|
+
end
|
10
|
+
|
11
|
+
def options=(new_options)
|
12
|
+
@options = new_options.map do |attributes|
|
13
|
+
option = Menu::Option.new(attributes)
|
14
|
+
option.dish = self
|
15
|
+
option.data_source = data_source
|
16
|
+
option
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
data/lib/hungry/resource.rb
CHANGED
@@ -1,32 +1,69 @@
|
|
1
|
-
require 'httparty'
|
1
|
+
require 'httparty' unless defined? HTTParty
|
2
2
|
|
3
3
|
module Hungry
|
4
4
|
class Resource
|
5
5
|
include HTTParty
|
6
6
|
|
7
|
-
attr_accessor :attributes
|
7
|
+
attr_accessor :attributes, :resources, :data_source
|
8
8
|
|
9
9
|
### CLASS METHODS:
|
10
10
|
|
11
11
|
def self.get(*args)
|
12
|
-
puts "[Resource]: GET #{args.map(&:inspect).join(', ')}"
|
13
12
|
self.base_uri Hungry.api_url
|
14
13
|
super
|
15
14
|
end
|
16
15
|
|
17
|
-
def self.belongs_to(resource, klass = Resource)
|
16
|
+
def self.belongs_to(resource, klass = 'Resource')
|
18
17
|
define_method resource do
|
19
|
-
|
20
|
-
|
21
|
-
klass.
|
18
|
+
@belongs_to ||= {}
|
19
|
+
@belongs_to[resource] ||= begin
|
20
|
+
klass = Kernel.const_get(klass) if klass.is_a?(String)
|
21
|
+
|
22
|
+
if attributes[resource].present?
|
23
|
+
resource = klass.new attributes[resource]
|
24
|
+
resource.data_source = data_source
|
25
|
+
resource
|
26
|
+
elsif url = resources[resource]
|
27
|
+
attributes = self.class.get url
|
28
|
+
resource = klass.new attributes
|
29
|
+
resource.data_source = url
|
30
|
+
resource
|
31
|
+
end
|
22
32
|
end
|
23
33
|
end
|
24
34
|
end
|
25
35
|
|
26
|
-
def self.has_many(resource, klass = Resource)
|
36
|
+
def self.has_many(resource, klass = 'Resource')
|
27
37
|
define_method resource do
|
28
|
-
|
29
|
-
|
38
|
+
@has_many ||= {}
|
39
|
+
@has_many[resource] ||= begin
|
40
|
+
klass = Kernel.const_get(klass) if klass.is_a?(String)
|
41
|
+
|
42
|
+
if url = resources[resource]
|
43
|
+
collection = klass.collection.from_url(url)
|
44
|
+
|
45
|
+
if attributes[resource].present?
|
46
|
+
collection.results = attributes[resource]
|
47
|
+
end
|
48
|
+
|
49
|
+
collection
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
def self.lazy_load(*attributes)
|
56
|
+
attributes.each do |attribute|
|
57
|
+
alias_method "#{attribute}_without_lazy_load".to_sym, attribute
|
58
|
+
define_method attribute do
|
59
|
+
result = send "#{attribute}_without_lazy_load".to_sym
|
60
|
+
|
61
|
+
if !result.present? && (canonical_data_source != data_source && canonical_data_source.present?)
|
62
|
+
reload
|
63
|
+
send "#{attribute}_without_lazy_load".to_sym
|
64
|
+
else
|
65
|
+
result
|
66
|
+
end
|
30
67
|
end
|
31
68
|
end
|
32
69
|
end
|
@@ -56,13 +93,23 @@ module Hungry
|
|
56
93
|
def find(id)
|
57
94
|
raise NoEndpointSpecified unless endpoint
|
58
95
|
|
59
|
-
|
96
|
+
uri = "#{endpoint}/#{id}"
|
97
|
+
|
98
|
+
Util.log "GET: #{uri}"
|
99
|
+
response = get uri
|
60
100
|
|
61
101
|
if response.code == 200
|
62
|
-
|
102
|
+
attributes = Util.parse_json(response.body)
|
103
|
+
resource = new(attributes)
|
104
|
+
resource.data_source = uri
|
105
|
+
resource
|
63
106
|
end
|
64
107
|
end
|
65
108
|
|
109
|
+
def first(n = 1)
|
110
|
+
collection.first(n)
|
111
|
+
end
|
112
|
+
|
66
113
|
def all(criteria = {})
|
67
114
|
collection.all(criteria)
|
68
115
|
end
|
@@ -89,5 +136,26 @@ module Hungry
|
|
89
136
|
end
|
90
137
|
end
|
91
138
|
end
|
139
|
+
|
140
|
+
def canonical_data_source
|
141
|
+
resources && resources[:self]
|
142
|
+
end
|
143
|
+
|
144
|
+
def reload
|
145
|
+
resource = self.class.find id
|
146
|
+
|
147
|
+
if resource
|
148
|
+
self.data_source = resource.data_source
|
149
|
+
initialize resource.attributes
|
150
|
+
else
|
151
|
+
self.data_source = nil
|
152
|
+
initialize Hash[*attributes.keys.map { |key| [key, nil] }]
|
153
|
+
end
|
154
|
+
|
155
|
+
@has_many = {}
|
156
|
+
@belongs_to = {}
|
157
|
+
|
158
|
+
self
|
159
|
+
end
|
92
160
|
end
|
93
161
|
end
|
data/lib/hungry/review.rb
CHANGED
@@ -1,8 +1,12 @@
|
|
1
|
-
require 'httparty'
|
2
|
-
|
3
1
|
module Hungry
|
4
2
|
class Review < Resource
|
5
3
|
|
4
|
+
### RESOURCES:
|
5
|
+
|
6
|
+
belongs_to :venue, 'Hungry::Venue'
|
7
|
+
|
8
|
+
has_many :responses, 'Hungry::Response'
|
9
|
+
|
6
10
|
### ATTRIBUTES:
|
7
11
|
|
8
12
|
### Review:
|
@@ -11,9 +15,5 @@ module Hungry
|
|
11
15
|
### Utility:
|
12
16
|
:created_at, :updated_at
|
13
17
|
|
14
|
-
### RESOURCES:
|
15
|
-
|
16
|
-
belongs_to :venue, Venue
|
17
|
-
|
18
18
|
end
|
19
19
|
end
|
data/lib/hungry/site.rb
CHANGED
@@ -3,19 +3,33 @@ module Hungry
|
|
3
3
|
|
4
4
|
self.endpoint = '/sites'
|
5
5
|
|
6
|
+
### FINDERS:
|
7
|
+
|
8
|
+
def self.with_hostname(hostname)
|
9
|
+
collection.all(hostname: hostname).first
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.for_country(country)
|
13
|
+
collection.all(country: country.id).first
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.default_site
|
17
|
+
collection.all(default: true).first
|
18
|
+
end
|
19
|
+
|
20
|
+
|
6
21
|
### ATTRIBUTES:
|
7
22
|
|
8
23
|
### Preview:
|
9
24
|
attr_accessor :id, :name, :title, :subtitle, :identifier, :default, :locale,
|
10
|
-
:url, :timezone, :country, :applications,
|
25
|
+
:url, :email, :support_email, :timezone, :country, :applications,
|
11
26
|
|
12
27
|
### Utility:
|
13
|
-
:resources,
|
28
|
+
:resources, :counters
|
14
29
|
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
collection.all(hostname: hostname).first
|
30
|
+
def hostname
|
31
|
+
uri = URI.parse(url) rescue nil
|
32
|
+
uri && uri.hostname
|
19
33
|
end
|
20
34
|
|
21
35
|
end
|
data/lib/hungry/tag.rb
CHANGED
@@ -3,6 +3,12 @@ module Hungry
|
|
3
3
|
|
4
4
|
self.endpoint = '/tags'
|
5
5
|
|
6
|
+
### RESOURCES:
|
7
|
+
|
8
|
+
has_many :venues, 'Hungry::Venue'
|
9
|
+
|
10
|
+
has_many :tags, 'Hungry::Tag'
|
11
|
+
|
6
12
|
### ATTRIBUTES:
|
7
13
|
|
8
14
|
### Tag:
|
@@ -10,12 +16,5 @@ module Hungry
|
|
10
16
|
|
11
17
|
### Utility:
|
12
18
|
:resources, :counters
|
13
|
-
|
14
|
-
### RESOURCES:
|
15
|
-
|
16
|
-
has_many :venues, Venue
|
17
|
-
|
18
|
-
has_many :tags, Tag
|
19
|
-
|
20
19
|
end
|
21
20
|
end
|
data/lib/hungry/user.rb
ADDED
@@ -0,0 +1,77 @@
|
|
1
|
+
module Hungry
|
2
|
+
class User < Resource
|
3
|
+
|
4
|
+
self.endpoint = '/users'
|
5
|
+
|
6
|
+
### ASSOCIATIONS:
|
7
|
+
|
8
|
+
has_many :reviews, 'Hungry::Review'
|
9
|
+
|
10
|
+
### FINDERS:
|
11
|
+
|
12
|
+
def self.with_ip(ip_address)
|
13
|
+
collection.all(ip: ip_address)
|
14
|
+
end
|
15
|
+
|
16
|
+
### CLASS METHODS:
|
17
|
+
|
18
|
+
def self.authenticate_with_persistence_token(persistence_token)
|
19
|
+
result = authenticate_via_api 'Cookie' => "persistence_token=#{persistence_token}"
|
20
|
+
return false unless result.present?
|
21
|
+
|
22
|
+
from_json(result)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.authenticate_with_perishable_token(perishable_token)
|
26
|
+
result = authenticate_via_api query: "perishable_token=#{perishable_token}"
|
27
|
+
return false unless result.present?
|
28
|
+
|
29
|
+
from_json(result)
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.from_json(json)
|
33
|
+
new Util.parse_json(json)
|
34
|
+
end
|
35
|
+
|
36
|
+
def self.authenticate_via_api(options = {})
|
37
|
+
options = {
|
38
|
+
path: '/account.json',
|
39
|
+
query: nil
|
40
|
+
}.merge(options)
|
41
|
+
|
42
|
+
url = URI.parse(Hungry.api_url)
|
43
|
+
url.path = options.delete(:path)
|
44
|
+
url.query = options.delete(:query)
|
45
|
+
|
46
|
+
http = Net::HTTP.new(url.host, url.port)
|
47
|
+
if url.scheme == 'https'
|
48
|
+
http.use_ssl = true
|
49
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
50
|
+
end
|
51
|
+
|
52
|
+
request = Net::HTTP::Get.new(url.request_uri, options)
|
53
|
+
response = http.request request
|
54
|
+
|
55
|
+
if response.code.to_i == 200
|
56
|
+
response.body
|
57
|
+
else
|
58
|
+
false
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
### ATTRIBUTES:
|
63
|
+
|
64
|
+
### Preview:
|
65
|
+
attr_accessor :id, :name, :avatar, :slug, :profile_url, :score, :bio,
|
66
|
+
:location, :email,
|
67
|
+
|
68
|
+
### FULL:
|
69
|
+
:gender, :birth_date, :website_url, :persistence_token,
|
70
|
+
:single_access_token, :maintainer_of, :connections,
|
71
|
+
:device_tokens, :admin,
|
72
|
+
|
73
|
+
### Utility:
|
74
|
+
:resources, :counters, :created_at, :updated_at, :activated_at
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
data/lib/hungry/util.rb
CHANGED
@@ -1,13 +1,23 @@
|
|
1
|
-
require 'cgi'
|
2
|
-
require 'rack/utils'
|
1
|
+
require 'cgi' unless defined?(CGI)
|
3
2
|
|
4
3
|
module Hungry
|
5
4
|
module Util
|
6
5
|
extend self
|
7
6
|
|
7
|
+
def log(message, type = :info)
|
8
|
+
if Hungry.logger
|
9
|
+
message = "[Hungry] #{message}"
|
10
|
+
Hungry.logger.send(type, message)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
def parse_json(json)
|
15
|
+
Hungry.json_parser.call(json)
|
16
|
+
end
|
17
|
+
|
8
18
|
def params_from_uri(uri)
|
9
19
|
uri = URI.parse(uri) unless uri.is_a?(URI)
|
10
|
-
|
20
|
+
parse_query(uri.query) if uri.query.present?
|
11
21
|
end
|
12
22
|
|
13
23
|
def uri_with_params(uri, params = {})
|
@@ -20,7 +30,37 @@ module Hungry
|
|
20
30
|
end
|
21
31
|
|
22
32
|
def is_numeric?(value)
|
23
|
-
value.to_s =~ /^[+-]?[\d]+(\.[\d]+){0,1}$/
|
33
|
+
!!(value.to_s =~ /^[+-]?[\d]+(\.[\d]+){0,1}$/)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
# Copied from rack/utils:
|
39
|
+
def unescape(s, encoding = Encoding::UTF_8)
|
40
|
+
URI.decode_www_form_component(s, encoding)
|
41
|
+
end
|
42
|
+
|
43
|
+
def parse_query(qs, d = nil, &unescaper)
|
44
|
+
unescaper ||= method(:unescape)
|
45
|
+
|
46
|
+
params = {}
|
47
|
+
|
48
|
+
(qs || '').split(d ? /[#{d}] */ : /[&;] */n).each do |p|
|
49
|
+
next if p.empty?
|
50
|
+
k, v = p.split('=', 2).map(&unescaper)
|
51
|
+
|
52
|
+
if cur = params[k]
|
53
|
+
if cur.class == Array
|
54
|
+
params[k] << v
|
55
|
+
else
|
56
|
+
params[k] = [cur, v]
|
57
|
+
end
|
58
|
+
else
|
59
|
+
params[k] = v
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
params
|
24
64
|
end
|
25
65
|
end
|
26
66
|
end
|
data/lib/hungry/venue.rb
CHANGED
@@ -6,27 +6,13 @@ module Hungry
|
|
6
6
|
|
7
7
|
### RESOURCES:
|
8
8
|
|
9
|
-
has_many :reviews, Review
|
9
|
+
has_many :reviews, 'Hungry::Review'
|
10
10
|
|
11
|
-
belongs_to :country, Country
|
11
|
+
belongs_to :country, 'Hungry::Country'
|
12
12
|
|
13
|
-
belongs_to :region, Region
|
13
|
+
belongs_to :region, 'Hungry::Region'
|
14
14
|
|
15
|
-
belongs_to :city, City
|
16
|
-
|
17
|
-
### ATTRIBUTES:
|
18
|
-
|
19
|
-
### Preview:
|
20
|
-
attr_accessor :id, :name, :category, :telephone, :fax, :website_url,
|
21
|
-
:tagline, :rating, :url, :address, :geolocation, :relevance,
|
22
|
-
:distance, :plan,
|
23
|
-
|
24
|
-
### Full:
|
25
|
-
:reachability, :staff, :prices, :capacity, :description,
|
26
|
-
:tags, :menus, :images, :maintainers, :awards, :opening_hours,
|
27
|
-
|
28
|
-
### Utility:
|
29
|
-
:resources, :counters, :created_at, :updated_at
|
15
|
+
belongs_to :city, 'Hungry::City'
|
30
16
|
|
31
17
|
### FINDERS:
|
32
18
|
|
@@ -50,8 +36,43 @@ module Hungry
|
|
50
36
|
collection.sort_by(sortable)
|
51
37
|
end
|
52
38
|
|
39
|
+
def self.maintainable_by(user_or_id)
|
40
|
+
collection.maintainable_by(user_or_id)
|
41
|
+
end
|
42
|
+
|
53
43
|
def self.paginate(page, options = {})
|
54
44
|
collection.paginate(page, options)
|
55
45
|
end
|
46
|
+
|
47
|
+
### ATTRIBUTES:
|
48
|
+
|
49
|
+
### Preview:
|
50
|
+
attr_accessor :id, :name, :category, :telephone, :fax, :website_url,
|
51
|
+
:tagline, :rating, :url, :address, :geolocation,
|
52
|
+
:currency_symbol, :relevance, :distance, :plan,
|
53
|
+
|
54
|
+
### Full:
|
55
|
+
:reachability, :staff, :prices, :capacity, :description,
|
56
|
+
:tags, :menus, :images, :maintainers, :awards, :opening_hours,
|
57
|
+
:holidays,
|
58
|
+
|
59
|
+
### Utility:
|
60
|
+
:counters, :created_at, :updated_at, :status
|
61
|
+
|
62
|
+
lazy_load :tags, :menus, :maintainers, :opening_hours, :holidays
|
63
|
+
|
64
|
+
def geolocation=(new_coordinates)
|
65
|
+
@geolocation = Geolocation.parse(new_coordinates).tap do |geo|
|
66
|
+
attributes[:geolocation] = geo
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def menus=(new_menus)
|
71
|
+
@menus = new_menus.map do |attributes|
|
72
|
+
menu = Menu.new(attributes)
|
73
|
+
menu.data_source = data_source
|
74
|
+
menu
|
75
|
+
end
|
76
|
+
end
|
56
77
|
end
|
57
78
|
end
|