willbailey-flareshow 0.0.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.
data/Flareshow.gemspec ADDED
@@ -0,0 +1,79 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run `rake gemspec`
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{flareshow}
8
+ s.version = "0.0.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Will Bailey"]
12
+ s.date = %q{2009-09-03}
13
+ s.description = %q{TODO: a ruby gem for interacting with the shareflow collaboration service by Zenbe}
14
+ s.email = %q{will.bailey@gmail.com}
15
+ s.extra_rdoc_files = [
16
+ "LICENSE",
17
+ "README.txt"
18
+ ]
19
+ s.files = [
20
+ "Flareshow.gemspec",
21
+ "LICENSE",
22
+ "Rakefile",
23
+ "TODO",
24
+ "VERSION",
25
+ "lib/base.rb",
26
+ "lib/comment.rb",
27
+ "lib/exceptions.rb",
28
+ "lib/file_attachment.rb",
29
+ "lib/flareshow.rb",
30
+ "lib/flow.rb",
31
+ "lib/invitation.rb",
32
+ "lib/membership.rb",
33
+ "lib/post.rb",
34
+ "lib/server.rb",
35
+ "lib/user.rb",
36
+ "lib/util.rb",
37
+ "test/flareshow_test.rb",
38
+ "test/test_helper.rb"
39
+ ]
40
+ s.has_rdoc = true
41
+ s.homepage = %q{http://github.com/willbailey/flareshow}
42
+ s.rdoc_options = ["--charset=UTF-8"]
43
+ s.require_paths = ["lib"]
44
+ s.rubyforge_project = %q{flareshow}
45
+ s.rubygems_version = %q{1.3.1}
46
+ s.summary = %q{TODO: a ruby gem for interacting with the shareflow collaboration service}
47
+ s.test_files = [
48
+ "test/flareshow_test.rb",
49
+ "test/test_helper.rb"
50
+ ]
51
+
52
+ if s.respond_to? :specification_version then
53
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
54
+ s.specification_version = 2
55
+
56
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
57
+ s.add_development_dependency(%q<thoughtbot-shoulda>, [">= 0"])
58
+ s.add_development_dependency(%q<json>, [">= 0"])
59
+ s.add_development_dependency(%q<curb>, [">= 0"])
60
+ s.add_development_dependency(%q<facets>, [">= 0"])
61
+ s.add_development_dependency(%q<facets/dictionary>, [">= 0"])
62
+ s.add_development_dependency(%q<uuid>, [">= 0"])
63
+ else
64
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
65
+ s.add_dependency(%q<json>, [">= 0"])
66
+ s.add_dependency(%q<curb>, [">= 0"])
67
+ s.add_dependency(%q<facets>, [">= 0"])
68
+ s.add_dependency(%q<facets/dictionary>, [">= 0"])
69
+ s.add_dependency(%q<uuid>, [">= 0"])
70
+ end
71
+ else
72
+ s.add_dependency(%q<thoughtbot-shoulda>, [">= 0"])
73
+ s.add_dependency(%q<json>, [">= 0"])
74
+ s.add_dependency(%q<curb>, [">= 0"])
75
+ s.add_dependency(%q<facets>, [">= 0"])
76
+ s.add_dependency(%q<facets/dictionary>, [">= 0"])
77
+ s.add_dependency(%q<uuid>, [">= 0"])
78
+ end
79
+ end
data/LICENSE ADDED
@@ -0,0 +1,20 @@
1
+ Copyright (c) 2009 Will Bailey
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining
4
+ a copy of this software and associated documentation files (the
5
+ "Software"), to deal in the Software without restriction, including
6
+ without limitation the rights to use, copy, modify, merge, publish,
7
+ distribute, sublicense, and/or sell copies of the Software, and to
8
+ permit persons to whom the Software is furnished to do so, subject to
9
+ the following conditions:
10
+
11
+ The above copyright notice and this permission notice shall be
12
+ included in all copies or substantial portions of the Software.
13
+
14
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/README.txt ADDED
@@ -0,0 +1,26 @@
1
+ ___ ___ __
2
+ /'___\/\_ \ /\ \
3
+ /\ \__/\//\ \ __ _ __ __ ____\ \ \___ ___ __ __ __
4
+ \ \ ,__\ \ \ \ /'__`\ /\`'__\/'__`\ /',__\\ \ _ `\ / __`\/\ \/\ \/\ \
5
+ \ \ \_/ \_\ \_/\ \L\.\_\ \ \//\ __//\__, `\\ \ \ \ \/\ \L\ \ \ \_/ \_/ \
6
+ \ \_\ /\____\ \__/.\_\\ \_\\ \____\/\____/ \ \_\ \_\ \____/\ \___x___/'
7
+ \/_/ \/____/\/__/\/_/ \/_/ \/____/\/___/ \/_/\/_/\/___/ \/__//__/
8
+
9
+ ~ Client Library For the Zenbe Shareflow API
10
+
11
+ Description goes here.
12
+
13
+ == Note on Patches/Pull Requests
14
+
15
+ * Fork the project.
16
+ * Make your feature addition or bug fix.
17
+ * Add tests for it. This is important so I don't break it in a
18
+ future version unintentionally.
19
+ * Commit, do not mess with rakefile, version, or history.
20
+ (if you want to have your own version, that is fine but
21
+ bump version in a commit by itself I can ignore when I pull)
22
+ * Send me a pull request. Bonus points for topic branches.
23
+
24
+ == Copyright
25
+
26
+ Copyright (c) 2009 Will Bailey. See LICENSE for details.
data/Rakefile ADDED
@@ -0,0 +1,61 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ begin
5
+ require 'jeweler'
6
+ Jeweler::Tasks.new do |gem|
7
+ gem.name = "flareshow"
8
+ gem.summary = %Q{TODO: a ruby gem for interacting with the shareflow collaboration service}
9
+ gem.description = %Q{TODO: a ruby gem for interacting with the shareflow collaboration service by Zenbe}
10
+ gem.email = "will.bailey@gmail.com"
11
+ gem.homepage = "http://github.com/willbailey/flareshow"
12
+ gem.authors = ["Will Bailey"]
13
+ gem.add_development_dependency "thoughtbot-shoulda"
14
+ gem.add_development_dependency "json"
15
+ gem.add_development_dependency "curb"
16
+ gem.add_development_dependency "facets"
17
+ gem.add_development_dependency "facets/dictionary"
18
+ gem.add_development_dependency "uuid"
19
+ gem.rubyforge_project = "flareshow"
20
+ end
21
+ rescue LoadError
22
+ puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
23
+ end
24
+
25
+ require 'rake/testtask'
26
+ Rake::TestTask.new(:test) do |test|
27
+ test.libs << 'lib' << 'test'
28
+ test.pattern = 'test/**/*_test.rb'
29
+ test.verbose = true
30
+ end
31
+
32
+ begin
33
+ require 'rcov/rcovtask'
34
+ Rcov::RcovTask.new do |test|
35
+ test.libs << 'test'
36
+ test.pattern = 'test/**/*_test.rb'
37
+ test.verbose = true
38
+ end
39
+ rescue LoadError
40
+ task :rcov do
41
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
42
+ end
43
+ end
44
+
45
+ task :test => :check_dependencies
46
+
47
+ task :default => :test
48
+
49
+ require 'rake/rdoctask'
50
+ Rake::RDocTask.new do |rdoc|
51
+ if File.exist?('VERSION')
52
+ version = File.read('VERSION')
53
+ else
54
+ version = ""
55
+ end
56
+
57
+ rdoc.rdoc_dir = 'rdoc'
58
+ rdoc.title = "flareshow #{version}"
59
+ rdoc.rdoc_files.include('README*')
60
+ rdoc.rdoc_files.include('lib/**/*.rb')
61
+ end
data/TODO ADDED
@@ -0,0 +1,11 @@
1
+ TODO:
2
+ flesh out more resource methods
3
+ make post requests with embedded file attachments respond with the file attachments for now...later we need to allow the creation of files in the same way as posts as flat
4
+ namespaced objects
5
+ remove temporary auth setup logging in user automatically
6
+ handle failure states on requests
7
+
8
+ TODONE:
9
+
10
+ QUESTIONS:
11
+ should authentication responses look like query and commit responses namespacing is applied differently in authentication currently?
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/base.rb ADDED
@@ -0,0 +1,337 @@
1
+ module Flareshow
2
+
3
+ # default parameters that are included with query
4
+ # requests unless they are explicitly overridden
5
+ DEFAULT_PARAMS = {:order => "created_at desc"} unless defined? DEFAULT_PARAMS
6
+
7
+ # mappings to allow easy conversion from the
8
+ # response keys the server sends back in JSUP
9
+ # messages
10
+ ResourceToClassMap = {
11
+ "flows" => "Flow",
12
+ "posts" => "Post",
13
+ "comments" => "Comment",
14
+ "files" => "FileAttachment",
15
+ "memberships" => "Membership",
16
+ "invitations" => "Invitation",
17
+ "users" => "User"
18
+ } unless defined? ResourceToClassMap
19
+ ClassToResourceMap = ResourceToClassMap.invert unless defined? ClassToResourceMap
20
+
21
+ # the base class for Flareshow can be inherited from to create Shareflow resource
22
+ # classes or the class methods can be used to interact with the API directly
23
+ class Base
24
+ # =================
25
+ # = Class Methods =
26
+ # =================
27
+ class << self
28
+ attr_accessor :server
29
+
30
+ # return the authentication endpoint for a given host and domain
31
+ def auth_endpoint
32
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/api/v2/auth.json"
33
+ end
34
+
35
+ # return the api endpoint for a given host and domain
36
+ def api_endpoint
37
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/api/v2.json"
38
+ end
39
+
40
+ # has the server been configured?
41
+ def server_defined?
42
+ !!Flareshow::Base.server
43
+ end
44
+
45
+ # make a post request to an endpoint
46
+ # returns a hash of
47
+ # - status code
48
+ # - headers
49
+ # - body
50
+ def post(url, params)
51
+ raise ConfigurationException unless server_defined?
52
+ request = Curl::Easy.new(url) do |curl|
53
+ curl.headers = {
54
+ 'Accept' => 'application/json',
55
+ 'User-Agent' => 'flareshow 0.1'
56
+ }
57
+ curl.multipart_form_post=true
58
+ end
59
+ request.http_post(*params)
60
+ process_response(request)
61
+ end
62
+
63
+ # do a get request
64
+ def http_get(url)
65
+ request = Curl::Easy.new(url + "?key=#{User.current.get("auth_token")}") do |curl|
66
+ curl.headers = {
67
+ 'User-Agent' => 'flareshow 0.1'
68
+ }
69
+ end
70
+ request.perform()
71
+ request.body_str
72
+ end
73
+
74
+ # authenticate with the server
75
+ def authenticate(params={}, callbacks={})
76
+ params = [
77
+ Curl::PostField.content("login", params[:login]),
78
+ Curl::PostField.content("password", params[:password])
79
+ ]
80
+ response = post(auth_endpoint, params)
81
+ handle_response(response, callbacks)
82
+ end
83
+
84
+ # query the server
85
+ def query(params={}, callbacks={})
86
+ raise UserRequiredException unless User.current
87
+
88
+ # add the json request parts
89
+ params = [
90
+ Curl::PostField.content("key", User.current.get("auth_token"), 'application/json'),
91
+ Curl::PostField.content("query", params.to_json, 'application/json')
92
+ ]
93
+
94
+ response = post(api_endpoint, params)
95
+ results = assimilate_resources(response) if response[:status_code] == 200
96
+ handle_response(response,callbacks,results)
97
+ end
98
+
99
+ # commit changes to the server
100
+ def commit(params={}, callbacks={}, files=[])
101
+ curl_params = []
102
+ has_files = false
103
+ if params["posts"]
104
+ # add any file parts passed in and assign a part id to the
105
+ params["posts"] = (params["posts"]).map do |f|
106
+ if f["files"]
107
+ f["files"] = (f["files"]).each do |ff|
108
+ has_files = true
109
+ curl_params.push(Curl::PostField.file(ff["part_id"], ff["file_path"]))
110
+ end
111
+ end
112
+ f
113
+ end
114
+ end
115
+
116
+ params["files"] = []
117
+
118
+ # add the json request parts
119
+ curl_params += [
120
+ Curl::PostField.content("key", User.current.get("auth_token"), 'application/json'),
121
+ Curl::PostField.content("data", params.to_json, 'application/json')
122
+ ]
123
+
124
+ response = post(api_endpoint, curl_params)
125
+ results = assimilate_resources(response) if response[:status_code] == 200
126
+ handle_response(response,callbacks,results)
127
+ end
128
+
129
+ # return the results directly or invoke callbacks if provided
130
+ def handle_response(response, callbacks={}, results=nil)
131
+ if callbacks.empty?
132
+ results
133
+ else
134
+ dispatch(response, callbacks)
135
+ true
136
+ end
137
+ end
138
+
139
+ # get the interesting bits out of the curl response
140
+ def process_response(request)
141
+ response = {:status_code => request.response_code, :headers => request.header_str, :body => JSON.parse(request.body_str)}
142
+ Util.log_info JSON.pretty_generate(response)
143
+ response
144
+ end
145
+
146
+ # assimilate the resources provided in the response
147
+ def assimilate_resources(response)
148
+ results = {}
149
+ # process each resource key and generate a new object
150
+ # or merge the object data with an existing object
151
+ response[:body].each do |resource_pair|
152
+ resource_key, resources = resource_pair[0], resource_pair[1]
153
+ klass = Kernel.const_get(Flareshow::ResourceToClassMap[resource_key])
154
+ next unless klass
155
+ resources.each do |resource_data|
156
+ item = klass.get(resource_data["id"], :server)
157
+ item.update(resource_data, :server)
158
+ results[resource_key] ||= []
159
+ results[resource_key].push(item)
160
+ end
161
+ end
162
+ results
163
+ end
164
+
165
+ # dispatch a request to the appropriate callback
166
+ def dispatch(response, callbacks={})
167
+ case response[:status_code]
168
+ when 200...201
169
+ callbacks[:on_success].call(response[:body]) if callbacks[:on_success]
170
+ else
171
+ callbacks[:on_failure].call(response[:body]) if callbacks[:on_failure]
172
+ end
173
+ end
174
+
175
+ # find an existing instance of this object in the client or create a new one
176
+ def get(id_or_object, source = :client)
177
+ o = if id_or_object.is_a?(String) || id_or_object.is_a?(Integer)
178
+ id = id_or_object.to_s
179
+ store[id] ||= new({"id" => id}, source)
180
+ elsif
181
+ id = id_or_object["id"]
182
+ store[id] ||= new(id_or_object, source)
183
+ end
184
+ end
185
+
186
+ # list out the instances in memory
187
+ def list
188
+ store.each_value do |v|
189
+ Util.log_info(v.inspect)
190
+ end
191
+ end
192
+
193
+ # get all the resources of this type from the server
194
+ def all
195
+ key = Flareshow::ClassToResourceMap[self.name]
196
+ params = DEFAULT_PARAMS
197
+ self.query({key => params})
198
+ end
199
+
200
+ # find a resource by querying the server
201
+ def find(params)
202
+ key = Flareshow::ClassToResourceMap[self.name]
203
+ params = DEFAULT_PARAMS.merge(params)
204
+ (self.query({key => params}) || {})[key]
205
+ end
206
+
207
+ # return the first resource in the client store
208
+ # or go to the server and fetch one item
209
+ def first
210
+ return store.first if store.size > 0
211
+ find({:limit => 1})
212
+ return store.first
213
+ end
214
+
215
+
216
+ # create a resource local and sync it to the server
217
+ def create(params)
218
+ new(params).save
219
+ end
220
+
221
+ def store
222
+ @objects ||= Dictionary.new
223
+ end
224
+
225
+ end
226
+
227
+ # ====================
228
+ # = Instance Methods =
229
+ # ====================
230
+
231
+ # constructor
232
+ # build a new Flareshow::Base resource
233
+ def initialize(data={}, source = :client)
234
+ @data = {}
235
+ data["id"] = UUID.generate.upcase if source == :client
236
+ update(data, source)
237
+ end
238
+
239
+ # ==============================
240
+ # = Server Persistence Actions =
241
+ # ==============================
242
+
243
+ # reload the resource from the server
244
+ def refresh(callbacks={})
245
+ key = Flareshow::ClassToResourceMap[self.class.name]
246
+ results = self.class.query({key => {"id" => id}}, callbacks)
247
+ mark_destroyed! if results.empty?
248
+ self
249
+ end
250
+
251
+ # save a resource to the server
252
+ def save(callbacks={})
253
+ key = Flareshow::ClassToResourceMap[self.class.name]
254
+ self.class.commit({key => [(self.changes || {}).merge({"id" => id})] }, callbacks)
255
+ self
256
+ end
257
+
258
+ # destroy the resource on the server
259
+ def destroy(callbacks={})
260
+ key = Flareshow::ClassToResourceMap[self.class.name]
261
+ self.class.commit({key => [{"id" => id, "_removed" => true}]}, callbacks)
262
+ mark_destroyed!
263
+ self
264
+ end
265
+
266
+ # has this resource been destroyed
267
+ def destroyed?
268
+ self._removed || self.frozen?
269
+ end
270
+
271
+ private
272
+
273
+ def mark_destroyed!
274
+ self.freeze
275
+ self._removed=true
276
+ self.class.store.delete(id)
277
+ end
278
+
279
+ public
280
+
281
+ # ==================================
282
+ # = Attribute and State Management =
283
+ # ==================================
284
+
285
+ # return the server id of a resource
286
+ def id
287
+ @data["id"]
288
+ end
289
+
290
+ # update the instance data for this resource
291
+ # keeping track of dirty state if the update came from
292
+ # the client
293
+ def update(attributes, source = :client)
294
+ attributes.each do |p|
295
+ key, value = p[0], p[1]
296
+ self.set(key, value, source)
297
+ end
298
+ end
299
+
300
+ # keep track of dirty state on the client by maintaining a copy
301
+ # of the original state of each intstance variable when it is provided by
302
+ # the server
303
+ def set(key, value, source = :client)
304
+ # Util.log_info("setting #{key} : #{value}")
305
+ @data["original_#{key}"] = value if source == :server
306
+ @data[key.to_s]=value
307
+ end
308
+
309
+ # get a data value
310
+ def get(key)
311
+ @data[key]
312
+ end
313
+
314
+ # all the state that has been modified on the client
315
+ def changes
316
+ attributes = @data.inject({}) do |memo, pair|
317
+ key, value = *pair
318
+ if @data[key] != @data["original_#{key}"] && !key.to_s.match(/original/)
319
+ memo[key] = value
320
+ end
321
+ memo
322
+ end
323
+ end
324
+
325
+ # fallback to getter or setter
326
+ def method_missing(meth, *args)
327
+ meth = meth.to_s
328
+ meth.match(/\=/) ? set(meth.gsub(/\=/,''), *args) : get(meth)
329
+ end
330
+
331
+ # has this model been removed on the server
332
+ def method_name
333
+ !!self._removed
334
+ end
335
+
336
+ end
337
+ end
data/lib/comment.rb ADDED
@@ -0,0 +1,12 @@
1
+ class Comment < Flareshow::Base
2
+
3
+ # permalink to this comment
4
+ def permalink(mobile=false)
5
+ if mobile
6
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/mobile/post/#{reply_to}"
7
+ else
8
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/p/#{reply_to}?comment_id#{id}"
9
+ end
10
+ end
11
+
12
+ end
data/lib/exceptions.rb ADDED
@@ -0,0 +1,3 @@
1
+ class ConfigurationException < Exception; end
2
+
3
+ class UserRequiredException < Exception; end
@@ -0,0 +1,24 @@
1
+ class FileAttachment < Flareshow::Base
2
+
3
+ # =================
4
+ # = Class Methods =
5
+ # =================
6
+ class << self
7
+ # file attachments has a resource key of files
8
+ # for querying the server
9
+ def resource_key
10
+ "files"
11
+ end
12
+ end
13
+
14
+ # download the file contents
15
+ def download
16
+ url = self.url
17
+ unless url.match(/http/)
18
+ url = "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}#{url}"
19
+ end
20
+ Util.log_info("getting #{url}")
21
+ self.class.http_get(url)
22
+ end
23
+
24
+ end
data/lib/flareshow.rb ADDED
@@ -0,0 +1,21 @@
1
+ ROOT = File.dirname(__FILE__) unless defined? ROOT
2
+
3
+ # gems
4
+ require 'rubygems' #TODO fix
5
+ require 'json'
6
+ require 'curb'
7
+ require 'facets'
8
+ require 'facets/dictionary'
9
+ require 'uuid'
10
+
11
+ # std lib
12
+ require 'ostruct'
13
+ require 'logger'
14
+
15
+ # app
16
+ require 'base'
17
+
18
+ # logging
19
+ DEFAULT_LOGGER = Logger.new(STDOUT) unless defined?(DEFAULT_LOGGER)
20
+
21
+ Dir.glob(File.join(ROOT, "*.rb")).each{|lib| require lib}
data/lib/flow.rb ADDED
@@ -0,0 +1,56 @@
1
+ class Flow < Flareshow::Base
2
+
3
+ # =================
4
+ # = Class Methods =
5
+ # =================
6
+ class << self
7
+ # find a flow by name
8
+ def find_by_name(name)
9
+ self.find({:name => name})
10
+ end
11
+ end
12
+
13
+ # permalink for this flow
14
+ def permalink(mobile=false)
15
+ if mobile
16
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/mobile/flows/#{id}"
17
+ else
18
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/c/#{id}"
19
+ end
20
+ end
21
+
22
+ #invite/reinvite a user to a flow by email address
23
+ def send_invitions(email_addresses)
24
+ self.invite = [email_addresses].flatten
25
+ self.save
26
+ end
27
+
28
+ # uninvite an invited user from a flow by email address
29
+ def revoke_invitations(email_addresses)
30
+ self.uninvite = [email_addresses].flatten
31
+ self.save
32
+ end
33
+
34
+ # remove a user from a flow
35
+ # you must be the owner of the flow to perform
36
+ # this action
37
+ def remove_members(member_ids)
38
+ self.remove_members = [email_addresses].flatten
39
+ self.save
40
+ end
41
+
42
+ # build a new post but don't persist it immediatel
43
+ def build_post(attributes)
44
+ post = Post.new
45
+ post.update(attributes)
46
+ post.flow_id = id
47
+ post
48
+ end
49
+
50
+ # create a new post in this flow
51
+ def create_post(attributes)
52
+ p=build_post(attributes)
53
+ p.save
54
+ end
55
+
56
+ end
data/lib/invitation.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Invitation < Flareshow::Base
2
+
3
+ end
data/lib/membership.rb ADDED
@@ -0,0 +1,3 @@
1
+ class Membership < Flareshow::Base
2
+
3
+ end
data/lib/post.rb ADDED
@@ -0,0 +1,37 @@
1
+ class Post < Flareshow::Base
2
+
3
+ # permalink to this post
4
+ def permalink(mobile=false)
5
+ if mobile
6
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/mobile/post/#{id}"
7
+ else
8
+ "http://#{Flareshow::Base.server.host}/#{Flareshow::Base.server.domain}/shareflow/p/#{id}"
9
+ end
10
+ end
11
+
12
+ # build a new comment but don't immediately persist it
13
+ def build_comment(attributes={})
14
+ c = Comment.new(attributes)
15
+ c.post_id = self.id
16
+ c
17
+ end
18
+
19
+ # create a new comment on the post
20
+ def create_comment(attributes={})
21
+ c = build_comment(attributes)
22
+ c.save
23
+ end
24
+
25
+ def build_file(file_path)
26
+ self.files ||= []
27
+ self.files += [{"part_id" => "file_#{UUID.generate}", "file_path" => file_path}]
28
+ end
29
+
30
+ # upload a file to a post
31
+ def create_file(file_path)
32
+ self.files = []
33
+ self.build_file(file_path)
34
+ self.save
35
+ self.files = nil
36
+ end
37
+ end
data/lib/server.rb ADDED
@@ -0,0 +1,2 @@
1
+ # represents a server connection for a Flareshow resource
2
+ class Server < Struct.new(:host, :domain); end
data/lib/user.rb ADDED
@@ -0,0 +1,74 @@
1
+ class User < Flareshow::Base
2
+
3
+ # =================
4
+ # = Class Methods =
5
+ # =================
6
+ class << self
7
+
8
+ # return the current authenticated user
9
+ def current
10
+ @current
11
+ end
12
+
13
+ # authenticate user credentials
14
+ def log_in(login, password)
15
+ authenticate({:login => login, :password => password},
16
+ {
17
+ :on_success => method(:on_authentication_success),
18
+ :on_failure => method(:on_authentication_failure)
19
+ }
20
+ )
21
+ end
22
+
23
+ private
24
+
25
+ # =============
26
+ # = Callbacks =
27
+ # =============
28
+ # login success callback
29
+ def on_authentication_success(response_body)
30
+ @current = User.get(response_body["data"], :server)
31
+ end
32
+
33
+ # login failed callback
34
+ def on_authentication_failure(response_body)
35
+ Util.log_error("failed to login: #{response_body}")
36
+ end
37
+
38
+ end
39
+
40
+ # ====================
41
+ # = Instance Methods =
42
+ # ====================
43
+
44
+ # ================
45
+ # = Associations =
46
+ # ================
47
+ def flows
48
+ Flow.find({"user_id" => {"in" => id}})
49
+ end
50
+
51
+ def posts
52
+ Post.find({"user_id" => {"in" => id}})
53
+ end
54
+
55
+ def comments
56
+ Comment.find({"user_id" => {"in" => id}})
57
+ end
58
+
59
+ def files
60
+ FileAttachment.find({"user_id" => {"in" => id}})
61
+ end
62
+
63
+ # ==================
64
+ # = Authentication =
65
+ # ==================
66
+ def logout
67
+
68
+ end
69
+
70
+ def logged_in?
71
+ auth_token
72
+ end
73
+
74
+ end
data/lib/util.rb ADDED
@@ -0,0 +1,13 @@
1
+ class Util
2
+
3
+ class << self
4
+ def log_info(message)
5
+ DEFAULT_LOGGER.info(message)
6
+ end
7
+
8
+ def log_error(message)
9
+ DEFAULT_LOGGER.info(message)
10
+ end
11
+ end
12
+
13
+ end
@@ -0,0 +1,7 @@
1
+ require 'test_helper'
2
+
3
+ class FlareshowTest < Test::Unit::TestCase
4
+ should "probably rename this file and start testing for real" do
5
+ flunk "hey buddy, you should probably rename this file and start testing for real"
6
+ end
7
+ end
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'test/unit'
3
+ require 'shoulda'
4
+
5
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
6
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
7
+ require 'flareshow'
8
+
9
+ class Test::Unit::TestCase
10
+ end
metadata ADDED
@@ -0,0 +1,134 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: willbailey-flareshow
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Will Bailey
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-09-03 00:00:00 -07:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: "0"
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: json
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: "0"
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: curb
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - ">="
42
+ - !ruby/object:Gem::Version
43
+ version: "0"
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: facets
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - ">="
52
+ - !ruby/object:Gem::Version
53
+ version: "0"
54
+ version:
55
+ - !ruby/object:Gem::Dependency
56
+ name: facets/dictionary
57
+ type: :development
58
+ version_requirement:
59
+ version_requirements: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - ">="
62
+ - !ruby/object:Gem::Version
63
+ version: "0"
64
+ version:
65
+ - !ruby/object:Gem::Dependency
66
+ name: uuid
67
+ type: :development
68
+ version_requirement:
69
+ version_requirements: !ruby/object:Gem::Requirement
70
+ requirements:
71
+ - - ">="
72
+ - !ruby/object:Gem::Version
73
+ version: "0"
74
+ version:
75
+ description: "TODO: a ruby gem for interacting with the shareflow collaboration service by Zenbe"
76
+ email: will.bailey@gmail.com
77
+ executables: []
78
+
79
+ extensions: []
80
+
81
+ extra_rdoc_files:
82
+ - LICENSE
83
+ - README.txt
84
+ files:
85
+ - Flareshow.gemspec
86
+ - LICENSE
87
+ - Rakefile
88
+ - TODO
89
+ - VERSION
90
+ - lib/base.rb
91
+ - lib/comment.rb
92
+ - lib/exceptions.rb
93
+ - lib/file_attachment.rb
94
+ - lib/flareshow.rb
95
+ - lib/flow.rb
96
+ - lib/invitation.rb
97
+ - lib/membership.rb
98
+ - lib/post.rb
99
+ - lib/server.rb
100
+ - lib/user.rb
101
+ - lib/util.rb
102
+ - test/flareshow_test.rb
103
+ - test/test_helper.rb
104
+ - README.txt
105
+ has_rdoc: true
106
+ homepage: http://github.com/willbailey/flareshow
107
+ licenses:
108
+ post_install_message:
109
+ rdoc_options:
110
+ - --charset=UTF-8
111
+ require_paths:
112
+ - lib
113
+ required_ruby_version: !ruby/object:Gem::Requirement
114
+ requirements:
115
+ - - ">="
116
+ - !ruby/object:Gem::Version
117
+ version: "0"
118
+ version:
119
+ required_rubygems_version: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - ">="
122
+ - !ruby/object:Gem::Version
123
+ version: "0"
124
+ version:
125
+ requirements: []
126
+
127
+ rubyforge_project: flareshow
128
+ rubygems_version: 1.3.5
129
+ signing_key:
130
+ specification_version: 2
131
+ summary: "TODO: a ruby gem for interacting with the shareflow collaboration service"
132
+ test_files:
133
+ - test/flareshow_test.rb
134
+ - test/test_helper.rb