eventbright 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.
Files changed (37) hide show
  1. data/.document +5 -0
  2. data/.gitignore +21 -0
  3. data/LICENSE +20 -0
  4. data/README.markdown +92 -0
  5. data/Rakefile +52 -0
  6. data/VERSION +1 -0
  7. data/lib/eventbright.rb +5 -0
  8. data/lib/eventbright/api_object.rb +180 -0
  9. data/lib/eventbright/api_object_class_methods.rb +117 -0
  10. data/lib/eventbright/api_object_collection.rb +60 -0
  11. data/lib/eventbright/api_object_relationships.rb +72 -0
  12. data/lib/eventbright/api_objects/attendee.rb +51 -0
  13. data/lib/eventbright/api_objects/discount.rb +62 -0
  14. data/lib/eventbright/api_objects/event.rb +79 -0
  15. data/lib/eventbright/api_objects/organizer.rb +26 -0
  16. data/lib/eventbright/api_objects/ticket.rb +63 -0
  17. data/lib/eventbright/api_objects/user.rb +45 -0
  18. data/lib/eventbright/api_objects/venue.rb +18 -0
  19. data/lib/eventbright/error.rb +14 -0
  20. data/lib/eventbright/main.rb +57 -0
  21. data/spec/eventbright/api_object_class_spec.rb +113 -0
  22. data/spec/eventbright/api_object_collection_spec.rb +67 -0
  23. data/spec/eventbright/api_object_relationship_spec.rb +23 -0
  24. data/spec/eventbright/api_object_spec.rb +15 -0
  25. data/spec/eventbright/user_spec.rb +141 -0
  26. data/spec/eventbright_api_faker.rb +18 -0
  27. data/spec/eventbright_spec.rb +36 -0
  28. data/spec/faked_responses/auth_required.json +1 -0
  29. data/spec/faked_responses/event_get.json +1 -0
  30. data/spec/faked_responses/user_get.json +1 -0
  31. data/spec/faked_responses/user_list_events.json +1 -0
  32. data/spec/faked_responses/user_list_organizers.json +1 -0
  33. data/spec/faked_responses/user_list_venues.json +1 -0
  34. data/spec/faked_responses/user_update.json +1 -0
  35. data/spec/spec.opts +1 -0
  36. data/spec/spec_helper.rb +35 -0
  37. metadata +132 -0
@@ -0,0 +1,18 @@
1
+ module EventBright
2
+
3
+ class Venue < ApiObject
4
+
5
+ updatable :name
6
+ updatable :address, :address_2
7
+ updatable :city, :region, :postal_code
8
+ updatable :country, :country_code
9
+ readable :latitude, :longitude
10
+ requires :name
11
+ renames :name => :venue, :address => :adress, :address_2 => :adress_2
12
+ ignores :"Lat-Long"
13
+
14
+ def state; region; end # Region is same as state in US
15
+ def state=(val); region= val; end # Region is same as state in US
16
+ end
17
+ class VenueCollection < ApiObjectCollection; collection_for Venue; end
18
+ end
@@ -0,0 +1,14 @@
1
+ module EventBright
2
+ class Error < Exception
3
+ attr_accessor :type, :response, :message
4
+ def initialize(message, type = "", response = nil)
5
+ @type = type
6
+ @response = response
7
+ @message = message
8
+ super(message)
9
+ end
10
+ def inspect
11
+ "<EventBright::Error(#{type}): #{message}>"
12
+ end
13
+ end
14
+ end
@@ -0,0 +1,57 @@
1
+ require 'httparty'
2
+
3
+ module EventBright
4
+ EVENTBRITE_TIME_STRING = '%Y-%m-%d %H:%M:%S'
5
+ def self.setup(app_key = "YmRmMmMxMjYzNDYy", debug = false)
6
+ @app_key = app_key
7
+ @debug = debug
8
+ end
9
+
10
+ def self.debug!
11
+ @debug = true
12
+ end
13
+
14
+ def self.call(function, opts = {})
15
+ @app_key ||= "YmRmMmMxMjYzNDYy"
16
+ opts[:app_key] = @app_key
17
+ if opts[:user].is_a? EventBright::User
18
+ # Allow passing User object instead of user auth info.
19
+ u = opts.delete :user
20
+ opts.merge!(u.auth)
21
+ end
22
+ debug "\tSending /#{function}\t\t(#{opts.inspect})"
23
+ response = API.do_post("/#{function}", :body => opts)
24
+ debug "\tResponse /#{function}\t\t#{response.inspect}"
25
+ response
26
+ end
27
+
28
+
29
+ def self.debug(msg)
30
+ puts msg if debug?
31
+ end
32
+
33
+ def self.debug?
34
+ @debug.nil? ? false : @debug
35
+ end
36
+
37
+ def self.formatted_time(date)
38
+ case date
39
+ when Time
40
+ date.strftime(EVENTBRITE_TIME_STRING)
41
+ when String
42
+ Time.parse(String).strftime(EVENTBRITE_TIME_STRING)
43
+ end
44
+ end
45
+
46
+ class API
47
+ include HTTParty
48
+ base_uri "https://www.eventbrite.com/json/"
49
+ def self.do_post(function, opts = {})
50
+ response = post(function, opts)
51
+ if response["error"]
52
+ raise Error.new(response["error"]["error_message"], response["error"]["error_type"], response)
53
+ end
54
+ response
55
+ end
56
+ end
57
+ end
@@ -0,0 +1,113 @@
1
+ share_examples_for "EventBright::ApiObject class methods" do
2
+ it "should have a singlet name same as class name, or set singlet_name" do
3
+ EventBright::Foo.singlet_name.should == 'foo'
4
+ EventBright::Bar.singlet_name.should == 'baz'
5
+ end
6
+ it "should add an s to the singlet name to get the plural, or use set plural" do
7
+ EventBright::Foo.plural_name.should == 'foos'
8
+ EventBright::Bar.plural_name.should == 'bazzes'
9
+ end
10
+ it "should have ignores" do
11
+ EventBright::Foo.ignores.should == []
12
+ EventBright::Foo.ignores :foo, :bar
13
+ EventBright::Foo.ignores :baz
14
+ EventBright::Foo.ignores.should == [:foo, :bar, :baz]
15
+ end
16
+ it "should have requires" do
17
+ EventBright::Foo.requires.should == []
18
+ EventBright::Foo.requires :foo, :bar
19
+ EventBright::Foo.requires :baz
20
+ EventBright::Foo.requires.should == [:foo, :bar, :baz]
21
+ end
22
+ it "should have reformats" do
23
+ EventBright::Foo.reformats.should == []
24
+ EventBright::Foo.reformats :foo, :bar
25
+ EventBright::Foo.reformats :baz
26
+ EventBright::Foo.reformats.should == [:foo, :bar, :baz]
27
+ end
28
+ it "should have renames" do
29
+ EventBright::Foo.renames.should == {}
30
+ EventBright::Foo.renames :foo => :bar, :quux => :wobble
31
+ EventBright::Foo.renames :baz => :qux
32
+ EventBright::Foo.renames.should == {:foo => :bar, :baz => :qux, :quux => :wobble}
33
+ end
34
+
35
+ it "should have updatable" do
36
+ f = EventBright::Foo.new(false, {})
37
+ f.should_not respond_to(:attr_1)
38
+ f.should_not respond_to(:attr_2)
39
+ f.should_not respond_to(:attr_3)
40
+ f.should_not respond_to(:attr_3=)
41
+ EventBright::Foo.updatable :attr_1, :attr_2
42
+ EventBright::Foo.updatable :attr_3
43
+ f.should respond_to(:attr_1)
44
+ f.should respond_to(:attr_2)
45
+ f.should respond_to(:attr_3)
46
+ f.should respond_to(:attr_3=)
47
+ f.should_receive(:attribute_set).with(:attr_3, :banana, false)
48
+ f.attr_3 = :banana
49
+ end
50
+ it "should have readable" do
51
+ f = EventBright::Foo.new(false, {})
52
+ f.should_not respond_to(:attr_4)
53
+ f.should_not respond_to(:attr_5)
54
+ f.should_not respond_to(:attr_6)
55
+ f.should_not respond_to(:attr_6=)
56
+ EventBright::Foo.readable :attr_4, :attr_5
57
+ EventBright::Foo.readable :attr_6
58
+ f.should respond_to(:attr_4)
59
+ f.should respond_to(:attr_5)
60
+ f.should respond_to(:attr_6)
61
+ f.should respond_to(:attr_6=)
62
+ f.should_receive(:attribute_set).with(:attr_6, :banana, true)
63
+ f.attr_6 = :banana
64
+ end
65
+ it "should have a readable_date" do
66
+ f = EventBright::Foo.new(false, {})
67
+ time = Time.parse("4/1/2010 13:37")
68
+ EventBright::Foo.readable_date :attr_7, :attr_8
69
+ f.attr_7 = f.attr_8 = "4/1/2010 13:37"
70
+ f.attributes.should == {:attr_7 => time, :attr_8 => time}
71
+ f.attr_7.should == EventBright.formatted_time(time)
72
+ end
73
+ it "should have an updatable_date" do
74
+ f = EventBright::Foo.new(false, {})
75
+ time = Time.parse("4/1/2010 13:37")
76
+ EventBright::Foo.updatable_date :attr_9, :attr_0
77
+ f.attr_9 = f.attr_0 = "4/1/2010 13:37"
78
+ f.attributes.should == {:attr_9 => time, :attr_0 => time}
79
+ f.attr_9.should == EventBright.formatted_time(time)
80
+ end
81
+ it "should have a remap method" do
82
+ f = EventBright::Foo.new(false, {})
83
+ f.should_not respond_to(:banana)
84
+ EventBright::Foo.remap :banana => :attr_1
85
+ f.should respond_to(:banana)
86
+ f.should_receive(:attr_1=).once
87
+ f.should_receive(:attr_1).once
88
+ f.banana = :banana
89
+ f.banana
90
+ end
91
+
92
+ it "should have the #has method" do
93
+ f = EventBright::Foo.new(false, {})
94
+ f.should_not respond_to(:bar)
95
+ f.class.relations.should == {}
96
+ EventBright::Foo.has :bar => EventBright::Bar
97
+ f.should respond_to(:bar)
98
+ f.should respond_to(:bar=)
99
+ f.class.relations.should have(1).relation
100
+ f.class.relations[:bar].should == EventBright::Bar
101
+ end
102
+
103
+ it "should have the #collection method" do
104
+ f = EventBright::Foo.new(false, {})
105
+ f.should_not respond_to(:baz)
106
+ f.class.collections.should == {}
107
+ EventBright::Foo.collection :baz => EventBright::BananaBunch
108
+ f.should respond_to(:baz)
109
+ f.should respond_to(:baz=)
110
+ f.class.collections.should have(1).relation
111
+ f.class.collections[:baz].should == EventBright::BananaBunch
112
+ end
113
+ end
@@ -0,0 +1,67 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe EventBright::ApiObjectCollection do
4
+ before(:all) do
5
+ @b = EventBright::BananaBunch.new(false, [{"banana" => {:val => 1}}, {"banana" => {:val => 2}}])
6
+ end
7
+ context "collection functions" do
8
+ it "should pass through standard Array methods" do
9
+ lambda{
10
+ @b.first
11
+ @b.last
12
+ @b[0]
13
+ }.should_not raise_error
14
+ end
15
+ it "should iterate through collection and check dirtyness for #dirty?" do
16
+ @b.first.should_receive(:dirty?).once.and_return(false)
17
+ @b.last.should_receive(:dirty?).once.and_return(false)
18
+ @b.dirty?.should == false
19
+ @b.first.should_receive(:dirty?).once.and_return(true)
20
+ @b.last.should_receive(:dirty?).once.and_return(false)
21
+ @b.dirty?.should == true
22
+ end
23
+ it "should iterate through collection and not save any objects if clean" do
24
+ @b.first.should_receive(:dirty?).once.and_return(false)
25
+ @b.first.should_not_receive(:save)
26
+ @b.last.should_receive(:dirty?).once.and_return(false)
27
+ @b.last.should_not_receive(:save)
28
+ @b.save
29
+ end
30
+ it "should iterate through collection and save dirty objects only" do
31
+ @b.first.should_receive(:dirty?).once.ordered.and_return(true)
32
+ @b.first.should_receive(:save).once.ordered.and_return(true)
33
+ @b.last.should_receive(:dirty?).once.and_return(false)
34
+ @b.last.should_not_receive(:save)
35
+ @b.save
36
+ end
37
+ end
38
+
39
+ context "class definitions" do
40
+ it "should have a singlet name same as class name" do
41
+ EventBright::BananaBunch.singlet_name.should == 'banana'
42
+ EventBright::BradyBunch.singlet_name.should == 'bob'
43
+ end
44
+ it "should add an s to the singlet name to get the plural" do
45
+ EventBright::BananaBunch.plural_name.should == 'bananas'
46
+ EventBright::BradyBunch.plural_name.should == 'joe'
47
+ end
48
+ it "should know what class it collects" do
49
+ EventBright::BananaBunch.collection_for.should eql EventBright::Banana
50
+ EventBright::BradyBunch.collection_for.should eql EventBright::Brady
51
+ end
52
+ it "should have a getter" do
53
+ EventBright::BananaBunch.getter.should == "user_list_bananas"
54
+ EventBright::BradyBunch.getter.should == :foo_bar_baz
55
+ end
56
+ end
57
+
58
+ it "should map an array of values on initialization" do
59
+ @b.first.val.should == 1
60
+ @b.last.val.should == 2
61
+ end
62
+
63
+ it "should silently reject useless objects (ones without required attributes, empty ones)" do
64
+ @bb = EventBright::BradyBunch.new(false, [{"bob" => {:foo => 1}}, {"bob" => {}}, {"bob" => {:bar => 3}}])
65
+ @bb.size.should == 1
66
+ end
67
+ end
@@ -0,0 +1,23 @@
1
+ share_examples_for "EventBright::ApiObject relationship methods" do
2
+ before :all do
3
+ @bar = EventBright::Bar.new
4
+ end
5
+ it "should be able to get relations" do
6
+ @bar.relations.should == {}
7
+ @bar.relations = {:banana => EventBright::Banana.new}
8
+ @bar.banana.should be_an_instance_of(EventBright::Banana)
9
+ @bar.relations.should have(1).items
10
+ @bar.should_receive(:relation_get).with(:banana)
11
+ lambda{
12
+ @bar.banana
13
+ }.should_not raise_error
14
+ end
15
+ it "should be able to get collections" do
16
+ @bar.collections.should == {}
17
+ @bar.collections = {:bananas => EventBright::BananaBunch.new}
18
+ @bar.bananas.should be_an_instance_of(EventBright::BananaBunch)
19
+ @bar.collections.should have(1).items
20
+ @bar.should_receive(:collection_get).with(:bananas)
21
+ lambda{@bar.bananas}.should_not raise_error
22
+ end
23
+ end
@@ -0,0 +1,15 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+ require File.expand_path(File.dirname(__FILE__) + '/api_object_class_spec')
3
+ require File.expand_path(File.dirname(__FILE__) + '/api_object_relationship_spec')
4
+ describe EventBright::ApiObject do
5
+ before(:all) do
6
+
7
+ end
8
+ describe "class methods" do
9
+ it_should_behave_like "EventBright::ApiObject class methods"
10
+ end
11
+ describe "relationships" do
12
+ it_should_behave_like "EventBright::ApiObject relationship methods"
13
+ end
14
+
15
+ end
@@ -0,0 +1,141 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/../spec_helper')
2
+
3
+ describe EventBright::User do
4
+ before(:all) do
5
+ EventBright.setup("key")
6
+ end
7
+
8
+ it "should load from API on initialization" do
9
+ EventBright::API.should_receive(:do_post).with("/user_get", anything).and_return(fake_response("/user_get"))
10
+ u = EventBright::User.new("fake_key")
11
+ u.attribute_get(:email).should == "david@orangesparkleball.com"
12
+ u.attribute_get(:password).should be_nil
13
+ u.attribute_get(:user_key).should_not be_nil
14
+ end
15
+
16
+ it "should not call API if no_load set in initialization" do
17
+ EventBright::API.should_not_receive(:do_post)
18
+ EventBright::User.new("fake_key", true)
19
+ end
20
+
21
+ it "should accept an array of [email, password] as authentication" do
22
+ EventBright::API.should_receive(:do_post).with("/user_get", :body => hash_including("password", "user")).and_return(fake_response("/user_get"))
23
+ u = EventBright::User.new(["fake_user", "fake_pass"])
24
+ u.attribute_get(:email).should_not be_nil
25
+ end
26
+
27
+ it "should return a user auth hash" do
28
+ u = EventBright::User.new("fake_key", true)
29
+ u2 = EventBright::User.new(["fake_email", "fake_pass"], true)
30
+ u.auth.should_not == u2.auth
31
+ u.auth["user_key"].should_not be_nil
32
+ u2.auth["user_key"].should be_nil
33
+ u.auth["user"].should be_nil
34
+ u2.auth["user"].should_not be_nil
35
+ end
36
+
37
+ it "should retrieve venues" do
38
+ u = EventBright::User.new("fake_key", true)
39
+ EventBright::API.should_receive(:do_post).with("/user_list_venues", anything).and_return(fake_response("/user_list_venues"))
40
+ v = u.venues
41
+ v.should be_an EventBright::VenueCollection
42
+ v.should_not be_empty
43
+ end
44
+
45
+ it "should cache venues" do
46
+ u = EventBright::User.new("fake_key", true)
47
+ EventBright::API.should_receive(:do_post).once.with("/user_list_venues", anything).and_return(fake_response("/user_list_venues"))
48
+ u.venues
49
+ u.venues
50
+ EventBright::API.should_receive(:do_post).once.with("/user_list_venues", anything).and_return(fake_response("/user_list_venues"))
51
+ u.dirty_venues!
52
+ u.venues
53
+ end
54
+
55
+ it "should retrieve organizers" do
56
+ u = EventBright::User.new("fake_key", true)
57
+ EventBright::API.should_receive(:do_post).with("/user_list_organizers", anything).and_return(fake_response("/user_list_organizers"))
58
+ o = u.organizers
59
+ o.should be_an EventBright::OrganizerCollection
60
+ o.should_not be_empty
61
+ end
62
+
63
+ it "should cache organizers" do
64
+ u = EventBright::User.new("fake_key", true)
65
+ EventBright::API.should_receive(:do_post).once.with("/user_list_organizers", anything).and_return(fake_response("/user_list_organizers"))
66
+ u.organizers
67
+ u.organizers
68
+ EventBright::API.should_receive(:do_post).once.with("/user_list_organizers", anything).and_return(fake_response("/user_list_organizers"))
69
+ u.dirty_organizers!
70
+ u.organizers
71
+ end
72
+
73
+ it "should retrieve events" do
74
+ u = EventBright::User.new("fake_key", true)
75
+ EventBright::API.should_receive(:do_post).with("/user_list_events", anything).and_return(fake_response("/user_list_events"))
76
+ e = u.events
77
+ e.should be_an EventBright::EventCollection
78
+ e.should_not be_empty
79
+ end
80
+
81
+ it "should cache events" do
82
+ u = EventBright::User.new("fake_key", true)
83
+ EventBright::API.should_receive(:do_post).once.with("/user_list_events", anything).and_return(fake_response("/user_list_events"))
84
+ u.events
85
+ u.events
86
+ EventBright::API.should_receive(:do_post).once.with("/user_list_events", anything).and_return(fake_response("/user_list_events"))
87
+ u.dirty_events!
88
+ u.events
89
+ end
90
+
91
+ it "should call init_with_hash and call API if calling load" do
92
+ u = EventBright::User.new("fake_key", true)
93
+ EventBright::API.should_receive(:do_post).with("/user_get", anything).and_return(fake_response("/user_get"))
94
+ u.should_receive(:init_with_hash).with(instance_of(Hash), anything)
95
+ u.load
96
+ end
97
+
98
+ it "should get an init_with_hash method" do
99
+ u = EventBright::User.new("fake_key", true)
100
+ h = fake_response("/user_get")["user"]
101
+ u.init_with_hash(h)
102
+ u.email.should_not be_nil
103
+ end
104
+
105
+ it "should load attributes when calling load" do
106
+ u = EventBright::User.new("fake_key", true)
107
+ u.email.should be_nil
108
+ u.load
109
+ u.email.should_not be_nil
110
+ end
111
+
112
+ it "should have a dirty-tracking update hash" do
113
+ u = EventBright::User.new("fake_key", true)
114
+ u.updatable_hash.should be_empty
115
+ u.load!
116
+ u.updatable_hash.size.should == 1
117
+ u.updatable_hash[:id].should_not be_nil
118
+ u.email = "foo"
119
+ u.updatable_hash.size.should == 2
120
+ u.updatable_hash[:email].should_not be_nil
121
+ end
122
+
123
+ it "should track loaded status" do
124
+ u = EventBright::User.new("fake_key", true)
125
+ u.loaded?.should be_false
126
+ u.load
127
+ u.loaded?.should be_true
128
+ end
129
+
130
+ it "should track dirty status" do
131
+ u = EventBright::User.new("fake_key", true)
132
+ # Can't be clean until we load
133
+ u.dirty?.should be_true
134
+ u.load!
135
+ u.dirty?.should be_false
136
+ u.date_modified = "now"
137
+ u.dirty?.should be_false
138
+ u.email = "banana"
139
+ u.dirty?.should be_true
140
+ end
141
+ end