magnolia 1.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.
File without changes
data/README ADDED
@@ -0,0 +1,3 @@
1
+ Check out the code, it is pretty well documented.
2
+
3
+ svn: http://svn.addictedtonew.com/libs/addicted-to-magnolia/trunk/
@@ -0,0 +1,85 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+ require 'rake/clean'
4
+ require 'rake/testtask'
5
+ require 'rake/packagetask'
6
+ require 'rake/gempackagetask'
7
+ require 'rake/rdoctask'
8
+ require 'rake/contrib/rubyforgepublisher'
9
+ require 'fileutils'
10
+ include FileUtils
11
+ require File.join(File.dirname(__FILE__), 'lib', 'magnolia', 'version')
12
+
13
+ AUTHOR = "John Nunemaker"
14
+ EMAIL = "nunemaker@gmail.com"
15
+ DESCRIPTION = "Library which makes it really easy to access your ma.gnolia bookmarks"
16
+ RUBYFORGE_PROJECT = "magnolia"
17
+ HOMEPATH = "http://#{RUBYFORGE_PROJECT}.rubyforge.org"
18
+ BIN_FILES = %w( )
19
+
20
+
21
+ NAME = "magnolia"
22
+ REV = File.read(".svn/entries")[/committed-rev="(d+)"/, 1] rescue nil
23
+ VERS = ENV['VERSION'] || (Magnolium::VERSION::STRING + (REV ? ".#{REV}" : ""))
24
+ CLEAN.include ['**/.*.sw?', '*.gem', '.config']
25
+ RDOC_OPTS = ['--quiet', '--title', "magnolia documentation",
26
+ "--opname", "index.html",
27
+ "--line-numbers",
28
+ "--main", "README",
29
+ "--inline-source"]
30
+
31
+ desc "Packages up magnolia gem."
32
+ task :default => [:test]
33
+ task :package => [:clean]
34
+
35
+ Rake::TestTask.new("test") { |t|
36
+ t.libs << "test"
37
+ t.pattern = "test/**/*_test.rb"
38
+ t.verbose = true
39
+ }
40
+
41
+ spec =
42
+ Gem::Specification.new do |s|
43
+ s.name = NAME
44
+ s.version = VERS
45
+ s.platform = Gem::Platform::RUBY
46
+ s.has_rdoc = true
47
+ s.extra_rdoc_files = ["README", "CHANGELOG"]
48
+ s.rdoc_options += RDOC_OPTS + ['--exclude', '^(examples|extras)/']
49
+ s.summary = DESCRIPTION
50
+ s.description = DESCRIPTION
51
+ s.author = AUTHOR
52
+ s.email = EMAIL
53
+ s.homepage = HOMEPATH
54
+ s.executables = BIN_FILES
55
+ s.rubyforge_project = RUBYFORGE_PROJECT
56
+ s.bindir = "bin"
57
+ s.require_path = "lib"
58
+ s.autorequire = "magnolia"
59
+
60
+ #s.add_dependency('activesupport', '>=1.3.1')
61
+ #s.required_ruby_version = '>= 1.8.2'
62
+
63
+ s.files = %w(README CHANGELOG Rakefile) +
64
+ Dir.glob("{bin,doc,test,lib,templates,generator,extras,website,script}/**/*") +
65
+ Dir.glob("ext/**/*.{h,c,rb}") +
66
+ Dir.glob("examples/**/*.rb") +
67
+ Dir.glob("tools/*.rb")
68
+
69
+ # s.extensions = FileList["ext/**/extconf.rb"].to_a
70
+ end
71
+
72
+ Rake::GemPackageTask.new(spec) do |p|
73
+ p.need_tar = true
74
+ p.gem_spec = spec
75
+ end
76
+
77
+ task :install do
78
+ name = "#{NAME}-#{VERS}.gem"
79
+ sh %{rake package}
80
+ sh %{sudo gem install pkg/#{name}}
81
+ end
82
+
83
+ task :uninstall => [:clean] do
84
+ sh %{sudo gem uninstall #{NAME}}
85
+ end
@@ -0,0 +1,108 @@
1
+ require 'magnolia'
2
+
3
+ # This is a test account I set up. Please do not use this key or mess with the test account. Thanks.
4
+ Magnolia.new('fc18b7bd1caf67b06b16a462b0b3c00890304ad9')
5
+
6
+ puts '---Testing the adding of a bookmark...'
7
+ begin
8
+ marks = Magnolia.add(:title => 'Addicted To New',
9
+ :description => 'A really cool site.',
10
+ :tags => 'me, addicting, cool',
11
+ :rating => 5,
12
+ :url => 'http://addictedtonew.com/')
13
+ addicted_mark = marks[0]
14
+ puts addicted_mark.title
15
+ rescue Magnolia::RequestError => msg
16
+ puts msg
17
+ marks = Magnolia.search(:url => 'http://addictedtonew.com/')
18
+ addicted_mark = marks[0] if marks.size > 0
19
+ end
20
+
21
+ puts
22
+ puts '---Testing the updating of a bookmark...'
23
+ marks = Magnolia.update(:id => addicted_mark.id, :title => 'Addicted To New by John Nunemaker')
24
+ markadd = marks[0]
25
+ puts markadd.title
26
+
27
+ puts
28
+ puts '---Testing Mark#save...'
29
+ begin
30
+ markol = Magnolia::Mark.new
31
+ markol.title = 'Ordered List'
32
+ markol.url = 'http://orderedlist.com'
33
+ markol.tags = 'steve smith, coding'
34
+ markol.save
35
+ puts 'new mark id: ' + markol.id
36
+ markol.title = 'Ordered List by Steve Smith'
37
+ puts 'Tags are: ' + markol.tags.inspect
38
+ markol.tags = nil
39
+ markol.save
40
+ marks = Magnolia.find(:id => markol.id)
41
+ upmark = marks[0]
42
+ puts 'Title updated to: ' + upmark.title
43
+ puts 'Tags are: ' + upmark.tags.inspect
44
+ rescue Magnolia::RequestError => msg
45
+ puts msg
46
+ marks = Magnolia.search(:url => 'http://orderedlist.com')
47
+ markol = marks[0] if marks.size > 0
48
+ end
49
+
50
+ puts
51
+ puts '---Testing the find method ...'
52
+ begin
53
+ marks = Magnolia.search(:person => 'magnoliaapitest')
54
+ marks.each do |mark|
55
+ puts mark.title, " #{mark.id}"
56
+ end
57
+ rescue Magnolia::RequestError => msg
58
+ puts msg
59
+ end
60
+
61
+ puts
62
+ puts '---Testing the get method ...'
63
+ marks = Magnolia.find(:id => addicted_mark.id)
64
+ marks.each do |mark|
65
+ puts mark.img_tag
66
+ puts mark.a_tag
67
+ end
68
+
69
+ puts
70
+ puts '---Testing the Mark#find method ...'
71
+ mark = Magnolia::Mark.find(addicted_mark.id)
72
+ puts mark.title
73
+
74
+ puts
75
+ puts '---Testing the adding of a tag...'
76
+ Magnolia.add_tags(:id => addicted_mark.id, :tags => 'john nunemaker')
77
+ marks = Magnolia.find(:id => addicted_mark.id)
78
+ puts marks[0].tags.inspect
79
+
80
+ Magnolia.delete_tags(:id => addicted_mark.id, :tags => 'john nunemaker')
81
+ marks = Magnolia.find(:id => addicted_mark.id)
82
+ puts marks[0].tags.inspect
83
+
84
+ puts
85
+ puts '---Testing the renaming of a tag...'
86
+ Magnolia.rename_tags(:id => 'all', :old => 'addicting', :new => 'very addicting')
87
+ marks = Magnolia.find(:id => addicted_mark.id)
88
+ puts marks[0].tags.inspect
89
+ Magnolia.rename_tags(:id => 'all', :old => 'very addicting', :new => 'addicting')
90
+ marks = Magnolia.find(:id => addicted_mark.id)
91
+ puts marks[0].tags.inspect
92
+
93
+ puts
94
+ puts '---Testing the deleting of addicted bookmark...'
95
+ Magnolia.delete(:id => addicted_mark.id)
96
+ puts '---Testing the deleting of ol bookmark...'
97
+ Magnolia.delete(:id => markol.id)
98
+
99
+ puts "---Testing the finding of a person's tags..."
100
+ tags = Magnolia.tags_find(:person => 'jnunemaker')
101
+ puts "Getting all of jnunemaker's tags...Total: #{tags.size}"
102
+ puts "Printing first ten tags..."
103
+ tags[0..10].each do |tag|
104
+ puts "#{tag.name} #{tag.count}"
105
+ end
106
+
107
+ puts
108
+ puts '---End of tests'
@@ -0,0 +1 @@
1
+ Dir[File.join(File.dirname(__FILE__), 'magnolia/**/*.rb')].sort.each { |lib| require lib }
@@ -0,0 +1,486 @@
1
+ # :title:Addicted To Ma.gnolia by John Nunemaker
2
+ # = Addicted To Ma.gnolia
3
+ #
4
+ # This class makes it really simple to access your Ma.gnolia bookmarks
5
+ # using the Ma.gnolia API[http://ma.gnolia.com/support/api/].
6
+ #
7
+ # Author:: John Nunemaker
8
+ # Website:: http://addictedtonew.com
9
+ # Last Updated:: June 3, 2006 @ 12:57AM EST
10
+ # Copyright:: Copyright (c) 2006 John Nunemaker
11
+ # License:: MIT <http://www.opensource.org/licenses/mit-license.php>
12
+ #
13
+ # == URL's For Downloads and Information
14
+ #
15
+ # * Ruby Forge: http://rubyforge.org/projects/magnolia/
16
+ # * SVN: svn checkout http://svn.addictedtonew.com/libs/addicted-to-magnolia/
17
+ # * Blog Entry: http://addictedtonew.com/archives/155/ruby-magnolia-api-class/
18
+ # * Online RDocs: http://addictedtonew.com/examples/magnolia/
19
+ #
20
+ # == Examples
21
+ #
22
+ # my_latest = Magnolia.search(:person => 'jnunemaker') # will find my last ten bookmarks
23
+ # group_latest = Magnolia.search(:group => 'webmedia') # will find the last ten bookmarks of the webmedia group
24
+ #
25
+ #
26
+ # == Copyright
27
+ #
28
+ # Copyright (c) 2006 John Nunemaker
29
+ #
30
+ # Permission is hereby granted, free of charge, to any person obtaining
31
+ # a copy of this software and associated documentation files (the "Software"),
32
+ # to deal in the Software without restriction, including without limitation
33
+ # the rights to use, copy, modify, merge, publish, distribute, sublicense,
34
+ # and/or sell copies of the Software, and to permit persons to whom the Software
35
+ # is furnished to do so, subject to the following conditions:
36
+ #
37
+ # The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
38
+ #
39
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
40
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
41
+ # OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
42
+ # IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
43
+ # DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
44
+ # ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
45
+ # DEALINGS IN THE SOFTWARE.
46
+ require 'net/http'
47
+ require 'rexml/document'
48
+ require 'cgi'
49
+
50
+ class Magnolia
51
+ # Exceptions
52
+ class MissingData < StandardError #:nodoc:
53
+ end
54
+ class RequestError < StandardError #:nodoc:
55
+ end
56
+
57
+ # This must be called before any of the other methods can be used. It sets a class variable named <tt>api_key</tt>
58
+ # which all the other class methods use when making requests.
59
+ #
60
+ # == Example
61
+ #
62
+ # Magnolia.new('yourgreatsuperapikey')
63
+ def initialize(api_key)
64
+ Magnolia.set_api_key(api_key)
65
+ end
66
+
67
+ class << self
68
+ # Sets the api key for all requests
69
+ def set_api_key(api_key)
70
+ @@api_key = api_key
71
+ end
72
+
73
+ # This method searches for bookmarks that match certain criteria provided by you. Ma.gnolia named this method <tt>bookmarks_find</tt>
74
+ # but I thought it was more appropriately named <tt>search</tt>.
75
+ #
76
+ # == Examples
77
+ #
78
+ # latest = Magnolia.find(:person => 'jnunemaker') # will find my last ten bookmarks
79
+ # recent = Magnolia.find(:person => 'jnunemaker', :limit => 20) # will find my last 20 bookmarks
80
+ # nice = Magnolia.find(:person => 'jnunemaker', :tags => 'nice', :limit => 5) # will find my last 5 bookmarks tagged 'nice'
81
+ #
82
+ # Let's get a bit trickier. Below will rescue from a request error such as not enough information or person not found, etc.
83
+ #
84
+ # begin
85
+ # marks = Magnolia.search(:person => 'jnunemaker')
86
+ # marks.each do |mark|
87
+ # puts mark.title, " #{mark.id}"
88
+ # end
89
+ # rescue Magnolia::RequestError => msg
90
+ # puts msg
91
+ # end
92
+ #
93
+ # == Options
94
+ #
95
+ # :tags - Multiple tags are treated as an AND search; seperate multiples with commas
96
+ # :person - Multiple screen names are treated as an ‘OR’ search; seperate multiples with commas
97
+ # :group - Multiple groups are treated as an ‘OR’ search; seperate multiples with commas
98
+ # :rating - Only bookmarks rated this value or higher will be returned
99
+ # :from - Only bookmarks created after this date time will be returned
100
+ # :to - Only bookmarks created before this date time will be returned
101
+ # :url - Only return bookmarks with this url
102
+ # :limit - A maximum number of bookmarks to return from search
103
+ #
104
+ # == Return Value
105
+ #
106
+ # Returns an array of Marks.
107
+ def search(options = {})
108
+ params = { :tags => nil,
109
+ :person => nil,
110
+ :group => nil,
111
+ :rating => nil,
112
+ :from => nil,
113
+ :to => nil,
114
+ :url => nil,
115
+ :limit => 10 }
116
+ params.update(options)
117
+
118
+ create_marks_from_xml(make_request('bookmarks_find', params))
119
+ end
120
+
121
+ # This method is basically like a Ruby on Rails <tt>find</tt> method. Pass it a short name (which is basically an id)
122
+ # or comma-seperated short names and
123
+ # it will return each mark that is found. Because it is similar to rails <tt>find</tt> method, I have aliased it.
124
+ #
125
+ # == Examples
126
+ #
127
+ # getone = Magnolia.get(:id => 'rubyonrails')
128
+ # getmultiple = Magnolia.get(:id => 'rubyonrails,ruby,someotherid')
129
+ #
130
+ # If you like Ruby on Rails and think <tt>find</tt> is a more appropriate name for the method, feel free to use it.
131
+ #
132
+ # getdiff = Magnolia.find(:id => 'id1')
133
+ #
134
+ # == Options
135
+ #
136
+ # :id - The short name for one or more bookmarks; seperate multiples with commas (required)
137
+ #
138
+ # == Return Value
139
+ #
140
+ # Returns an array of Marks.
141
+ def get(marks = {})
142
+ raise MissingData, 'The id must be included in order to know which bookmarks to get.' unless marks.include? :id
143
+ create_marks_from_xml(make_request('bookmarks_get', marks))
144
+ end
145
+ alias :find :get
146
+
147
+ # == Examples
148
+ #
149
+ # Magnolia.add(:title => 'Addicted To New',
150
+ # :description => 'A great site!',
151
+ # :url => 'http://addictedtonew.com/',
152
+ # :private => 'false',
153
+ # :tags => 'cool dude, lame tag, addicting',
154
+ # :rating => 5)
155
+ #
156
+ # == Options
157
+ #
158
+ # :url - A URL string. Must be valid (required)
159
+ # :title - A title string (optional)
160
+ # :description - A description string (optional)
161
+ # :private - The bookmark’s privacy status; either 'true' or 'false' (optional)
162
+ # :tags - A list of tags. This will completely replace any existing tags for each specified bookmark (optional)
163
+ # :rating - An integer representing a star rating; 1-5 (optional)
164
+ #
165
+ # == Return Value
166
+ #
167
+ # Returns an array containing the added mark
168
+ def add(mark = {})
169
+ raise MissingData, 'The url must be included to add a mark.' unless mark.include? :url
170
+ create_marks_from_xml(make_request('bookmarks_add', mark))
171
+ end
172
+ alias :create :add
173
+
174
+ # == Examples
175
+ #
176
+ # delone = Magnolia.delete(:id => 'java')
177
+ # delmultiple = Magnolia.delete(:id => 'java,perl,someotherid')
178
+ # deldiff = Magnolia.destroy(:id => 'someid')
179
+ #
180
+ # == Options
181
+ #
182
+ # :id - The short name for one or more bookmarks; seperate multiples with commas (required)
183
+ #
184
+ # == Return Value
185
+ #
186
+ # Nuttin
187
+ def delete(marks = {})
188
+ make_request('bookmarks_delete', marks)
189
+ end
190
+ alias :destroy :delete
191
+
192
+ # == Examples
193
+ #
194
+ # Magnolia.update(:id => 'someid',
195
+ # :title => 'Addicted To New',
196
+ # :description => 'A great site!',
197
+ # :url => 'http://addictedtonew.com/',
198
+ # :private => 'false',
199
+ # :tags => 'cool dude, lame tag, addicting',
200
+ # :rating => 5)
201
+ #
202
+ # == Options
203
+ #
204
+ # :id - The short name for one bookmark (required)
205
+ # :url - A URL string. Must be valid (optional)
206
+ # :title - A title string (optional)
207
+ # :description - A description string (optional)
208
+ # :private - The bookmark’s privacy status; either 'true' or 'false' (optional)
209
+ # :tags - A list of tags. This will completely replace any existing tags for each specified bookmark (optional)
210
+ # :rating - An integer representing a star rating; 1-5 (optional)
211
+ #
212
+ # == Return Value
213
+ #
214
+ # Returns an array containing the updated mark.
215
+ def update(mark = {})
216
+ raise MissingData, 'The id must be included in order to know which bookmark to update.' unless mark.include? :id
217
+ create_marks_from_xml(make_request('bookmarks_update', mark))
218
+ end
219
+ alias :edit :update
220
+
221
+ # == Examples
222
+ #
223
+ # Magnolia.tags_add(:id => 'rubyonrails', :tags => 'fast,simple')
224
+ #
225
+ # You can also use add_tags if tags_add seems backwards.
226
+ # Magnolia.add_tags(:id => 'rubyonrails', :tags => 'fast,simple')
227
+ #
228
+ # == Options
229
+ #
230
+ # :id - One or more bookmark short names to which the specified tags should be added
231
+ # :tags - Tags to be added to the specified bookmarks
232
+ #
233
+ # == Return Value
234
+ #
235
+ # Nuttin
236
+ def tags_add(mark = {})
237
+ raise MissingData, 'The id must be included in order to know which bookmark to add tags to.' unless mark.include? :id
238
+ raise MissingData, 'The tags must be included that you want to add.' unless mark.include? :tags
239
+ make_request('bookmarks_tags_add', mark)
240
+ end
241
+ alias :add_tags :tags_add
242
+
243
+ # == Examples
244
+ #
245
+ # Magnolia.tags_delete(:id => 'java', :tags => 'cool,fun')
246
+ #
247
+ # You can also use add_tags if tags_add seems backwards.
248
+ # Magnolia.add_tags(:id => 'id1', :tags => 'newtag1,newtag2')
249
+ #
250
+ # == Options
251
+ #
252
+ # :id - One or more bookmark short names to which the specified tags should be added
253
+ # :tags - Tags to be added to the specified bookmarks
254
+ #
255
+ # == Return Value
256
+ #
257
+ # Nuttin
258
+ def tags_delete(mark = {})
259
+ raise MissingData, 'The id must be included in order to know which bookmark to add tags to.' unless mark.include? :id
260
+ raise MissingData, 'The tags must be included that you want to add.' unless mark.include? :tags
261
+ make_request('bookmarks_tags_delete', mark)
262
+ end
263
+ alias :delete_tags :tags_delete
264
+
265
+ # == Examples
266
+ #
267
+ # Magnolia.tags_replace(:id => 'languages', :old => 'java', :new => 'rubyonrails')
268
+ #
269
+ # You can also use any of these below if you don't like tags_delete
270
+ # Magnolia.replace_tags(:id => 'languages', :old => 'java', :new => 'rubyonrails')
271
+ # Magnolia.rename_tags(:id => 'languages', :old => 'java', :new => 'rubyonrails')
272
+ # Magnolia.tags_rename(:id => 'languages', :old => 'java', :new => 'rubyonrails')
273
+ #
274
+ # == Options
275
+ #
276
+ # :id - One or more bookmark short names to which the specified tags should be added
277
+ # :old - Existing tag to be replaced
278
+ # :new - New tag to replace existing tag
279
+ #
280
+ # == Return Value
281
+ #
282
+ # Nuttin
283
+ def tags_replace(mark = {})
284
+ raise MissingData, 'The id must be included in order to know which bookmark to rename tags for.' unless mark.include? :id
285
+ raise MissingData, 'The old tag is required.' unless mark.include? :old
286
+ raise MissingData, 'The new tag is required.' unless mark.include? :new
287
+ make_request('bookmarks_tags_replace', mark)
288
+ end
289
+ alias :replace_tags :tags_replace
290
+ alias :rename_tags :tags_replace
291
+ alias :tags_rename :tags_replace
292
+
293
+ # == Examples
294
+ #
295
+ # tags = Magnolia.tags_find(:person => 'jnunemaker')
296
+ # tags.each do |tag|
297
+ # puts tag.name
298
+ # end
299
+ #
300
+ # You can also use the alias of find_tags if it makes more sense to you
301
+ #
302
+ # tags = Magnolia.find_tags(:person => 'jnunemaker')
303
+ #
304
+ # == Options
305
+ #
306
+ # :person - The person whose tags you would like to find
307
+ #
308
+ # == Return Value
309
+ #
310
+ # An array of Tag objects
311
+ def tags_find(mark = {})
312
+ raise MissingData, 'The person (screen name) is required.' unless mark.include? :person
313
+ root = make_request('tags_find', mark)
314
+ create_tags_from_xml(root)
315
+ end
316
+ alias :find_tags :tags_find
317
+
318
+ private
319
+ # Makes a request to magnolia and processes that request if need be
320
+ def make_request(api_method, params={})
321
+ params.update({ :api_key => @@api_key })
322
+ path = "/api/rest/1/#{api_method}"
323
+ http = Net::HTTP.new('ma.gnolia.com', 80)
324
+ response = http.post(path, hash_to_qs(params))
325
+ raise RequestError, "Cannot make request (#{response.message})!" unless response.message == 'OK'
326
+
327
+ # Find out if the request did in fact return xml, raise RequestError if it didn't
328
+ begin
329
+ doc = REXML::Document.new(response.body)
330
+ rescue
331
+ raise RequestError, 'XML was not returned as the response body.'
332
+ end
333
+
334
+ # We now have an xml document so let's see if it contains good stuff or a magnolia error message
335
+ # If magnolia error message, then raise a RequestError
336
+ root = doc.root
337
+ unless root.attributes['status'] == 'ok'
338
+ error_message = root.elements["error"].attributes['message']
339
+ error_code = root.elements["error"].attributes['code']
340
+ raise RequestError, "#{error_code}: #{error_message}"
341
+ end
342
+ root
343
+ end
344
+
345
+ # creates an array of bookmarks objects from xml
346
+ def create_marks_from_xml(xml)
347
+ marks = []
348
+ REXML::XPath.each(xml, "bookmarks/bookmark") do |mark|
349
+ marks << Mark.from_xml(mark)
350
+ end
351
+ marks
352
+ end
353
+
354
+ # creates an array of tag objects from xml
355
+ def create_tags_from_xml(xml)
356
+ tags = []
357
+ REXML::XPath.each(xml, "tags/tag") do |tag_xml|
358
+ tags << Tag.from_xml(tag_xml)
359
+ end
360
+ tags
361
+ end
362
+
363
+ # Converts a hash to a query string
364
+ def hash_to_qs(h)
365
+ str = ''
366
+ h.each { |key,val| str += "#{key}=#{CGI.escape(val.to_s)}&" unless val.nil? }
367
+ str
368
+ end
369
+ end # class self
370
+
371
+ # The mark class is used to store information about each bookmark after it is found, created or updated.
372
+ # Each method that is not in the DONT_PROCESS constant returns and array of <tt>Mark</tt> objects.
373
+ class Mark
374
+ def initialize
375
+ @tags = []
376
+ end
377
+ attr_accessor :id, :title, :url, :description
378
+ attr_accessor :screenshot, :rating, :private
379
+ attr_accessor :created, :updated, :owner, :tags
380
+ attr_reader :img_tag, :a_tag
381
+
382
+ # Creates an image tag for the screenshot image with the title as the alt text
383
+ def img_tag
384
+ "<img src='#{self.screenshot}' alt='#{self.title}' />"
385
+ end
386
+
387
+ # Creates a link to the url of the bookmark with the title as the text
388
+ def a_tag
389
+ "<a href='#{self.url}' title='Link to #{self.title}'>#{self.title}</a>"
390
+ end
391
+
392
+ # This method allows working with bookmarks much like ActiveRecord.
393
+ #
394
+ # == Examples
395
+ #
396
+ # mark = Magnolia::Mark.new
397
+ # mark.title = 'Addicted To New'
398
+ # mark.url = 'http://addictedtonew.com/'
399
+ # mark.tags = ['john nunemaker', 'me'] # you can also use comma-seperated list mark.tags = 'john nunemaker, me'
400
+ # mark.save
401
+ # puts mark.id # this is the id of the newly created bookmark
402
+ #
403
+ # You can also use it to update bookmarks like so:
404
+ #
405
+ # mark = Magnolia::Mark.find(:id => 'someshortname')
406
+ # mark.title = 'Addicted To New by John Nunemaker'
407
+ # mark.save
408
+ def save
409
+ if self.id == nil
410
+ # create a new bookmark
411
+ mark = to_h
412
+ marks = Magnolia.add(mark)
413
+ self.id = marks[0].id
414
+ else
415
+ # update an existing bookmark
416
+ mark = to_h
417
+ marks = Magnolia.update(mark)
418
+ end
419
+ end
420
+
421
+ # Returns the mark in hash form. This is used in the save method to pass the object in as a hash to the
422
+ # Magnolia <tt>add</tt> or <tt>update</tt> methods.
423
+ def to_h
424
+ mark = {:id => self.id,
425
+ :title => self.title,
426
+ :description => self.description,
427
+ :url => self.url,
428
+ :rating => self.rating,
429
+ :private => self.private}
430
+ if self.tags.nil?
431
+ mark.update({:tags => ''})
432
+ else
433
+ # allow for tags to be comma seperated list or array
434
+ if self.tags.is_a?(String)
435
+ mark.update({:tags => self.tags})
436
+ # turn the tags into an array
437
+ self.tags = self.tags.split(',')
438
+ elsif self.tags.is_a?(Array)
439
+ mark.update({:tags => self.tags.join(',')})
440
+ end
441
+ end
442
+ mark
443
+ end
444
+ private :to_h
445
+
446
+ class << self
447
+ # Finds a single bookmark by it's id (short name). If not found raises a Magnolia::RequestError
448
+ def find(id)
449
+ marks = Magnolia.get(:id =>id)
450
+ marks[0]
451
+ end
452
+
453
+ # Converts xml into a mark
454
+ def from_xml(xml)
455
+ mark = Mark.new()
456
+ mark.title = xml.elements['title'].text
457
+ mark.url = xml.elements['url'].text
458
+ mark.description = xml.elements['description'].text
459
+ mark.screenshot = xml.elements['screenshot'].text
460
+ mark.id = xml.attributes['id']
461
+ mark.rating = xml.attributes['rating']
462
+ mark.private = xml.attributes['private']
463
+ mark.created = xml.attributes['created']
464
+ mark.updated = xml.attributes['updated']
465
+ mark.owner = xml.attributes['owner']
466
+ REXML::XPath.each(xml, 'tags/tag') do |tag|
467
+ mark.tags << tag.attributes['name']
468
+ end
469
+ mark
470
+ end
471
+ end # class self
472
+ end # class Mark
473
+
474
+ class Tag
475
+ attr_accessor :name, :count
476
+
477
+ class << self
478
+ def from_xml(xml)
479
+ t = Tag.new
480
+ t.name = xml.attributes['name']
481
+ t.count = xml.attributes['count']
482
+ t
483
+ end
484
+ end
485
+ end
486
+ end # class Magnolia
@@ -0,0 +1,9 @@
1
+ module Magnolium #:nodoc:
2
+ module VERSION #:nodoc:
3
+ MAJOR = 1
4
+ MINOR = 1
5
+ TINY = 0
6
+
7
+ STRING = [MAJOR, MINOR, TINY].join('.')
8
+ end
9
+ end
@@ -0,0 +1,11 @@
1
+ require File.dirname(__FILE__) + '/test_helper.rb'
2
+
3
+ class MagnoliumTest < Test::Unit::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def test_truth
9
+ assert true
10
+ end
11
+ end
@@ -0,0 +1,2 @@
1
+ require 'test/unit'
2
+ require File.dirname(__FILE__) + '/../lib/magnolia'
metadata ADDED
@@ -0,0 +1,65 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.8.11
3
+ specification_version: 1
4
+ name: magnolia
5
+ version: !ruby/object:Gem::Version
6
+ version: 1.1.0
7
+ date: 2006-10-24 00:00:00 -04:00
8
+ summary: Library which makes it really easy to access your ma.gnolia bookmarks
9
+ require_paths:
10
+ - lib
11
+ email: nunemaker@gmail.com
12
+ homepage: http://magnolia.rubyforge.org
13
+ rubyforge_project: magnolia
14
+ description: Library which makes it really easy to access your ma.gnolia bookmarks
15
+ autorequire: magnolia
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: true
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ authors:
29
+ - John Nunemaker
30
+ files:
31
+ - README
32
+ - CHANGELOG
33
+ - Rakefile
34
+ - test/magnolia_test.rb
35
+ - test/test_helper.rb
36
+ - lib/magnolia
37
+ - lib/magnolia.rb
38
+ - lib/magnolia/magnolia.rb
39
+ - lib/magnolia/version.rb
40
+ - examples/examples.rb
41
+ test_files: []
42
+
43
+ rdoc_options:
44
+ - --quiet
45
+ - --title
46
+ - magnolia documentation
47
+ - --opname
48
+ - index.html
49
+ - --line-numbers
50
+ - --main
51
+ - README
52
+ - --inline-source
53
+ - --exclude
54
+ - ^(examples|extras)/
55
+ extra_rdoc_files:
56
+ - README
57
+ - CHANGELOG
58
+ executables: []
59
+
60
+ extensions: []
61
+
62
+ requirements: []
63
+
64
+ dependencies: []
65
+