glue 0.41.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/History.txt +6 -0
  2. data/Manifest.txt +6 -0
  3. data/README.txt +130 -0
  4. data/Rakefile +16 -0
  5. data/lib/glue.rb +49 -72
  6. data/test/test_glue.rb +218 -0
  7. metadata +84 -100
  8. data/doc/AUTHORS +0 -13
  9. data/doc/CHANGELOG.1 +0 -354
  10. data/doc/LICENSE +0 -32
  11. data/doc/RELEASES +0 -207
  12. data/lib/glue/attribute.rb +0 -113
  13. data/lib/glue/attributeutils.rb +0 -117
  14. data/lib/glue/autoreload.rb +0 -60
  15. data/lib/glue/builder.rb +0 -57
  16. data/lib/glue/builder/xml.rb +0 -103
  17. data/lib/glue/cache.rb +0 -22
  18. data/lib/glue/cache/drb.rb +0 -51
  19. data/lib/glue/cache/file.rb +0 -78
  20. data/lib/glue/cache/memcached.rb +0 -68
  21. data/lib/glue/cache/memory.rb +0 -79
  22. data/lib/glue/cache/og.rb +0 -61
  23. data/lib/glue/configuration.rb +0 -305
  24. data/lib/glue/fixture.rb +0 -154
  25. data/lib/glue/html.rb +0 -12
  26. data/lib/glue/localization.rb +0 -129
  27. data/lib/glue/logger.rb +0 -208
  28. data/lib/glue/mail.rb +0 -160
  29. data/lib/glue/mailer.rb +0 -55
  30. data/lib/glue/mailer/incoming.rb +0 -41
  31. data/lib/glue/mailer/outgoing.rb +0 -119
  32. data/lib/glue/settings.rb +0 -3
  33. data/lib/glue/uri.rb +0 -190
  34. data/lib/glue/validation.rb +0 -447
  35. data/lib/html/document.rb +0 -63
  36. data/lib/html/node.rb +0 -480
  37. data/lib/html/tokenizer.rb +0 -103
  38. data/lib/html/version.rb +0 -11
  39. data/test/fixture/article.csv +0 -3
  40. data/test/fixture/article.yml +0 -13
  41. data/test/fixture/user.yml +0 -12
  42. data/test/glue/builder/tc_xml.rb +0 -57
  43. data/test/glue/tc_aspects.rb +0 -99
  44. data/test/glue/tc_attribute.rb +0 -112
  45. data/test/glue/tc_attribute_mixins.rb +0 -86
  46. data/test/glue/tc_builder.rb +0 -30
  47. data/test/glue/tc_configuration.rb +0 -135
  48. data/test/glue/tc_fixture.rb +0 -98
  49. data/test/glue/tc_localization.rb +0 -49
  50. data/test/glue/tc_logger.rb +0 -43
  51. data/test/glue/tc_mail.rb +0 -99
  52. data/test/glue/tc_stores.rb +0 -16
  53. data/test/glue/tc_uri.rb +0 -97
  54. data/test/glue/tc_validation.rb +0 -217
  55. data/test/public/dummy_mailer/registration.xhtml +0 -5
data/History.txt ADDED
@@ -0,0 +1,6 @@
1
+ === 1.0.0 / 2009-08-25
2
+
3
+ * 1 major enhancement
4
+
5
+ * Birthday!
6
+
data/Manifest.txt ADDED
@@ -0,0 +1,6 @@
1
+ History.txt
2
+ Manifest.txt
3
+ README.txt
4
+ Rakefile
5
+ lib/glue.rb
6
+ test/test_glue.rb
data/README.txt ADDED
@@ -0,0 +1,130 @@
1
+ = glue
2
+
3
+ http://Glue.RubyForge.org
4
+
5
+ http://GlueNow.com
6
+
7
+ == DESCRIPTION:
8
+
9
+ The Glue gem enables posting to GlueNow.com API service using an account subdomain, username, password. In this version you can add a post by providing a title, body, optional author name and optional private settings. You can also access some basic info about a users account and check if their account info is valid.
10
+
11
+ You can also request public posts from an account using the same RSS that powers the many Glue feeds.
12
+
13
+ == FEATURES/PROBLEMS:
14
+
15
+ * To Add a new post Title & Body text must be included
16
+ * Access info about an account with successful login:
17
+ * Email Address
18
+ * If they are an admin
19
+ * Thier Author Name
20
+ * Can check if a subdomain is valid and belongs to an account
21
+ * Read all public posts
22
+ * This Gem is throughly tested
23
+ * Adding & Reading posts Only at this time
24
+ * You can't editor delete a posts yet
25
+ * No way to verify if a post has accepted the author name yet
26
+
27
+
28
+ == SYNOPSIS:
29
+
30
+ ---- Adding Posts ----
31
+
32
+ 1. Instantiate your account
33
+
34
+ * Provide the subdomain, username and password for http://Your-Account.GlueNow.com
35
+
36
+ account = Glue::API.new( "your-account", "j-username", "j-password" )
37
+
38
+ 2. Check if the account subdomain is valid
39
+
40
+ account.valid_site?
41
+
42
+ 3. Get more info about the user's account
43
+
44
+ response = account.user_info
45
+
46
+ response #=> {"rsp"=>{"user"=>{"author"=>"Jordan Dobson","admin"=>"true","email"=>"jordandobson@gmail.com"},"stat"=>"ok"}}
47
+
48
+ 4. Post your Content
49
+
50
+ * Both Title and Body are required - Set to a variable to check the response
51
+
52
+ response = account.post("My Title", "My Body")
53
+
54
+ * You can also choose to set the post as private and/or use the optional Author Name
55
+ * In this example we set false for not private and true to use the author name
56
+
57
+ response = account.post("My Title", "My Body", false, true)
58
+
59
+
60
+ 5. Get a success or error hash back
61
+
62
+ * A Successful response would look like this
63
+
64
+ response #=> {"rsp"=>{"post"=>{"title"=>"My Title","url"=>"http://bit.ly/sakIM","id"=>"14415","longurl"=>"http://jordandobson.com"},"stat"=>"ok"}}
65
+
66
+ * A Error response would be empty like this
67
+
68
+ response #=> {}
69
+
70
+ ---- Reading Posts ----
71
+
72
+ 1. Instantiate your Reader with your account info
73
+
74
+ * Provide the subdomain for http://Your-Account.GlueNow.com
75
+
76
+ account = Glue::RSS.new( "your-account" )
77
+
78
+ 2. Request posts from the RSS feed
79
+
80
+ * If you want all of them don't include any limiting or range. Defaults to up to 999 posts on one page
81
+
82
+ response = account.feed
83
+
84
+ * If you want to limit the results include a limit (1-999) and which page (used for paging)
85
+
86
+ response = account.feed(10, 3)
87
+
88
+ 3. Get an RSS feed back or HTML page - These Examples are simplified to include most important nodes
89
+
90
+ * A successful RSS response would look like
91
+
92
+ response #=> {"rss"=>{"channel"=>{"item"=>{"pubDate"=>"Fri, 12 Sep 2008 00:00:00 +0000","title"=>"My Title","guid"=>"http://jordandobson.com#14415","dc:creator"=>"Jordan","description"=>"<p>My Body</p>","link"=>"http://jordandobson.com","source"=>"Glue"}}}}
93
+
94
+ * A failed HTML responsed would look like
95
+
96
+ response #=> {"html"=>{"head"=>{"title"=>"GLUE | Web + Mobile Content Publishing"},"body"=>"<p>Webpage Body</p>"}}
97
+
98
+ == REQUIREMENTS:
99
+
100
+ * Mechanize & HTTParty
101
+ * Mocha (for tests)
102
+
103
+ == INSTALL:
104
+
105
+ * sudo gem install jordandobson-glue -include-dependencies
106
+
107
+ == LICENSE:
108
+
109
+ (The MIT License)
110
+
111
+ Copyright (c) 2009 Squad, Inc.
112
+
113
+ Permission is hereby granted, free of charge, to any person obtaining
114
+ a copy of this software and associated documentation files (the
115
+ 'Software'), to deal in the Software without restriction, including
116
+ without limitation the rights to use, copy, modify, merge, publish,
117
+ distribute, sublicense, and/or sell copies of the Software, and to
118
+ permit persons to whom the Software is furnished to do so, subject to
119
+ the following conditions:
120
+
121
+ The above copyright notice and this permission notice shall be
122
+ included in all copies or substantial portions of the Software.
123
+
124
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
125
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
126
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
127
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
128
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
129
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
130
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
data/Rakefile ADDED
@@ -0,0 +1,16 @@
1
+ # -*- ruby -*-
2
+
3
+ require 'rubygems'
4
+ require 'hoe'
5
+ require './lib/glue.rb'
6
+
7
+ Hoe.new('glue', Glue::VERSION) do |p|
8
+ # p.rubyforge_name = 'gluex' # if different than lowercase project name
9
+ p.developer('Jordan Dobson', 'jordan.dobson@madebysquad.com')
10
+ p.extra_deps = ['mechanize']
11
+ p.extra_deps = ['httparty']
12
+ p.extra_dev_deps = ['mocha']
13
+ p.remote_rdoc_dir = '' # Release to root
14
+ end
15
+
16
+ # vim: syntax=Ruby
data/lib/glue.rb CHANGED
@@ -1,87 +1,64 @@
1
- # = Glue
2
- #
3
- # Copyright (c) 2004-2006, George Moschovitis (http://www.gmosx.com)
4
- #
5
- # Glue (http://www.nitroproject.org) is copyrighted free software
6
- # created and maintained by George Moschovitis (mailto:george.moschovitis@gmail.com)
7
- # and released under the standard BSD Licence. For details
8
- # consult the file doc/LICENCE.
1
+ require 'rubygems'
2
+ require 'httparty'
3
+ require 'nokogiri'
4
+ require 'open-uri'
9
5
 
10
- require 'English'
11
- require 'pp'
12
-
13
- require 'facet/nullclass'
14
- require 'facets/more/paramix' # keep this before module/is
15
- require 'facets/core/module/is'
16
- require 'facets/core/class/cattr'
6
+ module Glue
17
7
 
18
- require 'glue/attribute'
19
- require 'glue/attributeutils'
8
+ VERSION = '1.0.0'
9
+ DOMAIN = 'gluenow.com'
20
10
 
21
- # Glue is a collection of reusable utilities and methods to
22
- # especially suited to Nitro and Og coding. We try to extract
23
- # more generally useful parts of Glue into the Facets project.
24
- # For more information about Facets have a look at:
25
- #
26
- # http://rubyforge.org/projects/facets/
27
- #
28
- # The Glue module is included by default in the TopLevel
29
- # for easy access to the utilities. Just use:
30
- #
31
- # $GLUE_DONT_INCLUDE = true
32
- #
33
- # before including Glue to dissable this behaviour.
11
+ class AuthError < StandardError; end
12
+ class FormatHelper; include HTTParty; format :xml; end
34
13
 
35
- module Glue
14
+ class API < Glue::FormatHelper
15
+
16
+ POST = '/api/post'
17
+ USER = '/api/user'
36
18
 
37
- # The version.
19
+ def initialize subdomain, user, pass
20
+ raise AuthError, 'Username, Password or Account subdomain is blank.' \
21
+ if subdomain.empty? || user.empty? || pass.empty?
22
+ @auth = { :username => user, :password => pass }
23
+ @site = "#{subdomain}.#{DOMAIN}"
24
+ self.class.base_uri @site
25
+ end
38
26
 
39
- Version = '0.31.0'
40
-
41
- # Library path.
27
+ def valid_site?
28
+ Nokogiri::HTML(open("http://#{@site}")).at('body#login') ? true : false
29
+ end
42
30
 
43
- LibPath = File.dirname(__FILE__)
31
+ def user_info
32
+ self.class.post(USER, :query => {}, :basic_auth => @auth)
33
+ end
44
34
 
45
- end
35
+ def post title, body, *opts
36
+ self.class.post(
37
+ POST,
38
+ :query => {
39
+ :title => title,
40
+ :body => body,
41
+ :draft => opts.include?( :draft ) ,
42
+ :author => opts.include?( :author ) },
43
+ :basic_auth => @auth
44
+ )
45
+ end
46
46
 
47
- class NilClass
48
- # quite usefull for error tolerant apps.
49
- # a bit dangerous? Will have to rethink this.
50
-
51
- def empty?
52
- true
53
47
  end
54
48
 
55
- def blank?
56
- true
57
- end
58
- end
49
+ class RSS < Glue::FormatHelper
59
50
 
60
- class Class
61
- #--
62
- # gmosx: is this really needed?
63
- #++
51
+ NEWS = '/news/rss'
52
+
53
+ def initialize subdomain
54
+ raise AuthError, 'Account Subdomain is missing or blank' if subdomain.empty?
55
+ self.class.base_uri "#{subdomain}.#{DOMAIN}"
56
+ end
57
+
58
+ def feed limit=999, page=1
59
+ self.class.get("#{NEWS}?limit=#{limit}&page=#{page}")
60
+ end
64
61
 
65
- def to_i
66
- return self.hash
67
62
  end
68
- end
69
-
70
- module Kernel
71
- # Pretty prints an exception/error object
72
- # usefull for helpfull debug messages
73
- #
74
- # Input:
75
- # The Exception/StandardError object
76
- #
77
- # Output:
78
- # the pretty printed string
79
-
80
- def pp_exception(ex)
81
- return %{#{ex.message}\n #{ex.backtrace.join("\n ")}\n LOGGED FROM: #{caller[0]}}
82
- end
83
- end
84
-
85
- # Include in the top level binding for easy access.
86
63
 
87
- include Glue unless $GLUE_DONT_INCLUDE
64
+ end
data/test/test_glue.rb ADDED
@@ -0,0 +1,218 @@
1
+ require "test/unit"
2
+ require "#{File.dirname(__FILE__)}/../lib/glue.rb"
3
+ require "mocha"
4
+
5
+ class TestGlue < Test::Unit::TestCase
6
+
7
+ def setup
8
+ @subdomain = 'AccountSubDomain'
9
+ @username = 'Username'
10
+ @password = 'Password'
11
+ @client = Glue::API.new( @subdomain, @username, @password )
12
+ @title = "My Title"
13
+ @title2 = "Your Title"
14
+ @body = "Body Text"
15
+ @body2 = "Hello World"
16
+ @url = "http://bit.ly/sakIM"
17
+ @id = "14415"
18
+ @id2 = "14416"
19
+ @lurl = "http://jordandobson.com"
20
+ @guid = "#{@lurl}##{@id}"
21
+ @guid2 = "#{@lurl}##{@id2}"
22
+ @author = "Jordan"
23
+
24
+ @resp_fail = {}
25
+
26
+ @resp_ok = { "rsp" => {
27
+ "user" => {
28
+ "author" => @author,
29
+ "admin" => "true" ,
30
+ "email" => nil },
31
+ "stat" => "ok" }}
32
+
33
+ @post_ok = { "rsp" => {
34
+ "post" => {
35
+ "title" => @title ,
36
+ "url" => @url ,
37
+ "id" => @id ,
38
+ "longurl" => @lurl },
39
+ "stat" => "ok" }}
40
+
41
+ @rss = { "rss" => {
42
+ "channel" => {
43
+ "item" => {
44
+ "pubDate" => "Fri, 12 Sep 2008 00:00:00 +0000",
45
+ "title" => @title ,
46
+ "guid" => @guid ,
47
+ "dc:creator" => @author ,
48
+ "description" => "<p>#{@body}</p>" ,
49
+ "link" => @lurl ,
50
+ "source" => "Glue" }}}}
51
+
52
+ @rss_many = { "rss" => {
53
+ "channel" => {
54
+ "item" => [{
55
+ "pubDate" => "Fri, 12 Sep 2008 00:00:00 +0000",
56
+ "title" => @title ,
57
+ "guid" => @guid ,
58
+ "dc:creator" => @author ,
59
+ "description" => "<p>#{@body}</p>" ,
60
+ "link" => @lurl ,
61
+ "source" => "Glue" },{
62
+ "pubDate" => "Fri, 12 Sep 2009 00:00:00 +0000",
63
+ "title" => @title2 ,
64
+ "guid" => @guid2 ,
65
+ "dc:creator" => nil ,
66
+ "description" => "<p>#{@body2}</p>" ,
67
+ "link" => @lurl ,
68
+ "source" => "Glue" }]}}}
69
+
70
+ @rss_empty = { "rss" => {
71
+ "channel" => {
72
+ "pubDate" => "Tue, 18 Aug 2009 10:48:28 +0000" ,
73
+ "webMaster" => "glue@jordan.gluenow.com (Glue)" ,
74
+ "link" => "http://jordandobson.com" }}}
75
+
76
+ @html_page = { "html" => {
77
+ "head" => {
78
+ "title" => "GLUE | Web + Mobile Content Publishing" },
79
+ "body" => "<p>Webpage Body</p>" }}
80
+ end
81
+
82
+ def test_raises_without_account_url
83
+ assert_raise Glue::AuthError do
84
+ Glue::API.new( '' , @username, @password )
85
+ end
86
+ end
87
+
88
+ def test_raises_without_user
89
+ assert_raise Glue::AuthError do
90
+ Glue::API.new( @subdomain, '', @password )
91
+ end
92
+ end
93
+
94
+ def test_raises_without_password
95
+ assert_raise Glue::AuthError do
96
+ Glue::API.new( @subdomain, @username, '' )
97
+ end
98
+ end
99
+
100
+ def test_raises_with_number_account_url
101
+ assert_raise NoMethodError do
102
+ Glue::API.new( 00 , @username, @password )
103
+ end
104
+ end
105
+
106
+ def test_raises_with_number_user
107
+ assert_raise NoMethodError do
108
+ Glue::API.new( @subdomain, 00, @password )
109
+ end
110
+ end
111
+
112
+ def test_raises_with_number_password
113
+ assert_raise NoMethodError do
114
+ Glue::API.new( @subdomain, @username, 00 )
115
+ end
116
+ end
117
+
118
+ def test_site_is_valid
119
+ OpenURI.stubs(:open_uri).returns('<body id="login"></body>')
120
+ assert @client.valid_site?
121
+ end
122
+
123
+ def test_site_is_invalid
124
+ OpenURI.stubs(:open_uri).returns('<body></body>')
125
+ assert !@client.valid_site?
126
+ end
127
+
128
+ def test_user_info_valid
129
+ Glue::API.stubs(:post).returns(@resp_ok)
130
+ actual = @client.user_info
131
+ assert_equal "ok", actual["rsp"]["stat"]
132
+ assert actual["rsp"]["user"]
133
+ assert_equal "Jordan", actual["rsp"]["user"]["author"]
134
+ assert_equal "true", actual["rsp"]["user"]["admin"]
135
+ assert_equal nil, actual["rsp"]["user"]["email"]
136
+ end
137
+
138
+ def test_user_info_invalid
139
+ Glue::API.stubs(:post).returns(@resp_fail)
140
+ actual = @client.user_info
141
+ assert_equal @resp_fail, actual
142
+ end
143
+
144
+ def test_bad_post_response
145
+ Glue::API.stubs(:post).returns(@resp_fail)
146
+ actual = @client.post(@title, @body)
147
+ assert_equal @resp_fail, actual
148
+ end
149
+
150
+ def test_good_post_response
151
+ Glue::API.stubs(:post).returns(@post_ok)
152
+ actual = @client.post(@title, @body)
153
+ assert_equal "ok", actual["rsp"]["stat"]
154
+ assert actual["rsp"]["post"]
155
+ assert_equal @title, actual["rsp"]["post"]["title"]
156
+ assert_equal @url, actual["rsp"]["post"]["url"]
157
+ assert_equal @id, actual["rsp"]["post"]["id"]
158
+ assert_equal @lurl, actual["rsp"]["post"]["longurl"]
159
+ end
160
+
161
+ # Need to test posting with the options
162
+
163
+ def test_reading_single_post
164
+ Glue::RSS.stubs(:get).returns(@rss)
165
+ actual = Glue::RSS.new('jordan').feed(1,1)['rss']['channel']["item"]
166
+ assert_equal @title, actual["title"]
167
+ assert_match @body, actual["description"]
168
+ assert_equal @lurl, actual["link"]
169
+ assert_equal @guid, actual["guid"]
170
+ assert_equal @author, actual["dc:creator"]
171
+ end
172
+
173
+ def test_reading_multiple_posts
174
+ Glue::RSS.stubs(:get).returns(@rss_many)
175
+ actual = Glue::RSS.new('jordan').feed['rss']['channel']["item"]
176
+ assert_equal 2, actual.length
177
+
178
+ # First Article
179
+ assert_equal @title, actual.first["title"]
180
+ assert_match @body, actual.first["description"]
181
+ assert_equal @lurl, actual.first["link"]
182
+ assert_equal @guid, actual.first["guid"]
183
+ assert_equal @author, actual.first["dc:creator"]
184
+
185
+ # Last Article
186
+ assert_equal @title2, actual.last["title"]
187
+ assert_match @body2, actual.last["description"]
188
+ assert_equal nil, actual.last["dc:creator"]
189
+ assert_equal @lurl, actual.last["link"]
190
+ assert_equal @guid2, actual.last["guid"]
191
+
192
+ assert_not_equal actual.first["title"], actual.last["title"]
193
+ assert_not_equal actual.first["description"], actual.last["description"]
194
+ assert_not_equal actual.first["dc:creator"], actual.last["dc:creator"]
195
+ assert_not_equal actual.first["guid"], actual.last["guid"]
196
+ assert_equal actual.first["link"], actual.last["link"]
197
+ end
198
+
199
+ def test_no_public_posts_available
200
+ Glue::RSS.stubs(:get).returns(@rss_empty)
201
+ subdomain = 'jordan'
202
+ actual = Glue::RSS.new(subdomain).feed
203
+ assert actual["rss"]["channel"]
204
+ assert_nil actual["rss"]["channel"]["item"]
205
+ assert_match subdomain, actual["rss"]["channel"]["webMaster"]
206
+ end
207
+
208
+ def test_bad_url
209
+ Glue::RSS.stubs(:get).returns(@html_page)
210
+ actual = Glue::RSS.new('666-DIE-666').feed
211
+ assert actual["html"]
212
+ assert_nil actual["rss"]
213
+ assert_raise NoMethodError do
214
+ actual["rss"]["channel"]
215
+ end
216
+ end
217
+
218
+ end