gdata_spreadsheet 0.1.0 → 0.1.1
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.
- data/README.rdoc +93 -1
- data/VERSION +1 -1
- data/gdata_spreadsheet.gemspec +2 -2
- data/lib/google/base.rb +65 -21
- data/lib/google/config.rb +14 -0
- data/lib/google/log.rb +11 -0
- data/lib/google/spreadsheet.rb +3 -0
- metadata +4 -4
data/README.rdoc
CHANGED
@@ -1,9 +1,101 @@
|
|
1
1
|
= GData Spreadsheet
|
2
2
|
|
3
|
+
Use the GData API the way its meant to be: OO-style!
|
4
|
+
|
5
|
+
|
6
|
+
== Installation
|
7
|
+
|
8
|
+
gem install gdata_spreadsheet
|
9
|
+
|
10
|
+
|
11
|
+
== Setup
|
12
|
+
|
13
|
+
You have to initialise the connection by setting up the config:
|
14
|
+
|
15
|
+
Google::Config.file = File.join(File.dirname(__FILE__), "google.yml")
|
16
|
+
|
17
|
+
The config file itself looks like this:
|
18
|
+
|
19
|
+
account: account@google.com
|
20
|
+
worksheet_token: session_token_for_worksheets
|
21
|
+
list_token: session_token_for_lists
|
22
|
+
|
23
|
+
Don't know how to get session tokens? Check this out: http://blog.tricycledevelopments.com/2010/08/19/gdata-authsub.html
|
24
|
+
|
25
|
+
|
26
|
+
== Usage
|
27
|
+
|
28
|
+
Just create a subclass of the <tt>Google::Base</tt> class and overwrite <tt>worksheet_name, id_column and sync_attributes</tt>.
|
29
|
+
A very simple example is the <tt>Log</tt> class, which can be used to write messages to a spreadsheet.
|
30
|
+
A more advanced example would be this:
|
31
|
+
|
32
|
+
module Google
|
33
|
+
class Order < Google::Base
|
34
|
+
attr_reader :line_items
|
35
|
+
|
36
|
+
def initialize(doc_id, id = nil, items = [])
|
37
|
+
super doc_id, id
|
38
|
+
|
39
|
+
@line_items = items
|
40
|
+
end
|
41
|
+
|
42
|
+
def id_column
|
43
|
+
"ordernumber"
|
44
|
+
end
|
45
|
+
|
46
|
+
def worksheet_name
|
47
|
+
"orders"
|
48
|
+
end
|
49
|
+
|
50
|
+
def sync_attributes
|
51
|
+
{
|
52
|
+
:timestamp => Time.now.strftime("%d/%m/%Y %H:%M"),
|
53
|
+
:ordernumber => 123,
|
54
|
+
...
|
55
|
+
:lineitems => line_items,
|
56
|
+
...
|
57
|
+
}
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
== Finding / updating existing records
|
64
|
+
|
65
|
+
The second parameter for the <tt>Base</tt> initialiser takes an ID. If an ID value is provided (and the <tt>id_column</tt> is specified),
|
66
|
+
then the matching row will be fetched from the spreadsheet while mapping all existing attributes (see 'How do attributes map?' for more information).
|
67
|
+
|
68
|
+
order = Google::Order.new("spreadsheet_id", "1234")
|
69
|
+
|
70
|
+
The record can then be written to the spreadsheet by calling <tt>save</tt>. If <tt>sync!</tt> is executed,
|
71
|
+
the attributes will be updated according to the mapping specified in <tt>sync_attributes</tt>.
|
72
|
+
|
73
|
+
order.save
|
74
|
+
|
75
|
+
|
76
|
+
== Creating new records
|
77
|
+
|
78
|
+
Just instantiate your model without an ID. <tt>sync!</tt> will take care of pushing the data to the spreadsheet.
|
79
|
+
|
80
|
+
order = Google::Order.new("spreadsheet_id")
|
81
|
+
order.sync!
|
82
|
+
|
83
|
+
|
84
|
+
== How do attributes map?
|
85
|
+
|
86
|
+
All attributes can then be accessed using the regular getters and setters:
|
87
|
+
|
88
|
+
order = Google::Order.new("spreadsheet_id")
|
89
|
+
order.ordernumber = "4321"
|
90
|
+
order.ordernumber # => "4321"
|
91
|
+
|
92
|
+
Google uses a shortened version of the column headers and strips all characters except for <tt>[a-z0-9]</tt>.
|
93
|
+
So when your column header in the spreadsheet reads 'Order Number', the mapped attribute in your code will be 'ordernumber'.
|
94
|
+
Make sure to call the correct methods!
|
3
95
|
|
4
96
|
|
5
97
|
== Note on Patches/Pull Requests
|
6
|
-
|
98
|
+
|
7
99
|
* Fork the project.
|
8
100
|
* Make your feature addition or bug fix.
|
9
101
|
* Add tests for it. This is important so I don't break it in a
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.1
|
data/gdata_spreadsheet.gemspec
CHANGED
@@ -5,11 +5,11 @@
|
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{gdata_spreadsheet}
|
8
|
-
s.version = "0.1.
|
8
|
+
s.version = "0.1.1"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["Tom"]
|
12
|
-
s.date = %q{2010-
|
12
|
+
s.date = %q{2010-09-01}
|
13
13
|
s.description = %q{}
|
14
14
|
s.email = %q{tom@trike.com.au}
|
15
15
|
s.extra_rdoc_files = [
|
data/lib/google/base.rb
CHANGED
@@ -1,7 +1,26 @@
|
|
1
1
|
module Google
|
2
|
+
|
3
|
+
# Base class for all your spreadsheet models.
|
4
|
+
# Check the Readme for detailed information on how it's used.
|
5
|
+
#
|
6
|
+
# === Finding / updating existing records
|
7
|
+
#
|
8
|
+
# order = Google::Order.new("spreadsheet_id", "1234")
|
9
|
+
# order.save
|
10
|
+
#
|
11
|
+
# === Creating new records
|
12
|
+
#
|
13
|
+
# order = Google::Order.new("spreadsheet_id")
|
14
|
+
# order.sync!
|
2
15
|
class Base
|
3
16
|
attr_reader :doc
|
4
17
|
|
18
|
+
# The standard initialiser takes the spreadsheet ID and an optional record ID
|
19
|
+
# (check the Readme to see how records are mapped). Overwrite the initialiser
|
20
|
+
# in order to pass in other necessary information (eg. as in Log).
|
21
|
+
#
|
22
|
+
# If a record ID is specified, then the associated row from the spreadsheet will be fetched,
|
23
|
+
# otherwise a new record is build.
|
5
24
|
def initialize(doc_id, row_id = nil)
|
6
25
|
raise Google::MissingDocumentError unless doc_id
|
7
26
|
|
@@ -11,26 +30,7 @@ module Google
|
|
11
30
|
initialize_row row_id
|
12
31
|
end
|
13
32
|
|
14
|
-
|
15
|
-
if id_column && id && @doc = @sheet.row_data(id_column, id.downcase, @worksheet_id)
|
16
|
-
initialize_doc
|
17
|
-
else
|
18
|
-
new_row
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
def new_row
|
23
|
-
@doc = Nokogiri::XML.parse("<entry xmlns=\"http://www.w3.org/2005/Atom\"></entry>").css("entry").first
|
24
|
-
@doc.add_namespace_definition "gsx", "http://schemas.google.com/spreadsheets/2006/extended"
|
25
|
-
@doc.add_namespace_definition "gd", "http://schemas.google.com/g/2005"
|
26
|
-
end
|
27
|
-
|
28
|
-
def initialize_doc
|
29
|
-
@doc["xmlns"] = "http://www.w3.org/2005/Atom"
|
30
|
-
@doc["xmlns:gsx"] = "http://schemas.google.com/spreadsheets/2006/extended"
|
31
|
-
@doc["xmlns:gd"] = "http://schemas.google.com/g/2005"
|
32
|
-
end
|
33
|
-
|
33
|
+
# Creates or updates the record.
|
34
34
|
def save
|
35
35
|
if new_record?
|
36
36
|
@sheet.add_row @doc, @worksheet_id
|
@@ -39,34 +39,58 @@ module Google
|
|
39
39
|
end
|
40
40
|
end
|
41
41
|
|
42
|
+
# Returns true if the record is not yet pushed to the spreadsheet.
|
42
43
|
def new_record?
|
43
44
|
!@doc.css("id").first
|
44
45
|
end
|
45
46
|
|
47
|
+
# Name of the worksheet that's mapped to the model.
|
48
|
+
#
|
49
|
+
# Overwrite this in your sub-class!
|
46
50
|
def worksheet_name
|
47
51
|
raise "Abstract! Overwrite this method in your subclass"
|
48
52
|
end
|
49
53
|
|
54
|
+
# Name of the column that'll will be used as the ID column.
|
55
|
+
#
|
56
|
+
# Overwrite this in your sub-class!
|
57
|
+
#
|
58
|
+
# <tt>return nil</tt> in your subclass, if you want a push only model
|
50
59
|
def id_column
|
51
60
|
raise "Abstract! Overwrite this method in your subclass"
|
52
|
-
# return nil in your subclass, if you want a push only model
|
53
61
|
end
|
54
62
|
|
63
|
+
# specify how attributes are mapped to the spreadsheet.
|
64
|
+
#
|
65
|
+
# ==== Example
|
66
|
+
# {
|
67
|
+
# :timestamp => Time.now.to_s(:db),
|
68
|
+
# :message => @message
|
69
|
+
# }
|
70
|
+
#
|
71
|
+
# The keys in the hash represent columns in the spreadsheet
|
72
|
+
# (check out the Readme, for more information about attribute mapping), the values will
|
73
|
+
# be written to the cells.
|
55
74
|
def sync_attributes
|
56
75
|
{ }
|
57
76
|
end
|
58
77
|
|
78
|
+
# Maps all attributes specified in Base#sync_attributes, so that a subsequent Base#save
|
79
|
+
# will push the data to the spreadsheet columns.
|
59
80
|
def sync
|
60
81
|
sync_attributes.each do |field, value|
|
61
82
|
set field, value
|
62
83
|
end
|
63
84
|
end
|
64
85
|
|
86
|
+
# Convenience method with executes Base#sync and then Base#save.
|
65
87
|
def sync!
|
66
88
|
sync
|
67
89
|
save
|
68
90
|
end
|
69
91
|
|
92
|
+
protected
|
93
|
+
|
70
94
|
def method_missing(method, *args, &block)
|
71
95
|
method = method.to_s
|
72
96
|
|
@@ -81,6 +105,26 @@ module Google
|
|
81
105
|
|
82
106
|
private
|
83
107
|
|
108
|
+
def initialize_row(id)
|
109
|
+
if id_column && id && @doc = @sheet.row_data(id_column, id.downcase, @worksheet_id)
|
110
|
+
initialize_doc
|
111
|
+
else
|
112
|
+
new_row
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
def new_row
|
117
|
+
@doc = Nokogiri::XML.parse("<entry xmlns=\"http://www.w3.org/2005/Atom\"></entry>").css("entry").first
|
118
|
+
@doc.add_namespace_definition "gsx", "http://schemas.google.com/spreadsheets/2006/extended"
|
119
|
+
@doc.add_namespace_definition "gd", "http://schemas.google.com/g/2005"
|
120
|
+
end
|
121
|
+
|
122
|
+
def initialize_doc
|
123
|
+
@doc["xmlns"] = "http://www.w3.org/2005/Atom"
|
124
|
+
@doc["xmlns:gsx"] = "http://schemas.google.com/spreadsheets/2006/extended"
|
125
|
+
@doc["xmlns:gd"] = "http://schemas.google.com/g/2005"
|
126
|
+
end
|
127
|
+
|
84
128
|
def attribute(field)
|
85
129
|
@doc.xpath(".//gsx:#{field}").first
|
86
130
|
end
|
data/lib/google/config.rb
CHANGED
@@ -1,6 +1,20 @@
|
|
1
1
|
require 'yaml'
|
2
2
|
|
3
3
|
module Google
|
4
|
+
|
5
|
+
# Wrapper to access settings.
|
6
|
+
# Unless you specify additional settings in your config file,
|
7
|
+
# you should never have to call settings on your own!
|
8
|
+
#
|
9
|
+
# === Initialisation
|
10
|
+
#
|
11
|
+
# Google::Config.file = File.join(File.dirname(__FILE__), "google.yml")
|
12
|
+
#
|
13
|
+
# === Example
|
14
|
+
#
|
15
|
+
# account: account@google.com
|
16
|
+
# worksheet_token: session_token_for_worksheets
|
17
|
+
# list_token: session_token_for_lists
|
4
18
|
class Config
|
5
19
|
def self.file=(path)
|
6
20
|
@@file = path
|
data/lib/google/log.rb
CHANGED
@@ -1,4 +1,13 @@
|
|
1
1
|
module Google
|
2
|
+
|
3
|
+
# Example spreadsheet model.
|
4
|
+
#
|
5
|
+
# This enables very basic message pushing to a spreadsheet named 'sync log'
|
6
|
+
#
|
7
|
+
# === Usage
|
8
|
+
#
|
9
|
+
# entry = Google::Log.new("spreadsheet_id", "awesome stuff!")
|
10
|
+
# entry.sync!
|
2
11
|
class Log < Base
|
3
12
|
|
4
13
|
def initialize(doc_id, message)
|
@@ -7,6 +16,8 @@ module Google
|
|
7
16
|
@message = message
|
8
17
|
end
|
9
18
|
|
19
|
+
private
|
20
|
+
|
10
21
|
def worksheet_name
|
11
22
|
"sync log"
|
12
23
|
end
|
data/lib/google/spreadsheet.rb
CHANGED
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: gdata_spreadsheet
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 25
|
5
5
|
prerelease: false
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 1
|
9
|
-
-
|
10
|
-
version: 0.1.
|
9
|
+
- 1
|
10
|
+
version: 0.1.1
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Tom
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-
|
18
|
+
date: 2010-09-01 00:00:00 +10:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|