rMeetup 1.0 → 2.0.1
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/LICENSE.md +21 -0
- data/README.md +65 -0
- data/Rakefile +6 -12
- data/lib/core_ext/string.rb +11 -0
- data/lib/rmeetup.rb +2 -63
- data/lib/rmeetup/client.rb +77 -0
- data/lib/rmeetup/errors.rb +15 -0
- data/lib/rmeetup/fetcher.rb +20 -33
- data/lib/rmeetup/fetcher/base.rb +66 -55
- data/lib/rmeetup/fetcher/open_events.rb +14 -0
- data/lib/rmeetup/fetcher/venues.rb +14 -0
- data/lib/rmeetup/poster.rb +17 -0
- data/lib/rmeetup/poster/base.rb +81 -0
- data/lib/rmeetup/{fetcher/comments.rb → poster/event_comment.rb} +5 -5
- data/lib/rmeetup/type.rb +2 -1
- data/lib/rmeetup/type/event.rb +21 -18
- data/lib/rmeetup/type/event_comment.rb +42 -0
- data/lib/rmeetup/type/rsvp.rb +9 -5
- data/lib/rmeetup/type/venue.rb +63 -0
- data/lib/rmeetup/version.rb +14 -0
- data/rmeetup.gemspec +34 -0
- data/spec/client_spec.rb +77 -29
- data/spec/fetcher_spec.rb +4 -4
- data/spec/fixtures/vcr_cassettes/fetching_cities.yml +358 -0
- data/spec/fixtures/vcr_cassettes/fetching_events.yml +54 -0
- data/spec/fixtures/vcr_cassettes/fetching_groups.yml +8627 -0
- data/spec/fixtures/vcr_cassettes/fetching_members.yml +3984 -0
- data/spec/fixtures/vcr_cassettes/fetching_photos.yml +54 -0
- data/spec/fixtures/vcr_cassettes/fetching_rsvps.yml +54 -0
- data/spec/spec_helper.rb +11 -69
- metadata +140 -101
- data/Manifest +0 -45
- data/README.rdoc +0 -34
- data/lib/rmeetup/fetcher/topics.rb +0 -14
- data/rMeetup.gemspec +0 -29
- data/spec/fetchers/base_spec.rb +0 -58
- data/spec/fetchers/cities_spec.rb +0 -18
- data/spec/fetchers/comments_spec.rb +0 -14
- data/spec/fetchers/events_spec.rb +0 -14
- data/spec/fetchers/groups_spec.rb +0 -14
- data/spec/fetchers/members_spec.rb +0 -14
- data/spec/fetchers/photos_spec.rb +0 -14
- data/spec/fetchers/rsvps_spec.rb +0 -14
- data/spec/fetchers/topics_spec.rb +0 -14
- data/spec/responses/cities.json +0 -1
- data/spec/responses/comments.json +0 -1
- data/spec/responses/error.json +0 -1
- data/spec/responses/events.json +0 -1
- data/spec/responses/groups.json +0 -1
- data/spec/responses/members.json +0 -1
- data/spec/responses/photos.json +0 -1
- data/spec/responses/rsvps.json +0 -1
- data/spec/responses/topics.json +0 -1
@@ -0,0 +1,17 @@
|
|
1
|
+
require "rmeetup/poster/base"
|
2
|
+
require "rmeetup/poster/event_comment"
|
3
|
+
|
4
|
+
module RMeetup
|
5
|
+
module Poster
|
6
|
+
|
7
|
+
def self.for(type)
|
8
|
+
name = type.to_s.camel_case.to_sym
|
9
|
+
if (name && constants.include?(name))
|
10
|
+
const_get(name).new
|
11
|
+
else
|
12
|
+
raise InvalidRequestTypeError.new(type)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,81 @@
|
|
1
|
+
require 'net/http'
|
2
|
+
require 'net/https'
|
3
|
+
|
4
|
+
module RMeetup
|
5
|
+
module Poster
|
6
|
+
class ApiError < StandardError
|
7
|
+
def initialize(error_message, request_url)
|
8
|
+
super "Meetup API Error: #{error_message} - API URL: #{request_url}"
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
class NoResponseError < StandardError
|
13
|
+
def initialize
|
14
|
+
super "No Response was returned from the Meetup API."
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
# == RMeetup::Fetcher::Base
|
19
|
+
#
|
20
|
+
# Base fetcher class that other fetchers
|
21
|
+
# will inherit from.
|
22
|
+
class Base
|
23
|
+
def initialize
|
24
|
+
@type = nil
|
25
|
+
end
|
26
|
+
|
27
|
+
# Fetch and parse a response
|
28
|
+
# based on a set of options.
|
29
|
+
# Override this method to ensure
|
30
|
+
# neccessary options are passed
|
31
|
+
# for the request.
|
32
|
+
def post(options = {})
|
33
|
+
url = build_url(options)
|
34
|
+
ret = post_response(url, options)
|
35
|
+
ret
|
36
|
+
end
|
37
|
+
|
38
|
+
protected
|
39
|
+
# OVERRIDE this method to format a result section
|
40
|
+
# as per Result type.
|
41
|
+
# Takes a result in a collection and
|
42
|
+
# formats it to be put back into the collection.
|
43
|
+
def format_result(result)
|
44
|
+
result
|
45
|
+
end
|
46
|
+
|
47
|
+
def build_url(options)
|
48
|
+
base_url
|
49
|
+
end
|
50
|
+
|
51
|
+
def base_url
|
52
|
+
"https://api.meetup.com/2/#{@type}/"
|
53
|
+
end
|
54
|
+
|
55
|
+
# Create a query string from an options hash
|
56
|
+
def params_for(options)
|
57
|
+
params = []
|
58
|
+
options.each do |key, value|
|
59
|
+
params << "#{key}=#{value}"
|
60
|
+
end
|
61
|
+
"?#{params.join("&")}"
|
62
|
+
end
|
63
|
+
|
64
|
+
# Encode a hash of options to be used as request parameters
|
65
|
+
def encode_options(options)
|
66
|
+
options.each do |key,value|
|
67
|
+
options[key] = URI.encode(value.to_s)
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
def post_response(url, options)
|
72
|
+
sslurl = URI.parse(url)
|
73
|
+
https = Net::HTTP.new(sslurl.host, sslurl.port)
|
74
|
+
https.use_ssl = true
|
75
|
+
req = Net::HTTP::Post.new(sslurl.path)
|
76
|
+
req.set_form_data(options)
|
77
|
+
resp = https.request(req)
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
@@ -1,14 +1,14 @@
|
|
1
1
|
module RMeetup
|
2
|
-
module
|
3
|
-
class
|
2
|
+
module Poster
|
3
|
+
class EventComment < Base
|
4
4
|
def initialize
|
5
|
-
@type = :
|
5
|
+
@type = :event_comment
|
6
6
|
end
|
7
7
|
|
8
8
|
# Turn the result hash into a Comment Class
|
9
9
|
def format_result(result)
|
10
|
-
RMeetup::Type::
|
10
|
+
RMeetup::Type::EventComment.new(result)
|
11
11
|
end
|
12
12
|
end
|
13
13
|
end
|
14
|
-
end
|
14
|
+
end
|
data/lib/rmeetup/type.rb
CHANGED
data/lib/rmeetup/type/event.rb
CHANGED
@@ -1,47 +1,50 @@
|
|
1
1
|
module RMeetup
|
2
2
|
module Type
|
3
|
-
|
3
|
+
|
4
4
|
# == RMeetup::Type::Event
|
5
5
|
#
|
6
6
|
# Data wraper for a Event fethcing response
|
7
7
|
# Used to access result attributes as well
|
8
8
|
# as progammatically fetch relative data types
|
9
9
|
# based on this event.
|
10
|
-
|
11
|
-
# Edited by Jason Berlinsky on 1/20/11 to allow for arbitrary data access
|
12
|
-
# See http://www.meetup.com/meetup_api/docs/events/ for available fields
|
13
|
-
|
10
|
+
|
14
11
|
class Event
|
15
|
-
|
16
|
-
attr_accessor :event
|
17
|
-
|
18
12
|
def initialize(event = {})
|
19
|
-
|
13
|
+
@event = event
|
20
14
|
end
|
21
|
-
|
15
|
+
attr_reader :event
|
16
|
+
alias_method :to_h, :event
|
17
|
+
|
22
18
|
def method_missing(id, *args)
|
23
|
-
|
19
|
+
if event.has_key?(id.id2name)
|
20
|
+
event[id.id2name]
|
21
|
+
else
|
22
|
+
fail NoMethodError.new('no method')
|
23
|
+
end
|
24
24
|
end
|
25
|
-
|
25
|
+
|
26
26
|
# Special accessors that need typecasting or other parsing
|
27
27
|
def id
|
28
|
-
|
28
|
+
event['id'].to_i
|
29
29
|
end
|
30
30
|
def lat
|
31
|
-
|
31
|
+
event['lat'].to_f
|
32
32
|
end
|
33
33
|
def lon
|
34
|
-
|
34
|
+
event['lon'].to_f
|
35
35
|
end
|
36
36
|
def rsvpcount
|
37
|
-
|
37
|
+
event['rsvpcount'].to_i
|
38
38
|
end
|
39
39
|
def updated
|
40
40
|
DateTime.parse(self.event['updated'])
|
41
41
|
end
|
42
42
|
def time
|
43
|
-
|
43
|
+
Time.at(self.event['time']/1000).to_datetime
|
44
|
+
end
|
45
|
+
def venue
|
46
|
+
OpenStruct.new( self.event['venue'] )
|
44
47
|
end
|
45
48
|
end
|
46
49
|
end
|
47
|
-
end
|
50
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
module RMeetup
|
2
|
+
module Type
|
3
|
+
|
4
|
+
# == RMeetup::Type::Comment
|
5
|
+
#
|
6
|
+
# Data wraper for a Comment fethcing response
|
7
|
+
# Used to access result attributes as well
|
8
|
+
# as progammatically fetch relative data types
|
9
|
+
# based on this comment.
|
10
|
+
|
11
|
+
# Edited by Jason Berlinsky on 1/20/11 to allow for arbitrary data access
|
12
|
+
# See http://www.meetup.com/meetup_api/docs/ew/comment/ for available fields
|
13
|
+
|
14
|
+
class EventComment
|
15
|
+
|
16
|
+
attr_accessor :comment
|
17
|
+
|
18
|
+
def initialize(comment = {})
|
19
|
+
self.comment = comment
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(id, *args)
|
23
|
+
return self.comment[id.id2name]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Special accessors that need typecasting or other parsing
|
27
|
+
|
28
|
+
def rating
|
29
|
+
return self.comment['rating'].to_i
|
30
|
+
end
|
31
|
+
def created
|
32
|
+
return DateTime.parse(self.comment['created'])
|
33
|
+
end
|
34
|
+
def lat
|
35
|
+
return self.comment['lat'].to_f
|
36
|
+
end
|
37
|
+
def lon
|
38
|
+
return self.comment['lon'].to_f
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/rmeetup/type/rsvp.rb
CHANGED
@@ -12,14 +12,18 @@ module RMeetup
|
|
12
12
|
# See http://www.meetup.com/meetup_api/docs/ew/rsvps/ for available fields
|
13
13
|
|
14
14
|
class Rsvp
|
15
|
-
attr_accessor :rsvp
|
16
|
-
|
17
15
|
def initialize(rsvp = {})
|
18
|
-
|
16
|
+
@rsvp = rsvp
|
19
17
|
end
|
18
|
+
attr_accessor :rsvp
|
19
|
+
alias_method :to_h, :rsvp
|
20
20
|
|
21
21
|
def method_missing(id, *args)
|
22
|
-
|
22
|
+
if rsvp.has_key?(id.id2name)
|
23
|
+
rsvp[id.id2name]
|
24
|
+
else
|
25
|
+
fail NoMethodError.new('no method')
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
# Special accessors that need typecasting or other parsing
|
@@ -32,4 +36,4 @@ module RMeetup
|
|
32
36
|
end
|
33
37
|
end
|
34
38
|
end
|
35
|
-
end
|
39
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
module RMeetup
|
2
|
+
module Type
|
3
|
+
|
4
|
+
# == RMeetup::Type::City
|
5
|
+
#
|
6
|
+
# Data wraper for a City fethcing response
|
7
|
+
# Used to access result attributes as well
|
8
|
+
# as progammatically fetch relative data types
|
9
|
+
# based on this city.
|
10
|
+
|
11
|
+
# Edited by Jason Berlinsky on 1/20/11 to allow for arbitrary data access
|
12
|
+
# See http://www.meetup.com/meetup_api/docs/cities/ for available fields
|
13
|
+
|
14
|
+
class Venue
|
15
|
+
|
16
|
+
attr_accessor :venue
|
17
|
+
|
18
|
+
def initialize(venue = {})
|
19
|
+
self.venue = venue
|
20
|
+
end
|
21
|
+
|
22
|
+
def method_missing(id, *args)
|
23
|
+
return self.venue[id.id2name]
|
24
|
+
end
|
25
|
+
|
26
|
+
# Special accessors that need typecasting or other parsing
|
27
|
+
|
28
|
+
def id
|
29
|
+
return self.venue['id'].to_i
|
30
|
+
end
|
31
|
+
def zip
|
32
|
+
return self.venue['zip'].to_s
|
33
|
+
end
|
34
|
+
def state
|
35
|
+
return self.venue['state'].to_s
|
36
|
+
end
|
37
|
+
def address_1
|
38
|
+
return self.venue['address_1'].to_s
|
39
|
+
end
|
40
|
+
def city
|
41
|
+
return self.venue['city'].to_s
|
42
|
+
end
|
43
|
+
def country
|
44
|
+
return self.venue['country'].to_s
|
45
|
+
end
|
46
|
+
def distance
|
47
|
+
return self.venue['distance'].to_i
|
48
|
+
end
|
49
|
+
def rating_count
|
50
|
+
return self.venue['rating_count'].to_i
|
51
|
+
end
|
52
|
+
def rating
|
53
|
+
return self.venue['rating'].to_s
|
54
|
+
end
|
55
|
+
def lat
|
56
|
+
return self.venue['lat'].to_f
|
57
|
+
end
|
58
|
+
def lon
|
59
|
+
return self.venue['lon'].to_f
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
data/rmeetup.gemspec
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
lib = File.expand_path('../lib/', __FILE__)
|
3
|
+
$:.unshift lib unless $:.include?(lib)
|
4
|
+
require 'rmeetup/version'
|
5
|
+
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.platform = Gem::Platform::RUBY
|
8
|
+
|
9
|
+
spec.name = 'rMeetup'
|
10
|
+
spec.description = 'meetup.com ruby client lib'
|
11
|
+
spec.authors = ['Jared Pace', 'Jason Berlinsky', 'Tommy Chan', 'Tanner Mares', 'Zishan Ahmad', 'Nikica Jokić']
|
12
|
+
spec.email = ['jdpace@github.com', 'jason@jasonberlinsky.com', 'tommytcchan@gmail.com', 'tannermares@gmail.com', 'me@zishanahmad.com', 'neektza@gmail.com']
|
13
|
+
spec.homepage = 'https://github.com/neektza/rmeetup'
|
14
|
+
spec.summary = 'A Ruby wrapper for the Meetup REST API v2'
|
15
|
+
|
16
|
+
spec.required_rubygems_version = '>= 1.3.6'
|
17
|
+
|
18
|
+
spec.add_dependency 'json', '~> 1.8'
|
19
|
+
spec.add_dependency 'buftok', '~> 0.2'
|
20
|
+
spec.add_dependency 'http', '~> 0.6'
|
21
|
+
spec.add_dependency 'http_parser.rb', '~> 0.6'
|
22
|
+
|
23
|
+
spec.add_development_dependency 'bundler', '~> 1.6'
|
24
|
+
|
25
|
+
spec.files = %w[LICENSE.md README.md Rakefile rmeetup.gemspec]
|
26
|
+
spec.licenses = %w[MIT]
|
27
|
+
spec.files += Dir.glob('lib/**/*.rb')
|
28
|
+
spec.files += Dir.glob('spec/**/*')
|
29
|
+
|
30
|
+
spec.test_files = Dir.glob('spec/**/*')
|
31
|
+
spec.require_paths = %w[lib]
|
32
|
+
|
33
|
+
spec.version = RMeetup::Version
|
34
|
+
end
|
data/spec/client_spec.rb
CHANGED
@@ -1,35 +1,83 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe RMeetup::Client
|
4
|
-
it 'should throw an error trying to search' do
|
5
|
-
lambda {
|
6
|
-
RMeetup::Client.fetch(:topics)
|
7
|
-
}.should raise_error(RMeetup::NotConfiguredError)
|
8
|
-
end
|
9
|
-
end
|
3
|
+
describe RMeetup::Client do
|
10
4
|
|
11
|
-
|
12
|
-
|
13
|
-
|
5
|
+
context 'provided no API key' do
|
6
|
+
it 'fails with an NotConfiguredError' do
|
7
|
+
expect { RMeetup::Client.new }.to raise_error(RMeetup::Error::NotConfiguredError)
|
8
|
+
end
|
14
9
|
end
|
15
|
-
|
16
|
-
it 'should throw an error' do
|
17
|
-
lambda {
|
18
|
-
RMeetup::Client.fetch(:clowns)
|
19
|
-
}.should raise_error(RMeetup::InvalidRequestTypeError)
|
20
|
-
end
|
21
|
-
end
|
22
10
|
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
11
|
+
context 'provided with proper options' do
|
12
|
+
|
13
|
+
describe "#fetch" do
|
14
|
+
let(:client) { RMeetup::Client.new({api_key: API_KEY}) }
|
15
|
+
|
16
|
+
it 'should throw an error if invalid data type is requested' do
|
17
|
+
expect do
|
18
|
+
client.fetch(:clowns)
|
19
|
+
end.to raise_error(RMeetup::Error::InvalidRequestTypeError)
|
20
|
+
end
|
21
|
+
|
22
|
+
context 'when fetching :groups' do
|
23
|
+
it 'returns a collection of Groups' do
|
24
|
+
VCR.use_cassette('fetching_groups') do
|
25
|
+
client.fetch(:groups, { topic: 'Ruby' }).each do |result|
|
26
|
+
result.should be_kind_of(RMeetup::Type::Group)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context 'when fetching :events' do
|
33
|
+
it 'returns a collection of Events' do
|
34
|
+
VCR.use_cassette('fetching_events') do
|
35
|
+
client.fetch(:events, { group_id: '95875' }).each do |result|
|
36
|
+
result.should be_kind_of(RMeetup::Type::Event)
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
context 'when fetching :rsvps' do
|
43
|
+
it 'returns a collection of RSVPs' do
|
44
|
+
VCR.use_cassette('fetching_rsvps') do
|
45
|
+
client.fetch(:rsvps, { event_id: '1342342' }).each do |result|
|
46
|
+
result.should be_kind_of(RMeetup::Type::Rsvp)
|
47
|
+
end
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
context 'when fetching :members' do
|
53
|
+
it 'returns a collection of Members' do
|
54
|
+
VCR.use_cassette('fetching_members') do
|
55
|
+
client.fetch(:members, { group_id: '95875' }).each do |result|
|
56
|
+
result.should be_kind_of(RMeetup::Type::Member)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
context 'when fetching :photos' do
|
63
|
+
it 'returns a collection of Photos' do
|
64
|
+
VCR.use_cassette('fetching_photos') do
|
65
|
+
client.fetch(:photos, { event_id: '13452536' }).each do |result|
|
66
|
+
result.should be_kind_of(RMeetup::Type::Photo)
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
context 'when fetching :cities' do
|
73
|
+
it 'returns a collection of Cities' do
|
74
|
+
VCR.use_cassette('fetching_cities') do
|
75
|
+
client.fetch(:cities).each do |result|
|
76
|
+
result.should be_kind_of(RMeetup::Type::City)
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
34
82
|
end
|
35
|
-
end
|
83
|
+
end
|