magnolia 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
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
+