orthor 0.1.1 → 0.1.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +20 -20
- data/lib/orthor.rb +49 -14
- data/spec/orthor_spec.rb +54 -0
- metadata +2 -2
data/README.md
CHANGED
@@ -44,25 +44,25 @@ If you do not provide a template_name to render your content with, you will get
|
|
44
44
|
Orthor returns all of your content in JSON so to make the job of translating JSON -> HTML easier, we provide some templating help:
|
45
45
|
|
46
46
|
Orthor::Templates.define do
|
47
|
-
template :basic_content, %(<div>{{
|
47
|
+
template :basic_content, %(<div>{{content}}</div>)
|
48
48
|
|
49
49
|
template :blog_entry, %(
|
50
50
|
<div class="blog-entry">
|
51
|
-
<h2>{{
|
52
|
-
<div class="blog-content">{{
|
51
|
+
<h2>{{title}}</h2>
|
52
|
+
<div class="blog-content">{{wysiwyg}}</div>
|
53
53
|
</div>)
|
54
54
|
template :blog_entry_brief, %(
|
55
55
|
<div class="blog-entry">
|
56
|
-
<h2><a href="{{
|
57
|
-
<p>{{
|
58
|
-
<div class="blog-content">{{
|
56
|
+
<h2><a href="{{url}}">{{title}}</a></h2>
|
57
|
+
<p>{{published_on}}</p>
|
58
|
+
<div class="blog-content">{{wysiwyg.blurb}}</div>
|
59
59
|
</div>)
|
60
60
|
|
61
61
|
template :user_manual, %(
|
62
62
|
<div class="user-manual-entry">
|
63
|
-
<h2>{{
|
64
|
-
<p class="last-updated">Last updated: {{
|
65
|
-
<div class="content">{{
|
63
|
+
<h2>{{title}}</h2>
|
64
|
+
<p class="last-updated">Last updated: {{updated_on}}</p>
|
65
|
+
<div class="content">{{wysiwyg}}</div>
|
66
66
|
</div>)
|
67
67
|
|
68
68
|
mapping :detail_templates, {
|
@@ -91,22 +91,22 @@ A call to Orthor.category("blog", :blog_types) means that any content item using
|
|
91
91
|
These tags are available to all content:
|
92
92
|
|
93
93
|
{{id}} - the orthor id of your content item
|
94
|
-
{{
|
95
|
-
{{
|
96
|
-
{{
|
97
|
-
{{
|
98
|
-
{{
|
99
|
-
{{
|
100
|
-
{{
|
94
|
+
{{title}} - your content title
|
95
|
+
{{created_on}} - the date your content was created
|
96
|
+
{{updated_on}} - the date your content was last updated
|
97
|
+
{{author}} - a hash of the original authors details
|
98
|
+
{{updater}} - a hash of the updater details
|
99
|
+
{{published_on}} - the date your content was published
|
100
|
+
{{url}} - the URL for your content as defined in Orthor, or auto generated as /:template-prefix/category-id/content-id
|
101
101
|
{{template}} - the name of the template this content was created from
|
102
102
|
{{category}} - a hash of this items category details
|
103
103
|
|
104
104
|
Other attributes that will be present on a per item specific basis are are the names of your template elements, e.g.
|
105
105
|
|
106
|
-
{{
|
107
|
-
{{Featured News Item
|
108
|
-
{{Supporting Image
|
109
|
-
{{Markdown
|
106
|
+
{{content}} # Template field name in Orthor: Content
|
107
|
+
{{featured_news_item}} # Template field name in Orthor: Featured News Item
|
108
|
+
{{supporting_image}} # Template field name in Orthor: Supporting Image
|
109
|
+
{{markdown_body}} # Template field name in Orthor: Markdown Body
|
110
110
|
|
111
111
|
## Questions? Comments?
|
112
112
|
|
data/lib/orthor.rb
CHANGED
@@ -3,6 +3,7 @@ $KCODE = 'u' if RUBY_VERSION < '1.9'
|
|
3
3
|
|
4
4
|
require 'moneta'
|
5
5
|
require 'json'
|
6
|
+
require 'net/http'
|
6
7
|
|
7
8
|
require 'orthor/templates'
|
8
9
|
|
@@ -11,6 +12,24 @@ class Orthor
|
|
11
12
|
attr_accessor :cache, :cache_expiry, :account_id
|
12
13
|
end
|
13
14
|
|
15
|
+
def self.load_content
|
16
|
+
raise "No point loading content when you don't have a cache setup" unless cache
|
17
|
+
|
18
|
+
load_category = lambda do |id|
|
19
|
+
cat = category(id)
|
20
|
+
cat["children"].each { |child| load_category[child["id"]] } if cat["children"]
|
21
|
+
cat["content"].each { |item| content(item["id"]) } if cat["content"]
|
22
|
+
end
|
23
|
+
|
24
|
+
JSON.parse(get_response("/#{account_id}.json")).each do |item|
|
25
|
+
if item["type"] == "category"
|
26
|
+
load_category[item["id"]]
|
27
|
+
else
|
28
|
+
content(item["id"])
|
29
|
+
end
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
14
33
|
def self.content(id, template = nil)
|
15
34
|
Templates.render(get(:content_items, id), template)
|
16
35
|
end
|
@@ -58,9 +77,9 @@ private
|
|
58
77
|
begin
|
59
78
|
suffix = type == :feeds ? "rss" : "json"
|
60
79
|
key = "#{id}-#{type}"
|
61
|
-
|
80
|
+
path = "/#{account_id}/#{type}/#{id}.#{suffix}"
|
62
81
|
|
63
|
-
resp = cache ? get_cached_content(key,
|
82
|
+
resp = cache ? get_cached_content(key, path) : get_response(path)
|
64
83
|
|
65
84
|
return resp unless suffix == "json"
|
66
85
|
|
@@ -70,24 +89,40 @@ private
|
|
70
89
|
end
|
71
90
|
end
|
72
91
|
|
73
|
-
def self.get_cached_content(
|
74
|
-
content = cache[
|
92
|
+
def self.get_cached_content(key, path)
|
93
|
+
content = cache[key]
|
75
94
|
if content.nil? || content.empty?
|
76
|
-
content = get_response(
|
77
|
-
|
78
|
-
options = {}
|
79
|
-
options[:expires_in] = cache_expiry if cache_expiry
|
80
|
-
cache.store(id, content, options) unless content.empty?
|
95
|
+
content = get_response(path)
|
96
|
+
cache_content(key, content)
|
81
97
|
end
|
82
98
|
content
|
83
99
|
end
|
84
100
|
|
85
|
-
def self.
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
101
|
+
def self.cache_content(key, content)
|
102
|
+
return if content.empty?
|
103
|
+
|
104
|
+
options = {}
|
105
|
+
options[:expires_in] = cache_expiry if cache_expiry
|
106
|
+
cache.store(key, content, options)
|
90
107
|
end
|
91
108
|
|
109
|
+
def self.get_response(path)
|
110
|
+
# default to content.orthor.com, if thats down, try www.orthor.com
|
111
|
+
uris = [ "http://content.orthor.com#{path}", "http://www.orthor.com#{path}" ]
|
112
|
+
response_content = ""
|
113
|
+
|
114
|
+
uris.each do |uri|
|
115
|
+
begin
|
116
|
+
r = Net::HTTP.get_response(URI.parse(uri))
|
117
|
+
if r.code.to_i == 200
|
118
|
+
response_content = r.body
|
119
|
+
break
|
120
|
+
end
|
121
|
+
rescue => e
|
122
|
+
break
|
123
|
+
end
|
124
|
+
end
|
125
|
+
response_content
|
126
|
+
end
|
92
127
|
private_class_method :get, :get_cached_content, :get_response
|
93
128
|
end
|
data/spec/orthor_spec.rb
CHANGED
@@ -8,8 +8,22 @@ describe Orthor do
|
|
8
8
|
:body => File.join(SPEC_DIR, 'resources', 'query.json'))
|
9
9
|
FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/categories/category.json",
|
10
10
|
:body => File.join(SPEC_DIR, 'resources', 'category.json'))
|
11
|
+
|
12
|
+
# account and cache loading resources
|
13
|
+
[ "top-level", "second-level" ].each do |name|
|
14
|
+
FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/categories/#{name}.json",
|
15
|
+
:body => File.join(SPEC_DIR, 'resources', "#{name}.json"))
|
16
|
+
end
|
17
|
+
|
11
18
|
FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/feeds/feed.rss",
|
12
19
|
:body => File.join(SPEC_DIR, 'resources', 'feed.rss'))
|
20
|
+
FakeWeb.register_uri(:get, "http://content.orthor.com/orthor.json",
|
21
|
+
:body => File.join(SPEC_DIR, 'resources', 'account.json'))
|
22
|
+
|
23
|
+
FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/content_items/missing.json",
|
24
|
+
:body => "", :status => 500)
|
25
|
+
FakeWeb.register_uri(:get, "http://www.orthor.com/orthor/content_items/missing.json",
|
26
|
+
:body => File.join(SPEC_DIR, 'resources', 'content.json'))
|
13
27
|
end
|
14
28
|
|
15
29
|
describe "setup" do
|
@@ -60,6 +74,33 @@ describe Orthor do
|
|
60
74
|
end
|
61
75
|
end
|
62
76
|
|
77
|
+
describe "loading cache" do
|
78
|
+
describe "without cache setting" do
|
79
|
+
before do
|
80
|
+
Orthor.setup { account "orthor" }
|
81
|
+
end
|
82
|
+
|
83
|
+
it "should raise an error" do
|
84
|
+
lambda { Orthor.load_content }.should raise_error
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
describe "with cache setting" do
|
89
|
+
before do
|
90
|
+
Orthor.setup do
|
91
|
+
account "orthor"
|
92
|
+
caching :memory, 20
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
it "should load all items into the cache" do
|
97
|
+
Orthor.load_content
|
98
|
+
Orthor.cache["news-categories"].should_not be_nil
|
99
|
+
Orthor.cache["content-content_items"].should_not be_nil
|
100
|
+
end
|
101
|
+
end
|
102
|
+
end
|
103
|
+
|
63
104
|
describe "caching" do
|
64
105
|
describe "no config" do
|
65
106
|
before(:all) do
|
@@ -127,4 +168,17 @@ describe Orthor do
|
|
127
168
|
end
|
128
169
|
end
|
129
170
|
end
|
171
|
+
|
172
|
+
describe "failover" do
|
173
|
+
before(:all) do
|
174
|
+
Orthor.setup do
|
175
|
+
account "orthor"
|
176
|
+
end
|
177
|
+
end
|
178
|
+
|
179
|
+
it "should use www.orthor.com if content.orthor.com is down" do
|
180
|
+
# initial request will go to content.orthor.com and return an empty string
|
181
|
+
Orthor.content("missing").should_not == ""
|
182
|
+
end
|
183
|
+
end
|
130
184
|
end
|