orthor 0.1.1 → 0.1.2

Sign up to get free protection for your applications and to get access to all the features.
Files changed (4) hide show
  1. data/README.md +20 -20
  2. data/lib/orthor.rb +49 -14
  3. data/spec/orthor_spec.rb +54 -0
  4. 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>{{Content}}</div>)
47
+ template :basic_content, %(<div>{{content}}</div>)
48
48
 
49
49
  template :blog_entry, %(
50
50
  <div class="blog-entry">
51
- <h2>{{Title}}</h2>
52
- <div class="blog-content">{{Wysiwyg}}</div>
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="{{URL}}">{{Title}}</a></h2>
57
- <p>{{Published on}}</p>
58
- <div class="blog-content">{{Wysiwyg.blurb}}</div>
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>{{Title}}</h2>
64
- <p class="last-updated">Last updated: {{Updated on}}</p>
65
- <div class="content">{{Wysiwyg}}</div>
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
- {{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
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
- {{Content}}
107
- {{Featured News Item}}
108
- {{Supporting Image}}
109
- {{Markdown body}}
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
 
@@ -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
- url = "http://content.orthor.com/#{account_id}/#{type}/#{id}.#{suffix}"
80
+ path = "/#{account_id}/#{type}/#{id}.#{suffix}"
62
81
 
63
- resp = cache ? get_cached_content(key, url) : get_response(url)
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(id, url)
74
- content = cache[id]
92
+ def self.get_cached_content(key, path)
93
+ content = cache[key]
75
94
  if content.nil? || content.empty?
76
- content = get_response(url)
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.get_response(uri)
86
- r = Net::HTTP.get_response(URI.parse(uri))
87
- r.code.to_i == 200 ? r.body : ""
88
- rescue => e
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
@@ -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
metadata CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
5
5
  segments:
6
6
  - 0
7
7
  - 1
8
- - 1
9
- version: 0.1.1
8
+ - 2
9
+ version: 0.1.2
10
10
  platform: ruby
11
11
  authors:
12
12
  - Anthony Langhorne