Class: Rubyfocus::Document

Inherits:
Object
  • Object
show all
Includes:
Searchable
Defined in:
lib/rubyfocus/document.rb

Overview

The Document is how rubyfocus stores an OmniFocus document, both locally and otherwise. A Document contains a number of arrays of contexts, settings, folders, projects, and tasks, and is also able to keep track of what patch it’s up to, for updating.

You can initialize a document through Document.new(doc), where doc is either an XML string, or a Nokogiri XML document (or nil). Alternatively, you can initialize through Document.from_file(file), which reads the file and parses it as XML

You add XML to the document by running Documet::apply_xml(doc), which takes all children of the root XML node, tries to turn each child into a relevant object, and adds it to the document. This is done using the private ivar_for method, as well as add_element(e), which you can use to add individual objects.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Methods included from Searchable

#find, #select

Constructor Details

#initialize(doc = nil) ⇒ Document

Initalise with one of:

  • a Nokogiri document

  • a string

  • a fetcher subclass



28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
# File 'lib/rubyfocus/document.rb', line 28

def initialize(doc=nil)
	%w(contexts settings projects folders tasks).each{ |s| instance_variable_set("@#{s}", Rubyfocus::SearchableArray.new) }

	if doc
		if doc.is_a?(String)
			apply_xml(Nokogiri::XML(doc))
		elsif doc.is_a?(Nokogiri::XML)
			apply_xml(doc)
		elsif doc.kind_of?(Rubyfocus::Fetcher)
			self.fetcher = doc
			base = Nokogiri::XML(doc.base)
			self.apply_xml(base)
			self.patch_id = doc.base_id
		end
	end
end

Instance Attribute Details

#contextsObject (readonly)

A number of arrays into which elements may fit



15
16
17
# File 'lib/rubyfocus/document.rb', line 15

def contexts
  @contexts
end

#fetcherObject

This is the fetcher object, used to fetch new data



22
23
24
# File 'lib/rubyfocus/document.rb', line 22

def fetcher
  @fetcher
end

#foldersObject (readonly)

A number of arrays into which elements may fit



15
16
17
# File 'lib/rubyfocus/document.rb', line 15

def folders
  @folders
end

#patch_idObject

This is the identifier of the current patch level. This also determines which patches can be applied to the current document.



19
20
21
# File 'lib/rubyfocus/document.rb', line 19

def patch_id
  @patch_id
end

#projectsObject (readonly)

A number of arrays into which elements may fit



15
16
17
# File 'lib/rubyfocus/document.rb', line 15

def projects
  @projects
end

#settingsObject (readonly)

A number of arrays into which elements may fit



15
16
17
# File 'lib/rubyfocus/document.rb', line 15

def settings
  @settings
end

#tasksObject (readonly)

A number of arrays into which elements may fit



15
16
17
# File 'lib/rubyfocus/document.rb', line 15

def tasks
  @tasks
end

Class Method Details

.from_localObject

Initialize from the local repo



51
52
53
# File 'lib/rubyfocus/document.rb', line 51

def self.from_local
	new(Rubyfocus::LocalFetcher.new)
end

.from_url(url) ⇒ Object

Initialize with a URL, for remote fetching. Not implemented yet

Raises:

  • (RuntimeError)


57
58
59
60
# File 'lib/rubyfocus/document.rb', line 57

def self.from_url(url)
	raise RuntimeError, "Rubyfocus::Document.from_url not yet implemented."
	# new(Rubyfocus::RemoteFetcher.new(url))
end

.from_xml(file) ⇒ Object

…or from file! If you provide it with an XML file, it’ll load up without a fetcher.



46
47
48
# File 'lib/rubyfocus/document.rb', line 46

def self.from_xml(file)
	new(File.read(file))
end

.load_from_file(file_location) ⇒ Object

Load from a a hash



63
64
65
66
67
# File 'lib/rubyfocus/document.rb', line 63

def self.load_from_file(file_location)
	d = YAML::load_file(file_location)
	d.fetcher.reset
	d
end

Instance Method Details

#[](search_id) ⇒ Object


Find elements from id



136
137
138
# File 'lib/rubyfocus/document.rb', line 136

def [] search_id
	self.elements.find{ |elem| elem.id == search_id }
end

#add_element(e) ⇒ Object

Add an element. Element should be a Project, Task, Context, Folder, or Setting We assume whoever does this will set document appropriately on the element



101
102
103
104
105
106
107
108
# File 'lib/rubyfocus/document.rb', line 101

def add_element(e)
	dest = ivar_for(e)
	if dest
		dest << e
	else
		raise ArgumentError, "You passed a #{e.class} to Document#add_element - I don't know what to do with this."
	end
end

#apply_xml(doc) ⇒ Object


Apply XML!



81
82
83
84
85
# File 'lib/rubyfocus/document.rb', line 81

def apply_xml(doc)
	doc.root.children.select{ |e| !e.text? }.each do |node|
		elem = Rubyfocus::Parser.parse(self, node)
	end
end

#elementsObject Also known as: array


Searchable stuff



127
128
129
# File 'lib/rubyfocus/document.rb', line 127

def elements
	@tasks + @projects + @contexts + @folders + @settings
end

#remove_element(e) ⇒ Object

Remove an element from the document. We assume whoever does this is smart enough to also set the element’s #document value to nil



113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rubyfocus/document.rb', line 113

def remove_element(e)
	e = self[e] if e.is_a?(String)
	return if e.nil?

	dest = ivar_for(e)
	if dest
		dest.delete(e)
	else
		raise ArgumentError, "You passed a #{e.class} to Document#remove_element - I don't know what to do with this."	
	end
end

#save(file) ⇒ Object


YAML export



143
144
145
# File 'lib/rubyfocus/document.rb', line 143

def save(file)
	File.open(file, "w"){ |io| io.puts YAML::dump(self) }
end

#updateObject


Use the linked fetcher to update the document



71
72
73
74
75
76
77
# File 'lib/rubyfocus/document.rb', line 71

def update
	if fetcher
		fetcher.update_full(self)
	else
		raise RuntimeError, "Tried to update a document with no fetcher."
	end
end