rubyfocus 0.3.1 → 0.4.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.
- checksums.yaml +4 -4
- data/README.md +26 -6
- data/lib/rubyfocus/document.rb +30 -7
- data/lib/rubyfocus/includes/idref.rb +1 -1
- data/lib/rubyfocus/items/context.rb +0 -1
- data/lib/rubyfocus/items/folder.rb +0 -2
- data/lib/rubyfocus/items/item.rb +2 -10
- data/lib/rubyfocus/items/ranked_item.rb +19 -0
- data/lib/rubyfocus/items/task.rb +1 -1
- data/lib/rubyfocus/patch.rb +16 -29
- data/version.txt +1 -1
- metadata +2 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 63565e849764d58187bc270c714a509aec780ff5
|
4
|
+
data.tar.gz: 91c1408da7a1764a625d0ebd1434441dde52cd79
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 2f2925e0baae0e08eaf043a7dea9120446ab15b99729f9319c3c47e73feafe7246262879fa409734f0fce6e7566571a3711e3023d56217ec83af77a33ebdaad7
|
7
|
+
data.tar.gz: 119909f3d146a97f0d4cd7b3fd0c1afff0425220c8acfd235f6635609a3fe2fdfd33f3106bf51cbc85481a65c43dc991a01f68cf1f4d5110e91b5d2421c10166
|
data/README.md
CHANGED
@@ -1,8 +1,14 @@
|
|
1
|
+
# Version: 0.4.0
|
2
|
+
|
1
3
|
Rubyfocus is a one-way (read-only) ruby bridge to OmniFocus. Analyse, store, inspect, or play with your projects and tasks in OmniFocus from the comfort and flexibility of ruby!
|
2
4
|
|
3
5
|
# Installation
|
4
6
|
|
5
|
-
|
7
|
+
## Via rubygems
|
8
|
+
|
9
|
+
```
|
10
|
+
gem install rubyfocus
|
11
|
+
```
|
6
12
|
|
7
13
|
## Via git
|
8
14
|
|
@@ -16,7 +22,7 @@ Now build and install it!
|
|
16
22
|
|
17
23
|
```
|
18
24
|
gem build rubyfocus.gemspec
|
19
|
-
gem install rubyfocus-0.
|
25
|
+
gem install rubyfocus-0.3.0.gem
|
20
26
|
```
|
21
27
|
|
22
28
|
# Usage
|
@@ -64,13 +70,13 @@ d.projects.first.tasks
|
|
64
70
|
|
65
71
|
What if you want to select only certain projects? Sure, you can use standard `Array#find` or `Array#select` methods, but you can also make use of a hash of values:
|
66
72
|
|
67
|
-
```
|
73
|
+
```ruby
|
68
74
|
d.projects.select(name: "Sample project")
|
69
75
|
```
|
70
76
|
|
71
77
|
Once you have your objects, you can query them for more information:
|
72
78
|
|
73
|
-
```
|
79
|
+
```ruby
|
74
80
|
t = d.tasks.first
|
75
81
|
t.name # => "Sample task"
|
76
82
|
t.project.name # => "Sample project"
|
@@ -102,11 +108,25 @@ Rubyfocus makes use of this by fetching and reading OmniFocus' local store on yo
|
|
102
108
|
|
103
109
|
Other goals include:
|
104
110
|
|
105
|
-
*
|
106
|
-
*
|
111
|
+
* Registering with the Omni Sync Server, so you don't need to always delete + reinstantiate the database.
|
112
|
+
* Determining when you're "detached" from the latest version on the OSS.
|
113
|
+
* A couple of example projects using rubyfocus (especially a static webpage generator for kanban)
|
107
114
|
|
108
115
|
# History
|
109
116
|
|
117
|
+
## 0.4.0 // 2016-01-01
|
118
|
+
|
119
|
+
* Happy new year!
|
120
|
+
* [Modified] Container IDRef is now located on RankedItem, rather than having several on each RankedItem subclass.
|
121
|
+
* [New] RankedItems can look at their ancestry much more easily, using RankedItem#ancestry and RankedItem#contained_within?
|
122
|
+
* [New] Documents now forbid elements with duplicate IDs unless Document#allow_duplicate_ids is set to true.
|
123
|
+
* [New] Patchers now treate CREATE nodes on elements whose IDs already exist in the database as UPDATE nodes
|
124
|
+
* [Fixed] Patchers will now interpret missing parameters as "default values" e.g. project update without `status` parameter assumed to be active.
|
125
|
+
|
126
|
+
## 0.3.1 // 2015-12-31
|
127
|
+
|
128
|
+
* [Bugfix] IDRefs will now return +nil+ if the relevant ID is not set.
|
129
|
+
|
110
130
|
## 0.3.0 // 2015-10-17
|
111
131
|
|
112
132
|
* [New] Now supports remote syncing with the Omni Sync Server!
|
data/lib/rubyfocus/document.rb
CHANGED
@@ -53,7 +53,7 @@ class Rubyfocus::Document
|
|
53
53
|
end
|
54
54
|
|
55
55
|
# Initialize with a URL, for remote fetching.
|
56
|
-
# Not implemented yet
|
56
|
+
# Not implemented yet TODO implement
|
57
57
|
def self.from_url(url)
|
58
58
|
raise RuntimeError, "Rubyfocus::Document.from_url not yet implemented."
|
59
59
|
# new(Rubyfocus::RemoteFetcher.new(url))
|
@@ -96,9 +96,22 @@ class Rubyfocus::Document
|
|
96
96
|
end
|
97
97
|
private :ivar_for
|
98
98
|
|
99
|
-
# Add an element. Element should be a Project, Task, Context, Folder, or Setting
|
100
|
-
#
|
101
|
-
|
99
|
+
# Add an element. Element should be a Project, Task, Context, Folder, or Setting.
|
100
|
+
# If overwrite set to false and ID already occurs in the document, throw an error.
|
101
|
+
# If ID is nil, throw an error.
|
102
|
+
def add_element(e, overwrite:false)
|
103
|
+
# Error check
|
104
|
+
raise(Rubyfocus::DocumentElementException, "Adding element to document, but it has no ID.") if e.id.nil?
|
105
|
+
raise(Rubyfocus::DocumentElementException, "Adding element to document, but element with this ID already exists.") if !overwrite && has_id?(e.id)
|
106
|
+
|
107
|
+
# Otherwise, full steam ahead
|
108
|
+
e.document = self
|
109
|
+
|
110
|
+
if (dupe_element = self[e.id]) && overwrite
|
111
|
+
remove_element(dupe_element)
|
112
|
+
end
|
113
|
+
|
114
|
+
# Add to the correct array
|
102
115
|
dest = ivar_for(e)
|
103
116
|
if dest
|
104
117
|
dest << e
|
@@ -108,12 +121,12 @@ class Rubyfocus::Document
|
|
108
121
|
end
|
109
122
|
|
110
123
|
# Remove an element from the document.
|
111
|
-
# We assume whoever does this is smart enough to also set the element's #document value
|
112
|
-
# to nil
|
113
124
|
def remove_element(e)
|
114
125
|
e = self[e] if e.is_a?(String)
|
115
126
|
return if e.nil?
|
116
127
|
|
128
|
+
e.document = nil
|
129
|
+
|
117
130
|
dest = ivar_for(e)
|
118
131
|
if dest
|
119
132
|
dest.delete(e)
|
@@ -131,16 +144,26 @@ class Rubyfocus::Document
|
|
131
144
|
# For Searchable include
|
132
145
|
alias_method :array, :elements
|
133
146
|
|
147
|
+
|
134
148
|
#-------------------------------------------------------------------------------
|
135
149
|
# Find elements from id
|
136
150
|
def [] search_id
|
137
151
|
self.elements.find{ |elem| elem.id == search_id }
|
138
152
|
end
|
139
153
|
|
154
|
+
# Check if the document has an element of a given ID
|
155
|
+
def has_id?(id)
|
156
|
+
self.elements.any?{ |e| e.id == id }
|
157
|
+
end
|
158
|
+
|
140
159
|
#---------------------------------------
|
141
160
|
# YAML export
|
142
161
|
|
143
162
|
def save(file)
|
144
163
|
File.open(file, "w"){ |io| io.puts YAML::dump(self) }
|
145
164
|
end
|
146
|
-
end
|
165
|
+
end
|
166
|
+
|
167
|
+
#-------------------------------------------------------------------------------
|
168
|
+
# Exceptions
|
169
|
+
class Rubyfocus::DocumentElementException < Exception; end
|
@@ -6,7 +6,7 @@ module Rubyfocus
|
|
6
6
|
name_id = "#{name}_id".to_sym
|
7
7
|
attr_accessor name_id
|
8
8
|
define_method(name) do
|
9
|
-
return document &&
|
9
|
+
return document && (id_value = send(name_id)) && document.find(id_value)
|
10
10
|
end
|
11
11
|
|
12
12
|
define_method("#{name}=") do |o|
|
data/lib/rubyfocus/items/item.rb
CHANGED
@@ -13,8 +13,6 @@ class Rubyfocus::Item
|
|
13
13
|
attr_accessor :id, :added, :modified, :document
|
14
14
|
|
15
15
|
def initialize(document=nil, n=nil)
|
16
|
-
self.document = document
|
17
|
-
|
18
16
|
case n
|
19
17
|
when Nokogiri::XML::Element
|
20
18
|
apply_xml(n)
|
@@ -24,6 +22,8 @@ class Rubyfocus::Item
|
|
24
22
|
send(setter,v) if respond_to?(setter)
|
25
23
|
end
|
26
24
|
end
|
25
|
+
|
26
|
+
document.add_element(self) if document
|
27
27
|
end
|
28
28
|
|
29
29
|
def apply_xml(n)
|
@@ -45,14 +45,6 @@ class Rubyfocus::Item
|
|
45
45
|
inspect_properties.each_with_object({}){ |s,hsh| hsh[s] = self.send(s) }
|
46
46
|
end
|
47
47
|
|
48
|
-
#---------------------------------------
|
49
|
-
# Document set/get methods
|
50
|
-
def document= d
|
51
|
-
@document.remove_element(self) if @document
|
52
|
-
@document = d
|
53
|
-
@document.add_element(self) if @document
|
54
|
-
end
|
55
|
-
|
56
48
|
#-------------------------------------------------------------------------------
|
57
49
|
# Private inspect methods
|
58
50
|
|
@@ -1,6 +1,25 @@
|
|
1
1
|
class Rubyfocus::RankedItem < Rubyfocus::NamedItem
|
2
2
|
attr_accessor :rank
|
3
3
|
|
4
|
+
# Ranked items also happen to be contained items
|
5
|
+
idref :container
|
6
|
+
|
7
|
+
# Retrieve a full list of the parents of this item. [0] = immediate parent
|
8
|
+
def ancestry
|
9
|
+
if container
|
10
|
+
[container] + container.ancestry
|
11
|
+
else
|
12
|
+
[]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
# Is this item contained within another? You may supply an object, string or integer ID, hash of properties,
|
17
|
+
# or proc to run on each item.
|
18
|
+
def contained_within?(object)
|
19
|
+
object = document.find(object) if [String, Fixnum, Hash, Proc].include?(object.class)
|
20
|
+
ancestry.include?(object)
|
21
|
+
end
|
22
|
+
|
4
23
|
def apply_xml(n)
|
5
24
|
super(n)
|
6
25
|
conditional_set(:rank, n.at_xpath("xmlns:rank")){ |e| e.inner_html.to_i }
|
data/lib/rubyfocus/items/task.rb
CHANGED
data/lib/rubyfocus/patch.rb
CHANGED
@@ -92,45 +92,32 @@ class Rubyfocus::Patch
|
|
92
92
|
end
|
93
93
|
end
|
94
94
|
|
95
|
-
# Apply this patch to a document.
|
95
|
+
# Apply this patch to a document.
|
96
96
|
def apply_to!(document)
|
97
97
|
# Updates modify elements
|
98
|
-
self.update.each
|
99
|
-
|
100
|
-
|
101
|
-
# Tasks can become projects and v.v.: check this.
|
102
|
-
if [Rubyfocus::Task, Rubyfocus::Project].include?(elem.class)
|
103
|
-
should_be_project = (node.at_xpath("xmlns:project") != nil)
|
104
|
-
if (elem.class == Rubyfocus::Project) && !should_be_project
|
105
|
-
elem.document = nil # Remove this from current document
|
106
|
-
elem = elem.to_task # Convert to task
|
107
|
-
elem.document = document # Insert again!
|
108
|
-
elsif (elem.class == Rubyfocus::Task) && should_be_project
|
109
|
-
elem.document = nil # Remove this from current document
|
110
|
-
elem = elem.to_project # Convert to task
|
111
|
-
elem.document = document # Insert again!
|
112
|
-
end
|
113
|
-
end
|
114
|
-
|
115
|
-
elem.apply_xml(node) if elem
|
116
|
-
end
|
117
|
-
|
98
|
+
self.update.each{ |node| update_node(document, node) }
|
99
|
+
|
118
100
|
# Deletes remove elements
|
119
|
-
self.delete.each
|
120
|
-
document.remove_element(node["id"])
|
121
|
-
end
|
101
|
+
self.delete.each{ |node| document.remove_element(node["id"]) }
|
122
102
|
|
123
103
|
# Creates make new elements
|
124
|
-
self.create.each
|
125
|
-
if Rubyfocus::Parser.parse(document, node).nil?
|
126
|
-
raise RuntimeError, "Encountered unparsable XML during patch reading: #{node}."
|
127
|
-
end
|
128
|
-
end
|
104
|
+
self.create.each{ |node| update_node(document, node) }
|
129
105
|
|
130
106
|
# Modify current patch_id to show new value
|
131
107
|
document.patch_id = self.to_id
|
132
108
|
end
|
133
109
|
|
110
|
+
# Atomic node update code
|
111
|
+
def update_node(document, node)
|
112
|
+
# Create new element with correct ID. Then add to document, overwriting previous element(s)
|
113
|
+
new_node = Rubyfocus::Parser.parse(nil, node)
|
114
|
+
if new_node
|
115
|
+
document.add_element(new_node, overwrite: true)
|
116
|
+
else
|
117
|
+
raise(RuntimeError, "Encountered unparsable XML during patch reading: #{node}.")
|
118
|
+
end
|
119
|
+
end
|
120
|
+
|
134
121
|
# String representation
|
135
122
|
def to_s
|
136
123
|
if from_ids.size == 1
|
data/version.txt
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.4.0
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rubyfocus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jan-Yves Ruzicka
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-01-17 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: nokogiri
|