purzelrakete-boomloop 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
data/History.txt ADDED
@@ -0,0 +1,2 @@
1
+ 0.0.1, 06.05.2008.
2
+ * First checkin
data/README.txt ADDED
@@ -0,0 +1,36 @@
1
+ This is a Ruby API with which you can access boomloop.com.
2
+
3
+ == API Documentation
4
+
5
+ You can find documentation about the underlying boomloop REST api here: http://boomloop.com/api.
6
+
7
+ == Getting started
8
+
9
+ You have to register your api client on boomloop.com before using the api. This is
10
+ a 3 step process.
11
+
12
+ 1. Start by signing up on boomloop.com and register your application. You can do that
13
+ here: http://boomloop.com/oauth/new. When you have registered your application, you will
14
+ receive a consumer key and a consumer secret.
15
+
16
+ 2. Setup the api like this: boomloop -k <your consumer key> -s <your consumer secret>
17
+ You will be given a URL – go there and authorize your application.
18
+
19
+ 3. Go back to your terminal window and press <enter>. You're registered :).
20
+
21
+ == Example API Call
22
+
23
+ Once you have authorized your client, you can make the first API call like this:
24
+
25
+ client = Boomloop::Authentication::Client.new("api", Boomloop::Authentication::Store::YAMLStore.new)
26
+ connection = client.create_accesstoken
27
+ events = connection.get("/events").body
28
+
29
+ This returns the raw XML. We'll see how to get Event Objects next.
30
+
31
+ The Client takes two arguments - a config key, and an authentication name. When you authorize using
32
+ the boomloop script, a config key 'api' is created in the YAMLStore. This holds your the access
33
+ tokens so that you don't need to negotiate them every time you want to make a request.
34
+
35
+
36
+
data/bin/boomloop ADDED
@@ -0,0 +1,43 @@
1
+ #! /usr/bin/env ruby
2
+ %w(optparse ostruct).each &method(:require)
3
+ require File.dirname(__FILE__) + '/../lib/boomloop'
4
+
5
+ def error(text); puts text; exit; end
6
+
7
+ options = OpenStruct.new
8
+ parser = OptionParser.new
9
+ parser.banner = %Q{
10
+ == Usage
11
+
12
+ You have to register your api client on boomloop.com before using the api. This is
13
+ a 3 step process.
14
+
15
+ 1. Start by signing up on boomloop.com and register your application. You can do that
16
+ here: http://boomloop.com/oauth/new. When you have registered your application, you will
17
+ receive a consumer key and a consumer secret.
18
+
19
+ 2. Setup the api like this: boomloop -k <your consumer key> -s <your consumer secret>
20
+ You will be given a URL – go there and authorize your application.
21
+
22
+ 3. Go back to your terminal window and press <enter>. Now do something with the API :).
23
+
24
+ }
25
+
26
+ parser.on_tail("-h", "--help", "Show this message") { error(parser) }
27
+ parser.on("-k", "--key KEY", "Your consumer KEY") { |key| options.key = key }
28
+ parser.on("-s", "--secret SECRET", "Your consumer SECRET") { |secret| options.secret = secret }
29
+
30
+ # parse.
31
+ parser.parse!(ARGV) rescue error(parser)
32
+ error(parser) unless options.secret && options.key
33
+
34
+ # negotiate the tokens
35
+ client = Boomloop::Authentication::Client.new("api", Boomloop::Authentication::Store::YAMLStore.new)
36
+ request_token = client.consume(options.key, options.secret) rescue error("Invalid. Check your credentials at http://boomloop.com/oauth/applications.")
37
+ puts "\nalmost ready! go to #{ request_token.authorize_url }\n\n press enter when you're done... <waiting>\n"
38
+
39
+ while !@access_token && gets
40
+ @access_token = client.activate rescue nil
41
+ end
42
+
43
+ puts "your keys have been activated. you're ready to use the api. \n\n"
File without changes
@@ -0,0 +1,37 @@
1
+ module Boomloop
2
+ module Authentication
3
+ class Client
4
+ attr_accessor :store, :user
5
+ attr_accessor :consumer, :request_token, :access_token
6
+
7
+ def initialize(user, store)
8
+ self.user = user
9
+ self.store = store
10
+ end
11
+
12
+ def consume(key, secret)
13
+ self.create_consumer(key, secret)
14
+ self.request_token = self.consumer.get_request_token
15
+ self.store.find(user).update(:consumer_key => key, :consumer_secret => secret)
16
+ self.request_token
17
+ end
18
+
19
+ def activate
20
+ if self.request_token
21
+ self.access_token = self.request_token.get_access_token
22
+ self.store.find(user).update(:access_key => self.access_token.token, :access_secret => self.access_token.secret)
23
+ end
24
+ end
25
+
26
+ def create_consumer(key, secret)
27
+ self.consumer = OAuth::Consumer.new(key, secret, { :site => "http://boomloop.com" })
28
+ end
29
+
30
+ def create_accesstoken
31
+ credentials = self.store.find(self.user)
32
+ self.consumer ||= create_consumer(credentials['consumer_key'], credentials['consumer_secret'])
33
+ self.access_token ||= OAuth::AccessToken.new(self.consumer, credentials['access_key'], credentials['access_secret'])
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,29 @@
1
+ module Boomloop
2
+ module Authentication
3
+ class Credentials
4
+ attr_accessor :username, :store, :options
5
+
6
+ def initialize(username, store, options)
7
+ self.username = username
8
+ self.store = store
9
+ self.options = options || {}
10
+ end
11
+
12
+ def update(tosave)
13
+ tosave.each do |key, value|
14
+ self.options[key] = value
15
+ end
16
+
17
+ save
18
+ end
19
+
20
+ def save
21
+ self.store.update(self)
22
+ end
23
+
24
+ def [](key)
25
+ self.options[key]
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,11 @@
1
+ module Boomloop
2
+ module Authentication
3
+ module Store
4
+ class Base
5
+ def update(credentials)
6
+ raise NotImplementedError.new("where's me store!")
7
+ end
8
+ end
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,40 @@
1
+ module Boomloop
2
+ module Authentication
3
+ module Store
4
+ class YAMLStore < Base
5
+ @@ymlfile = File.dirname(__FILE__) + '/../../../config/credentials.yml'
6
+
7
+ class << self
8
+ attr_accessor :config
9
+ end
10
+
11
+ def initialize
12
+ self.class.load_config
13
+ end
14
+
15
+ def self.load_config
16
+ File.open(@@ymlfile) do |file|
17
+ self.config = YAML.load(file) || {}
18
+ end
19
+ end
20
+
21
+ def self.save_config
22
+ if self.config
23
+ File.open(@@ymlfile, "w") do |f|
24
+ f.write self.config.to_yaml
25
+ end
26
+ end
27
+ end
28
+
29
+ def update(credentials)
30
+ self.class.config[credentials.username] = credentials.options
31
+ self.class.save_config
32
+ end
33
+
34
+ def find(user)
35
+ ::Boomloop::Authentication::Credentials.new(user, self, self.class.config[user])
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
data/lib/boomloop.rb ADDED
@@ -0,0 +1,14 @@
1
+ require 'rubygems'
2
+ require 'yaml'
3
+ gem 'oauth'
4
+ require 'oauth/consumer'
5
+ require 'ostruct'
6
+ require 'activesupport'
7
+
8
+ module Boomloop
9
+ class ApiError < ::StandardError; end
10
+ end
11
+
12
+ Dir.glob(File.dirname(__FILE__) + "/**/*.rb").each do |file|
13
+ require file
14
+ end
@@ -0,0 +1,84 @@
1
+ module Boomloop
2
+ module Resources
3
+ class Base < ::OpenStruct
4
+ API_BASE = 'http://api.boomloop.com/'
5
+
6
+ class << self
7
+ attr_accessor :connection
8
+ end
9
+
10
+ def self.connection
11
+ @@connection ||= init
12
+ end
13
+
14
+ # get oauth token
15
+ def self.init
16
+ client = Boomloop::Authentication::Client.new("api", Boomloop::Authentication::Store::YAMLStore.new)
17
+ self.connection = client.create_accesstoken
18
+ end
19
+
20
+ def save
21
+ returned = self.class.create(self)
22
+ self.instance_variable_set("@table", returned.to_hash)
23
+ returned
24
+ end
25
+
26
+ def child_resources
27
+ links = to_hash.keys.select { |key| key =~ /resource-url$/ }
28
+ end
29
+
30
+ def to_hash
31
+ instance_variable_get("@table")
32
+ end
33
+
34
+ def to_xml
35
+ self.to_hash.to_xml
36
+ end
37
+
38
+ def self.singular
39
+ self.to_s.demodulize.tableize.singularize
40
+ end
41
+
42
+ def self.plural
43
+ self.to_s.demodulize.pluralize.tableize
44
+ end
45
+
46
+ # REST methods
47
+ def self.index(params = {})
48
+ url = API_BASE + self.plural
49
+ url += "?#{ params.to_query }" unless params.empty?
50
+ xml = connection.get(url)
51
+ attrs = Hash.from_xml(xml)
52
+ construct_resource_collection(attrs)
53
+ end
54
+
55
+ def self.show(url)
56
+ xml = connection.get(url)
57
+ attrs = Hash.from_xml(xml)
58
+ self.new(attrs[self.singular])
59
+ end
60
+
61
+ def self.create(resource)
62
+ url = API_BASE + self.plural
63
+ xml = connection.post(url, resource.to_hash.to_query)
64
+ self.new(Hash.from_xml(xml)[self.singular])
65
+ end
66
+
67
+ def self.construct_resource_collection(attrs)
68
+ collection = attrs[self.plural][self.singular]
69
+ case collection
70
+ when Array : collection.map { |hash| self.new(hash) }
71
+ when Hash : self.new(collection)
72
+ end
73
+ end
74
+
75
+ def self.transitive_create(resource)
76
+ if resource.child_resources
77
+ child_resources.each { |child| transitive_create(child) }
78
+ else
79
+ create(resource)
80
+ end
81
+ end
82
+ end
83
+ end
84
+ end
@@ -0,0 +1,6 @@
1
+ module Boomloop
2
+ module Resources
3
+ class Event < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Boomloop
2
+ module Resources
3
+ class EventSeries < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Boomloop
2
+ module Resources
3
+ class Place < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Boomloop
2
+ module Resources
3
+ class TicketCategory < Base
4
+ end
5
+ end
6
+ end
data/lib/version.rb ADDED
@@ -0,0 +1,9 @@
1
+ module Boomloop #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 0
4
+ MINOR = 0
5
+ TINY = 1
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,105 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ context "a boomloop resource" do
4
+ setup do
5
+ @connection = Boomloop::Resources::Base.connection
6
+ end
7
+
8
+ specify "should be creatable by passing in a hash of values" do
9
+ monster = Boomloop::Resources::Monster.new(:size => :huge, :affect => :sanguine, :name => "fred")
10
+ monster.affect.should.be :sanguine
11
+ end
12
+
13
+ specify "should be able to return a hash representation of itself" do
14
+ qualities = { :size => :huge, :affect => :sanguine, :name => "fred" }
15
+ monster = Boomloop::Resources::Monster.new(qualities)
16
+ monster.to_hash.should.equal qualities
17
+ end
18
+
19
+ specify "should be showable when calling Boomloop::Resources::Monster.show('http://api.boomloop.com/monsters/fred')" do
20
+ @connection.expects(:get).with("http://api.boomloop.com/monsters/fred").at_least_once.returns(%Q[
21
+ <monster>
22
+ <resource_url>http://api.boomloop.com/monsters/fred</resource_url>
23
+ <size>huge</size>
24
+ <affect>sanguine</affect>
25
+ <name>fred</name>
26
+ </monster>
27
+ ])
28
+
29
+ monster = Boomloop::Resources::Monster.show('http://api.boomloop.com/monsters/fred')
30
+ monster.name.should.equal "fred"
31
+ end
32
+
33
+ specify "should be listable when calling Boomloop::Resources::Monster.index" do
34
+ @connection.expects(:get).with("http://api.boomloop.com/monsters").at_least_once.returns(%Q[
35
+ <monsters>
36
+ <monster>
37
+ <resource_url>http://api.boomloop.com/monsters/fred</resource_url>
38
+ <size>huge</size>
39
+ <affect>sanguine</affect>
40
+ <name>fred</name>
41
+ </monster>
42
+
43
+ <monster>
44
+ <resource_url>http://api.boomloop.com/monsters/simon</resource_url>
45
+ <size>middling</size>
46
+ <affect>indifferent</affect>
47
+ <name>simon</name>
48
+ </monster>
49
+ </monsters>
50
+ ])
51
+
52
+ monsters = Boomloop::Resources::Monster.index
53
+ monsters.map { |monster| monster.name }.should.include "fred"
54
+ end
55
+
56
+ specify "should be listable when calling Boomloop::Resources::Monster.index and there is only one result" do
57
+ @connection.expects(:get).with("http://api.boomloop.com/monsters").at_least_once.returns(%Q[
58
+ <monsters>
59
+ <monster>
60
+ <resource_url>http://api.boomloop.com/monsters/fred</resource_url>
61
+ <size>huge</size>
62
+ <affect>sanguine</affect>
63
+ <name>fred</name>
64
+ </monster>
65
+ </monsters>
66
+ ])
67
+
68
+ monsters = Boomloop::Resources::Monster.index
69
+ monsters.name.should.equal "fred"
70
+ end
71
+
72
+ specify "should be listable with attributes when calling Boomloop::Resources::Monster.index(:affect => :sanguine)" do
73
+ @connection.expects(:get).with("http://api.boomloop.com/monsters?affect=sanguine").at_least_once.returns(%Q[
74
+ <monsters>
75
+ <monster>
76
+ <resource_url>http://api.boomloop.com/monsters/fred</resource_url>
77
+ <size>huge</size>
78
+ <affect>sanguine</affect>
79
+ <name>fred</name>
80
+ </monster>
81
+ </monsters>
82
+ ])
83
+
84
+ monsters = Boomloop::Resources::Monster.index(:affect => :sanguine)
85
+ monsters.name.should.equal "fred"
86
+ end
87
+
88
+ specify "should be savable when calling .save on a Monster instance" do
89
+ intended_resource_url = 'http://api.boomloop.com/monsters/samuel'
90
+ intended_attributes = { :size => :laughable, :affect => :mordant, :name => "samuel" }
91
+
92
+ @connection.expects(:post).with("http://api.boomloop.com/monsters", intended_attributes.to_query).at_least_once.returns(%Q[
93
+ <monster>
94
+ <resource_url>#{ intended_resource_url }</resource_url>
95
+ <size>laughable</size>
96
+ <affect>mordant</affect>
97
+ <name>samuel</name>
98
+ </monster>
99
+ ])
100
+
101
+ monster = Boomloop::Resources::Monster.new(intended_attributes)
102
+ monster.save
103
+ monster.resource_url.should.equal intended_resource_url
104
+ end
105
+ end
@@ -0,0 +1,6 @@
1
+ module Boomloop
2
+ module Resources
3
+ class Monster < Base
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,8 @@
1
+ require 'rubygems'
2
+ require 'test/spec'
3
+ require 'mocha'
4
+
5
+ current_dir = File.dirname(__FILE__)
6
+
7
+ require current_dir + '/../lib/boomloop'
8
+ require current_dir + '/mocks/monster'
metadata ADDED
@@ -0,0 +1,81 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: purzelrakete-boomloop
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ platform: ruby
6
+ authors:
7
+ - Rany Keddo
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2008-05-21 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: oauth
17
+ version_requirement:
18
+ version_requirements: !ruby/object:Gem::Requirement
19
+ requirements:
20
+ - - ">"
21
+ - !ruby/object:Gem::Version
22
+ version: 0.0.0
23
+ version:
24
+ description: boomloop is a kick-ass event platform.
25
+ email: rany@playtype.net
26
+ executables:
27
+ - boomloop
28
+ extensions: []
29
+
30
+ extra_rdoc_files:
31
+ - History.txt
32
+ - README.txt
33
+ files:
34
+ - lib/authentication/client.rb
35
+ - lib/authentication/credentials.rb
36
+ - lib/authentication/store/base.rb
37
+ - lib/authentication/store/yaml_store.rb
38
+ - lib/boomloop.rb
39
+ - lib/resources/base.rb
40
+ - lib/resources/event.rb
41
+ - lib/resources/event_series.rb
42
+ - lib/resources/place.rb
43
+ - lib/resources/ticket_category.rb
44
+ - lib/version.rb
45
+ - bin/boomloop
46
+ - History.txt
47
+ - README.txt
48
+ - test/boomloop_resource_test.rb
49
+ - test/mocks
50
+ - test/mocks/monster.rb
51
+ - test/test_helper.rb
52
+ - config/credentials.yml
53
+ has_rdoc: true
54
+ homepage: http://github.com/purzelrakete/boomloop
55
+ post_install_message:
56
+ rdoc_options:
57
+ - --main
58
+ - README.txt
59
+ require_paths:
60
+ - lib
61
+ required_ruby_version: !ruby/object:Gem::Requirement
62
+ requirements:
63
+ - - ">="
64
+ - !ruby/object:Gem::Version
65
+ version: "0"
66
+ version:
67
+ required_rubygems_version: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: "0"
72
+ version:
73
+ requirements: []
74
+
75
+ rubyforge_project:
76
+ rubygems_version: 1.0.1
77
+ signing_key:
78
+ specification_version: 2
79
+ summary: Ruby API for boomloop.com
80
+ test_files: []
81
+