orthor 0.1.4 → 0.2.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.
data/README.md CHANGED
@@ -77,7 +77,7 @@ If you don't want to use the with_orthor_* helpers you can use named templates:
77
77
  </div>)
78
78
  template :blog_entry_brief, %(
79
79
  <div class="blog-entry">
80
- <h2><a href="{{url}}">{{title}}</a></h2>
80
+ <h2><a href="{{orthor_url}}">{{title}}</a></h2>
81
81
  <p>{{published_on}}</p>
82
82
  <div class="blog-content">{{wysiwyg.blurb}}</div>
83
83
  </div>)
@@ -121,7 +121,7 @@ These tags are available to all content:
121
121
  {{author}} - a hash of the original authors details
122
122
  {{updater}} - a hash of the updater details
123
123
  {{published_on}} - the date your content was published
124
- {{url}} - the URL for your content as defined in Orthor, or auto generated as /:template-prefix/category-id/content-id
124
+ {{orthor_url}} - the URL for your content as defined in Orthor, or auto generated as /:template-prefix/category-id/content-id
125
125
  {{template}} - the name of the template this content was created from
126
126
  {{category}} - a hash of this items category details
127
127
 
@@ -13,6 +13,23 @@ class Orthor
13
13
  attr_accessor :cache, :cache_expiry, :site_id
14
14
  end
15
15
 
16
+ def self.content(id, options = {})
17
+ Templates.render(get(:content_items, id), options[:template])
18
+ end
19
+
20
+ def self.query(id, options = {})
21
+ Templates.render(get(:queries, id), options[:template])
22
+ end
23
+
24
+ def self.category(id, options = {})
25
+ id = options[:page] && options[:page].to_i > 1 ? "#{id}-#{options[:page]}" : id
26
+ Templates.render(get(:categories, id), options[:template])
27
+ end
28
+
29
+ def self.feed(id)
30
+ get(:feeds, id)
31
+ end
32
+
16
33
  def self.load_content
17
34
  raise "No point loading content when you don't have a cache setup" unless cache
18
35
 
@@ -31,22 +48,6 @@ class Orthor
31
48
  end
32
49
  end
33
50
 
34
- def self.content(id, template = nil)
35
- Templates.render(get(:content_items, id), template)
36
- end
37
-
38
- def self.query(id, template = nil)
39
- Templates.render(get(:queries, id), template)
40
- end
41
-
42
- def self.category(id, template = nil)
43
- Templates.render(get(:categories, id), template)
44
- end
45
-
46
- def self.feed(id)
47
- get(:feeds, id)
48
- end
49
-
50
51
  def self.render(items, template)
51
52
  Templates.render(items, template)
52
53
  end
@@ -65,7 +66,7 @@ class Orthor
65
66
  end
66
67
 
67
68
  def self.setup(&block)
68
- raise ArgumentError unless block_given?
69
+ raise ArgumentError, "Block required" unless block_given?
69
70
  self.cache = false # default
70
71
 
71
72
  class_eval &block
@@ -77,10 +78,10 @@ private
77
78
 
78
79
  begin
79
80
  suffix = type == :feeds ? "rss" : "json"
80
- key = "#{id}-#{type}"
81
+ cache_key = "#{id}-#{type}"
81
82
  path = "/#{site_id}/#{type}/#{id}.#{suffix}"
82
83
 
83
- resp = cache ? get_cached_content(key, path) : get_response(path)
84
+ resp = cache ? get_cached_content(cache_key, path) : get_response(path)
84
85
 
85
86
  return resp unless suffix == "json"
86
87
 
@@ -119,8 +120,7 @@ private
119
120
  response_content = r.body
120
121
  break
121
122
  end
122
- rescue => e
123
- break
123
+ rescue
124
124
  end
125
125
  end
126
126
  response_content
@@ -37,32 +37,25 @@ class Orthor
37
37
  def self.parse(item, template_name_or_mapping)
38
38
  return "" if item == ""
39
39
 
40
- # ensure we're dealing with an array
41
- unless item.is_a?(Array)
42
- if item["type"] == "category"
43
- item = item["content"]
44
- else
45
- item = [item]
46
- end
47
- end
40
+ content_items = content_items_from(item)
48
41
 
49
- item.collect do |c|
50
- markup = template_for(c, template_name_or_mapping)
42
+ content_items.collect do |content|
43
+ markup = template_for(content, template_name_or_mapping)
51
44
 
52
- c.inject(markup) do |html, (key, val)|
45
+ content.inject(markup) do |html, (key, val)|
53
46
  if val.is_a?(String) && html.include?("{{#{key}.blurb}}")
54
47
  val = "#{val.to_s.gsub(/<\/?[^>]*>/, "")[0..150]}..."
55
48
  key = "#{key}.blurb"
56
49
 
57
50
  html = html.gsub("{{#{key}}}", val.to_s)
58
51
  elsif val.is_a?(Hash) && html.include?("{{#{key}.")
59
- # we've got something like Author.Email
52
+ # we've got something like author.email
60
53
  html = val.inject(html) { |h, (k, v)| h = h.gsub("{{#{key}.#{k}}}", v.to_s) }
61
54
  else
62
55
  html = html.gsub("{{#{key}}}", val.to_s)
63
56
  end
64
57
  end
65
- end.join("")
58
+ end.join("")
66
59
  rescue Orthor::Templates::Unknown => e
67
60
  raise e
68
61
  rescue => e
@@ -89,6 +82,15 @@ class Orthor
89
82
  markup
90
83
  end
91
84
 
92
- private_class_method :parse, :template_for
85
+ def self.content_items_from(item)
86
+ if item.is_a?(Array)
87
+ content_items = item # content queries return an array
88
+ elsif item["type"] == "category"
89
+ content_items = item["content"]
90
+ else
91
+ content_items = [item]
92
+ end
93
+ end
94
+ private_class_method :parse, :template_for, :content_items_from
93
95
  end
94
96
  end
@@ -4,9 +4,9 @@ module OrthorHelper
4
4
  render_orthor_result(:content, id, &blk)
5
5
  end
6
6
 
7
- def with_orthor_category(id, &blk)
7
+ def with_orthor_category(id, page = nil, &blk)
8
8
  return unless block_given?
9
- render_orthor_result(:category, id, &blk)
9
+ render_orthor_result(:category, id, page, &blk)
10
10
  end
11
11
 
12
12
  def with_orthor_query(id, &blk)
@@ -14,12 +14,53 @@ module OrthorHelper
14
14
  render_orthor_result(:query, id, &blk)
15
15
  end
16
16
 
17
+ def orthor_pagination(category_id, options = {})
18
+ return unless defined?(request) && defined?(params)
19
+
20
+ current_page = params[:page] ? params[:page].to_i : 1
21
+ category = Orthor.category(category_id, :page => current_page)
22
+ return if category == "" || category["total_pages"] == 1 # no pagination required
23
+
24
+ options[:prev_label] ||= "&larr;"
25
+ options[:next_label] ||= "&rarr;"
26
+
27
+ if params[:page] && params[:page].to_i > 0
28
+ href = request.url
29
+ else
30
+ href = request.url + (request.url.include?("?") ? "&" : "?") + "page=#{current_page}"
31
+ end
32
+
33
+ previous_link = if current_page > 1
34
+ %!<a class="previous" href="#{href.gsub("page=#{current_page}", "page=#{current_page - 1}")}">#{options[:prev_label]}</a>!
35
+ else
36
+ %!<span class="previous disabled">#{options[:prev_label]}</span>!
37
+ end
38
+ next_link = if current_page < category["total_pages"]
39
+ %!<a class="next" href="#{href.gsub("page=#{current_page}", "page=#{current_page + 1}")}">#{options[:next_label]}</a>!
40
+ else
41
+ %!<span class="next disabled">#{options[:next_label]}</span>!
42
+ end
43
+
44
+ html = <<-HTML
45
+ <div class="orthor-pagination">
46
+ #{previous_link}
47
+ #{next_link}
48
+ </div>
49
+ HTML
50
+
51
+ make_safe(html)
52
+ end
53
+
17
54
  private
18
- def render_orthor_result(method, id, &blk)
55
+ def render_orthor_result(method, id, page = nil, &blk)
19
56
  html = defined?(capture) ? capture(&blk) : yield
20
- parsed_html = Orthor.send(method, id, html)
57
+ parsed_html = make_safe(Orthor.send(method, id, :page => page, :template => html))
21
58
  defined?(concat) ? concat(parsed_html) : parsed_html
22
59
  end
60
+
61
+ def make_safe(html)
62
+ html.respond_to?(:html_safe) ? html.html_safe : html
63
+ end
23
64
  end
24
65
 
25
66
  ActionView::Base.send(:include, OrthorHelper) if defined?(ActionView::Base)
@@ -8,6 +8,8 @@ describe Orthor::Templates 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
+ FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/categories/category-2.json",
12
+ :body => File.join(SPEC_DIR, 'resources', 'category-2.json'))
11
13
  FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/queries/varied.json",
12
14
  :body => File.join(SPEC_DIR, 'resources', 'varied_content.json'))
13
15
  FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/feeds/feed.rss",
@@ -33,7 +35,7 @@ describe Orthor::Templates do
33
35
 
34
36
  describe "utf8" do
35
37
  it "should be able to parse utf8" do
36
- Orthor.content("utf8", :brief).should == "<h2>Q&A with Tobias Lütke of Shopify - (37signals)</h2>"
38
+ Orthor.content("utf8", :template => :brief).should == "<h2>Q&A with Tobias Lütke of Shopify - (37signals)</h2>"
37
39
  end
38
40
  end
39
41
 
@@ -55,22 +57,22 @@ describe Orthor::Templates do
55
57
 
56
58
  describe "nested attributes" do
57
59
  it "should support User.Email, User.First name, User.Last name" do
58
- Orthor.content("content", :user).should == "<div>demo@orthor.com</div><div>Bob Demo</div>"
60
+ Orthor.content("content", :template => :user).should == "<div>demo@orthor.com</div><div>Bob Demo</div>"
59
61
  end
60
62
  end
61
63
 
62
64
  describe "a content item" do
63
65
  it "should display content using the named template" do
64
- Orthor.content("content", :basic).should == %!<h2>What is Orthor</h2><div class="content"><h2>So what is Orthor really??</h2></div>!
66
+ Orthor.content("content", :template => :basic).should == %!<h2>What is Orthor</h2><div class="content"><h2>So what is Orthor really??</h2></div>!
65
67
  end
66
68
 
67
69
  it "should respect given template name" do
68
- Orthor.content("content", :brief).should == %!<h2>What is Orthor</h2>!
70
+ Orthor.content("content", :template => :brief).should == %!<h2>What is Orthor</h2>!
69
71
  end
70
72
 
71
73
  describe "blurb" do
72
74
  it "should truncate some of the text, strip html and add ..." do
73
- Orthor.content("content", :blurb).should == "<div>So what is Orthor really??...</div>"
75
+ Orthor.content("content", :template => :blurb).should == "<div>So what is Orthor really??...</div>"
74
76
  end
75
77
  end
76
78
  end
@@ -83,13 +85,13 @@ describe Orthor::Templates do
83
85
 
84
86
  describe "a content query" do
85
87
  it "should render the template for each item" do
86
- Orthor.query("query", :brief).should == %!<h2>User Manual updated</h2><h2>Account event tracking</h2><h2>Tutorials have been updated</h2>!
88
+ Orthor.query("query", :template => :brief).should == %!<h2>User Manual updated</h2><h2>Account event tracking</h2><h2>Tutorials have been updated</h2>!
87
89
  end
88
90
  end
89
91
 
90
92
  describe "a category" do
91
93
  it "should render the template for each item" do
92
- Orthor.category("category", :brief).should == %!<h2>User Manual updated</h2><h2>Account event tracking</h2><h2>Tutorials have been updated</h2><h2>Content Queries have landed in Orthor</h2>!
94
+ Orthor.category("category", :template => :brief).should == %!<h2>User Manual updated</h2><h2>Account event tracking</h2><h2>Tutorials have been updated</h2><h2>Content Queries have landed in Orthor</h2>!
93
95
  end
94
96
  end
95
97
 
@@ -109,7 +111,7 @@ describe Orthor::Templates do
109
111
 
110
112
  describe "with a non-existant template" do
111
113
  it "should raise an error" do
112
- lambda { Orthor.category("category", :blah) }.should raise_error(Orthor::Templates::Unknown)
114
+ lambda { Orthor.category("category", :template => :blah) }.should raise_error(Orthor::Templates::Unknown)
113
115
  end
114
116
  end
115
117
 
@@ -124,7 +126,7 @@ describe Orthor::Templates do
124
126
 
125
127
  describe "with a named map" do
126
128
  it "should find the template from the map" do
127
- Orthor.content("content", :listing).should == "<h2>What is Orthor</h2>"
129
+ Orthor.content("content", :template => :listing).should == "<h2>What is Orthor</h2>"
128
130
  end
129
131
  end
130
132
 
@@ -8,6 +8,8 @@ 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
+ FakeWeb.register_uri(:get, "http://content.orthor.com/orthor/categories/category-2.json",
12
+ :body => File.join(SPEC_DIR, 'resources', 'category-2.json'))
11
13
 
12
14
  # account and cache loading resources
13
15
  [ "top-level", "second-level" ].each do |name|
@@ -84,6 +86,14 @@ describe Orthor do
84
86
  it 'should be able to fetch categories' do
85
87
  Orthor.category("category").to_s.should include("The User Manual has recently had a big overhaul")
86
88
  end
89
+
90
+ describe "category pages" do
91
+ it "should support optional page argument" do
92
+ Orthor.category("category", :page => 2)["content"].length.should == 1
93
+ Orthor.category("category", :page => 1)["content"].length.should == 4
94
+ Orthor.category("category", :page => nil)["content"].length.should == 4
95
+ end
96
+ end
87
97
  end
88
98
 
89
99
  describe "loading cache" do
@@ -191,6 +201,7 @@ describe Orthor do
191
201
  it "should use www.orthor.com if content.orthor.com is down" do
192
202
  # initial request will go to content.orthor.com and return an empty string
193
203
  Orthor.content("missing").should_not == ""
204
+ Orthor.content("missing")["title"].should == "What is Orthor"
194
205
  end
195
206
  end
196
207
  end
@@ -1,6 +1,7 @@
1
1
  require 'rubygems'
2
2
  require 'spec'
3
3
  require 'fake_web'
4
+ require 'rr'
4
5
  require File.join(File.dirname(__FILE__), '..', 'lib', 'orthor')
5
6
 
6
7
  SPEC_DIR = File.dirname(__FILE__) unless defined? SPEC_DIR
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: orthor
3
3
  version: !ruby/object:Gem::Version
4
- hash: 19
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
- - 4
10
- version: 0.1.4
8
+ - 2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Anthony Langhorne
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-06-10 00:00:00 +10:00
18
+ date: 2011-03-20 00:00:00 +11:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency