archive_tree 1.0.0.rc3 → 1.0.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/Gemfile +19 -0
- data/Gemfile.lock +109 -0
- data/README.md +19 -5
- data/Rakefile +38 -0
- data/lib/archive_tree.rb +1 -3
- data/lib/archive_tree/action_view_extensions.rb +67 -2
- data/spec/db/models.rb +3 -0
- data/spec/db/schema.rb +14 -0
- data/spec/factories/posts_factory.rb +6 -0
- data/spec/lib/action_view_extensions/action_view_extensions_spec.rb +76 -0
- data/spec/lib/archive_node_spec.rb +38 -0
- data/spec/lib/archive_tree_core_spec.rb +14 -0
- data/spec/lib/archive_tree_spec.rb +98 -0
- data/spec/lib/archived_months_spec.rb +49 -0
- data/spec/lib/archived_years_spec.rb +27 -0
- data/spec/spec_helper.rb +69 -0
- metadata +91 -15
- data/lib/archive_tree/action_view_extensions/draw_archive_tree.rb +0 -76
data/Gemfile
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
source 'http://rubygems.org'
|
2
|
+
|
3
|
+
gem 'activerecord', '~> 3.0.1'
|
4
|
+
gem 'actionpack', '~> 3.0.1'
|
5
|
+
|
6
|
+
group :development, :test do
|
7
|
+
gem 'mysql', '~> 2.8.0'
|
8
|
+
|
9
|
+
if RUBY_VERSION =~ /1\.9\.\d/
|
10
|
+
gem('ruby-debug-base19', '=0.11.23') if RUBY_VERSION == '1.9.1'
|
11
|
+
gem 'ruby-debug19', '~> 0.11.0'
|
12
|
+
else
|
13
|
+
gem 'ruby-debug'
|
14
|
+
end
|
15
|
+
|
16
|
+
gem 'rspec', '~> 2.0.0'
|
17
|
+
gem 'factory_girl_rails', '~> 1.0.0'
|
18
|
+
gem 'database_cleaner', '~> 0.6.0'
|
19
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,109 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
abstract (1.0.0)
|
5
|
+
actionmailer (3.0.1)
|
6
|
+
actionpack (= 3.0.1)
|
7
|
+
mail (~> 2.2.5)
|
8
|
+
actionpack (3.0.1)
|
9
|
+
activemodel (= 3.0.1)
|
10
|
+
activesupport (= 3.0.1)
|
11
|
+
builder (~> 2.1.2)
|
12
|
+
erubis (~> 2.6.6)
|
13
|
+
i18n (~> 0.4.1)
|
14
|
+
rack (~> 1.2.1)
|
15
|
+
rack-mount (~> 0.6.12)
|
16
|
+
rack-test (~> 0.5.4)
|
17
|
+
tzinfo (~> 0.3.23)
|
18
|
+
activemodel (3.0.1)
|
19
|
+
activesupport (= 3.0.1)
|
20
|
+
builder (~> 2.1.2)
|
21
|
+
i18n (~> 0.4.1)
|
22
|
+
activerecord (3.0.1)
|
23
|
+
activemodel (= 3.0.1)
|
24
|
+
activesupport (= 3.0.1)
|
25
|
+
arel (~> 1.0.0)
|
26
|
+
tzinfo (~> 0.3.23)
|
27
|
+
activeresource (3.0.1)
|
28
|
+
activemodel (= 3.0.1)
|
29
|
+
activesupport (= 3.0.1)
|
30
|
+
activesupport (3.0.1)
|
31
|
+
archive-tar-minitar (0.5.2)
|
32
|
+
arel (1.0.1)
|
33
|
+
activesupport (~> 3.0.0)
|
34
|
+
builder (2.1.2)
|
35
|
+
columnize (0.3.2)
|
36
|
+
database_cleaner (0.6.0)
|
37
|
+
diff-lcs (1.1.2)
|
38
|
+
erubis (2.6.6)
|
39
|
+
abstract (>= 1.0.0)
|
40
|
+
factory_girl (1.3.2)
|
41
|
+
factory_girl_rails (1.0)
|
42
|
+
factory_girl (~> 1.3)
|
43
|
+
rails (>= 3.0.0.beta4)
|
44
|
+
i18n (0.4.2)
|
45
|
+
linecache19 (0.5.11)
|
46
|
+
ruby_core_source (>= 0.1.4)
|
47
|
+
mail (2.2.9)
|
48
|
+
activesupport (>= 2.3.6)
|
49
|
+
i18n (~> 0.4.1)
|
50
|
+
mime-types (~> 1.16)
|
51
|
+
treetop (~> 1.4.8)
|
52
|
+
mime-types (1.16)
|
53
|
+
mysql (2.8.1)
|
54
|
+
polyglot (0.3.1)
|
55
|
+
rack (1.2.1)
|
56
|
+
rack-mount (0.6.13)
|
57
|
+
rack (>= 1.0.0)
|
58
|
+
rack-test (0.5.6)
|
59
|
+
rack (>= 1.0)
|
60
|
+
rails (3.0.1)
|
61
|
+
actionmailer (= 3.0.1)
|
62
|
+
actionpack (= 3.0.1)
|
63
|
+
activerecord (= 3.0.1)
|
64
|
+
activeresource (= 3.0.1)
|
65
|
+
activesupport (= 3.0.1)
|
66
|
+
bundler (~> 1.0.0)
|
67
|
+
railties (= 3.0.1)
|
68
|
+
railties (3.0.1)
|
69
|
+
actionpack (= 3.0.1)
|
70
|
+
activesupport (= 3.0.1)
|
71
|
+
rake (>= 0.8.4)
|
72
|
+
thor (~> 0.14.0)
|
73
|
+
rake (0.8.7)
|
74
|
+
rspec (2.0.1)
|
75
|
+
rspec-core (~> 2.0.1)
|
76
|
+
rspec-expectations (~> 2.0.1)
|
77
|
+
rspec-mocks (~> 2.0.1)
|
78
|
+
rspec-core (2.0.1)
|
79
|
+
rspec-expectations (2.0.1)
|
80
|
+
diff-lcs (>= 1.1.2)
|
81
|
+
rspec-mocks (2.0.1)
|
82
|
+
rspec-core (~> 2.0.1)
|
83
|
+
rspec-expectations (~> 2.0.1)
|
84
|
+
ruby-debug-base19 (0.11.24)
|
85
|
+
columnize (>= 0.3.1)
|
86
|
+
linecache19 (>= 0.5.11)
|
87
|
+
ruby_core_source (>= 0.1.4)
|
88
|
+
ruby-debug19 (0.11.6)
|
89
|
+
columnize (>= 0.3.1)
|
90
|
+
linecache19 (>= 0.5.11)
|
91
|
+
ruby-debug-base19 (>= 0.11.19)
|
92
|
+
ruby_core_source (0.1.4)
|
93
|
+
archive-tar-minitar (>= 0.5.2)
|
94
|
+
thor (0.14.4)
|
95
|
+
treetop (1.4.8)
|
96
|
+
polyglot (>= 0.3.1)
|
97
|
+
tzinfo (0.3.23)
|
98
|
+
|
99
|
+
PLATFORMS
|
100
|
+
ruby
|
101
|
+
|
102
|
+
DEPENDENCIES
|
103
|
+
actionpack (~> 3.0.1)
|
104
|
+
activerecord (~> 3.0.1)
|
105
|
+
database_cleaner (~> 0.6.0)
|
106
|
+
factory_girl_rails (~> 1.0.0)
|
107
|
+
mysql (~> 2.8.0)
|
108
|
+
rspec (~> 2.0.0)
|
109
|
+
ruby-debug19 (~> 0.11.0)
|
data/README.md
CHANGED
@@ -1,9 +1,15 @@
|
|
1
1
|
## Introduction
|
2
2
|
|
3
|
-
ArchiveTree is a
|
3
|
+
ArchiveTree is a Ruby Gem for your Ruby on Rails application that makes it easy for you to generate structured trees of your records.
|
4
4
|
|
5
|
-
Since it
|
5
|
+
Since it uses a column of your choice, from any ActiveRecord Model, you will have flexibility to use in most of the Ruby on Rails applications
|
6
6
|
|
7
|
+
## Compatibility
|
8
|
+
|
9
|
+
The Gem was developed to work with Rails 3.0.x, running on Ruby 1.8.7 or 1.9.2.
|
10
|
+
Since it uses SQL specific queries, it works on MySQL and PostgreSQL databases.
|
11
|
+
|
12
|
+
**Note:** This gem does not work with Ruby v1.9.1.
|
7
13
|
|
8
14
|
## Installation
|
9
15
|
|
@@ -28,6 +34,14 @@ Now let's say that you wish to allow your users to sweep through your posts in a
|
|
28
34
|
|
29
35
|
### API
|
30
36
|
|
37
|
+
#### Inclusion:
|
38
|
+
|
39
|
+
In your ActiveRecord Model:
|
40
|
+
|
41
|
+
<pre>
|
42
|
+
acts_as_archive #=> defaults to :created_at
|
43
|
+
</pre>
|
44
|
+
|
31
45
|
#### Default usage:
|
32
46
|
|
33
47
|
<pre>
|
@@ -54,15 +68,15 @@ Post.archive_tree(:months => [1]) #=> { 2010 => { 1 => [Post] },
|
|
54
68
|
Post.archive_tree(:years_and_months => { 2010 => [1] }) #=> { 2010 => { 1 => [Post] } }
|
55
69
|
</pre>
|
56
70
|
|
57
|
-
###
|
71
|
+
### View
|
58
72
|
|
59
73
|
<pre>
|
60
|
-
draw_archive_tree
|
74
|
+
draw_archive_tree #=> defaults to: :model_sym => :post, :route => :posts_path, :toggle => true, :toggle_text => '[ + ]'
|
61
75
|
</pre>
|
62
76
|
|
63
77
|
## Documentation
|
64
78
|
|
65
|
-
This gem's documentation documentation is available at http://
|
79
|
+
This gem's documentation documentation is available at http://rubydoc.info/github/GnomesLab/archive_tree/
|
66
80
|
|
67
81
|
|
68
82
|
## License
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'rake'
|
2
|
+
require 'rake/rdoctask'
|
3
|
+
require 'rake/gempackagetask'
|
4
|
+
|
5
|
+
desc 'Generate documentation for the archive_tree plugin.'
|
6
|
+
Rake::RDocTask.new(:rdoc) do |rdoc|
|
7
|
+
rdoc.rdoc_dir = 'rdoc'
|
8
|
+
rdoc.title = 'ArchiveTree'
|
9
|
+
rdoc.options << '--line-numbers' << '--inline-source'
|
10
|
+
rdoc.rdoc_files.include('README.md')
|
11
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
12
|
+
end
|
13
|
+
|
14
|
+
begin
|
15
|
+
require 'rspec/core/rake_task'
|
16
|
+
|
17
|
+
RSpec::Core::RakeTask.new(:spec) do |t|
|
18
|
+
t.ruby_opts = '-w'
|
19
|
+
end
|
20
|
+
|
21
|
+
task :default => :spec
|
22
|
+
rescue LoadError
|
23
|
+
raise 'RSpec could not be loaded. Run `bundle install` to get all development dependencies.'
|
24
|
+
end
|
25
|
+
|
26
|
+
# Rubygems
|
27
|
+
namespace :rubygems do
|
28
|
+
gemspec = eval(File.read('archive_tree.gemspec'))
|
29
|
+
Rake::GemPackageTask.new(gemspec) do |pkg|
|
30
|
+
pkg.gem_spec = gemspec
|
31
|
+
end
|
32
|
+
|
33
|
+
desc "build the gem and release it to rubygems.org"
|
34
|
+
task :release => :gem do
|
35
|
+
sh "rake spec"
|
36
|
+
sh "gem push pkg/archive_tree-#{gemspec.version}.gem"
|
37
|
+
end
|
38
|
+
end
|
data/lib/archive_tree.rb
CHANGED
@@ -17,8 +17,8 @@
|
|
17
17
|
# TODO: This module should undergo a query optimization. Furthermore, an ORM abstraction.
|
18
18
|
module ArchiveTree
|
19
19
|
|
20
|
-
require 'archive_tree/action_view_extensions'
|
21
20
|
autoload :Core, 'archive_tree/core'
|
21
|
+
autoload :ActionViewExtensions, 'archive_tree/action_view_extensions'
|
22
22
|
|
23
23
|
def acts_as_archive(date_field = :created_at)
|
24
24
|
raise ::ArgumentError, "undefined parameter #{date_field.to_s}" unless column = columns_hash[date_field.to_s]
|
@@ -33,5 +33,3 @@ module ArchiveTree
|
|
33
33
|
attr_accessor :date_field
|
34
34
|
|
35
35
|
end # ArchiveTree
|
36
|
-
|
37
|
-
ActiveRecord::Base.send :extend, ArchiveTree if defined?(ActiveRecord::Base)
|
@@ -1,8 +1,73 @@
|
|
1
1
|
module ArchiveTree
|
2
2
|
|
3
3
|
module ActionViewExtensions
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
# In the presence of records for a given model it draws the archive tree. Otherwise, returns an empty string
|
6
|
+
#
|
7
|
+
# This method relies on the following private methods:
|
8
|
+
# * +draw_years+
|
9
|
+
# * +draw_months+
|
10
|
+
#
|
11
|
+
# Default behavior
|
12
|
+
# * It will attempt to create a tree of your Post model
|
13
|
+
# * Will use the posts_path route
|
14
|
+
# * Will display a toggle link
|
15
|
+
# * Will use "[ + ]" as the text for the toggle link
|
16
|
+
#
|
17
|
+
# Options
|
18
|
+
# * model_sym #=> the symbol of the model to request the archive_nodes
|
19
|
+
# * route #=> the route that handles the archived posts requests
|
20
|
+
# * toggle #=> when true, includes a toggle link before the years
|
21
|
+
# * toggle_text #=> the text used in the toggle link
|
22
|
+
#
|
23
|
+
# Example using the default settings:
|
24
|
+
# <%= draw_archive_tree %>
|
25
|
+
#
|
26
|
+
# Overriding the defaults example:
|
27
|
+
# <%= draw_archive_tree :model_sym => :post, :route => :archive_published_at_path, :toggle => false %>
|
28
|
+
|
29
|
+
def draw_archive_tree(options = {})
|
30
|
+
options.reverse_merge!({ :model_sym => :post, :route => :posts_path, :toggle => true, :toggle_text => '[ + ]' })
|
31
|
+
model = options[:model_sym].to_s.capitalize.constantize
|
32
|
+
|
33
|
+
raw model.count > 0 ? draw_years(model, options[:route], options[:toggle], options[:toggle_text]) : ''
|
34
|
+
end # draw_archive_tree
|
35
|
+
|
36
|
+
private
|
37
|
+
def draw_years(model_sym, route, toggle, toggle_text) # :nodoc:
|
38
|
+
model = model_sym.to_s.capitalize.constantize
|
39
|
+
route = :posts_path unless self.respond_to? route
|
40
|
+
|
41
|
+
content_tag :ul do
|
42
|
+
ul_body = ""
|
43
|
+
|
44
|
+
model.archived_years.each_key do |year, count|
|
45
|
+
ul_body << content_tag(:li, :class => year == Time.now.year ? 'active' : 'inactive') do
|
46
|
+
(toggle ? link_to(toggle_text, "#", :class => "toggle") : '') + " " +
|
47
|
+
link_to(year, self.send(route, year)) +
|
48
|
+
draw_months(model_sym, route, year)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
ul_body
|
53
|
+
end
|
54
|
+
end # draw_years
|
55
|
+
|
56
|
+
def draw_months(model_sym, route, year) # :nodoc:
|
57
|
+
model = model_sym.to_s.capitalize.constantize
|
58
|
+
|
59
|
+
content_tag :ul do
|
60
|
+
ul_body = ""
|
61
|
+
|
62
|
+
model.archived_months(:year => year).each_pair do |month, count|
|
63
|
+
ul_body << content_tag(:li, link_to("#{Date::MONTHNAMES[month]} (#{count})",
|
64
|
+
self.send(route, year, month < 10 ? "0#{month}" : month)))
|
65
|
+
end
|
66
|
+
|
67
|
+
ul_body
|
68
|
+
end
|
69
|
+
end # draw_months
|
70
|
+
|
6
71
|
end # ActionViewExtensions
|
7
72
|
|
8
73
|
end # ArchiveTree
|
data/spec/db/models.rb
ADDED
data/spec/db/schema.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
ActiveRecord::Schema.define(:version => 20100803160738) do
|
2
|
+
|
3
|
+
create_table "posts", :force => true do |t|
|
4
|
+
t.string "title", :null => false
|
5
|
+
t.text "body", :null => false
|
6
|
+
t.datetime "published_at", :null => true
|
7
|
+
t.datetime "created_at"
|
8
|
+
t.datetime "updated_at"
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index "posts", ["created_at"], :name => "index_posts_on_created_at"
|
12
|
+
add_index "posts", ["published_at"], :name => "index_posts_on_published_at"
|
13
|
+
|
14
|
+
end
|
@@ -0,0 +1,6 @@
|
|
1
|
+
Factory.define(:post) do |p|
|
2
|
+
p.sequence(:title) { |n| "Post Title #{n}" }
|
3
|
+
p.sequence(:body) { |n| "This is the #{n}th post. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer dictum, neque ut imperdiet pellentesque, nulla tellus tempus magna, sed consectetur orci metus a justo. Aliquam ac congue nunc. Mauris a tortor ut massa egestas tempus. Pellentesque tincidunt fermentum diam sagittis ullamcorper. Lorem ipsum dolor sit amet, consectetur adipiscing elit. Integer dictum." }
|
4
|
+
p.sequence(:published_at) { |n| Time.now - n.month }
|
5
|
+
p.created_at Time.now
|
6
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree::ActionViewExtensions do
|
4
|
+
|
5
|
+
before :each do
|
6
|
+
@helper = ActionView::Base.new
|
7
|
+
|
8
|
+
# Inject routes into ActionView::Base
|
9
|
+
@helper.instance_eval do
|
10
|
+
def posts_path(*)
|
11
|
+
'/blog/2010'
|
12
|
+
end
|
13
|
+
|
14
|
+
def dummy_path(*)
|
15
|
+
'/dummy/2010'
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
describe "draw_achive_tree" do
|
21
|
+
|
22
|
+
it "should be included in ActionView::Base" do
|
23
|
+
@helper.should respond_to :draw_archive_tree
|
24
|
+
end # included
|
25
|
+
|
26
|
+
describe "without posts" do
|
27
|
+
it "returns an empty string when the archive tree is empty" do
|
28
|
+
@helper.draw_archive_tree.should be_empty
|
29
|
+
end
|
30
|
+
end # without posts
|
31
|
+
|
32
|
+
describe "with posts" do
|
33
|
+
before :each do
|
34
|
+
Factory.create :post, :created_at => Date.new(Time.now.year, 1, 1)
|
35
|
+
Factory.create :post, :created_at => Date.new(Time.now.year, 2, 1)
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should return the archive tree for all records" do
|
39
|
+
@helper.draw_archive_tree.should == %Q{<ul><li class=\"active\"><a href=\"#\" class=\"toggle\">[ + ]</a> <a href=\"/blog/2010\">2010</a><ul><li><a href=\"/blog/2010\">January (1)</a></li><li><a href=\"/blog/2010\">February (1)</a></li></ul></li></ul>}
|
40
|
+
end
|
41
|
+
end # with posts
|
42
|
+
|
43
|
+
describe "overridable" do
|
44
|
+
before :each do
|
45
|
+
Factory.create :post, :created_at => Date.new(Time.now.year, 1, 1)
|
46
|
+
Factory.create :post, :created_at => Date.new(Time.now.year, 2, 1)
|
47
|
+
end
|
48
|
+
|
49
|
+
it "allows the model name to be overriden" do
|
50
|
+
lambda { @helper.draw_archive_tree(:model_sym => :hello) }.should raise_error NameError
|
51
|
+
end
|
52
|
+
|
53
|
+
it "allows the route to be overriden" do
|
54
|
+
@helper.draw_archive_tree(:route => :dummy_path).should == %Q{<ul><li class=\"active\"><a href=\"#\" class=\"toggle\">[ + ]</a> <a href=\"/dummy/2010\">2010</a><ul><li><a href=\"/dummy/2010\">January (1)</a></li><li><a href=\"/dummy/2010\">February (1)</a></li></ul></li></ul>}
|
55
|
+
end
|
56
|
+
|
57
|
+
it "defaults to the hardcoded route whenever the provided route is unknown" do
|
58
|
+
1.upto(10) { |i| Factory.create :post }
|
59
|
+
@helper.draw_archive_tree(:route => :xpto_path).should match(/ul/)
|
60
|
+
end
|
61
|
+
|
62
|
+
it "allows the toggle to be overriden" do
|
63
|
+
html = @helper.draw_archive_tree(:toggle => false)
|
64
|
+
html.should_not include '<a href="#" class="toggle">[ + ]</a>'
|
65
|
+
end
|
66
|
+
|
67
|
+
it "allows the toggle text to be overriden" do
|
68
|
+
html = @helper.draw_archive_tree(:toggle_text => '+toggle+')
|
69
|
+
html.should include '<a href="#" class="toggle">+toggle+</a>'
|
70
|
+
end
|
71
|
+
|
72
|
+
end # overridable
|
73
|
+
|
74
|
+
end # draw_achive_tree
|
75
|
+
|
76
|
+
end # ArchiveTree::ActionViewExtensions
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree do
|
4
|
+
describe "archive_node" do
|
5
|
+
|
6
|
+
before :each do
|
7
|
+
1.upto(2) { |i| Factory.create(:post, :created_at => "#{Time.now.year}-0#{i}-01 00:00:00") }
|
8
|
+
1.upto(2) { |i| Factory.create(:post, :created_at => "#{Time.now.year + 1}-0#{i}-01 00:00:00") }
|
9
|
+
end
|
10
|
+
|
11
|
+
describe "defaults" do
|
12
|
+
it "uses the current year" do
|
13
|
+
Post.archive_node.each { |p| p.created_at.year.should == Time.now.year }
|
14
|
+
end
|
15
|
+
|
16
|
+
it "ignores the month" do
|
17
|
+
Post.archive_node.should have(2).record
|
18
|
+
end
|
19
|
+
|
20
|
+
end # defaults
|
21
|
+
|
22
|
+
describe "overridable" do
|
23
|
+
it "allows to override the year" do
|
24
|
+
year = Time.now.year + 1
|
25
|
+
Post.archive_node(:year => year).each { |p| p.created_at.year.should == year }
|
26
|
+
end
|
27
|
+
|
28
|
+
it "allows to select a month" do
|
29
|
+
Post.archive_node(:year => Time.now.year, :month => 1).each { |p| p.created_at.month.should == 1 }
|
30
|
+
end
|
31
|
+
|
32
|
+
it "allows to override the year and select a month" do
|
33
|
+
Post.archive_node(:year => Time.now.year, :month => 1).should have(1).record
|
34
|
+
end
|
35
|
+
end # overridables
|
36
|
+
|
37
|
+
end # archive_node
|
38
|
+
end # ArchiveTree
|
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree do
|
4
|
+
|
5
|
+
describe "self included" do
|
6
|
+
|
7
|
+
it "should extend klass with its ArchiveTree::Core" do
|
8
|
+
[:archived_years, :archived_months, :archive_tree, :archive_node].each do |method|
|
9
|
+
Post.should respond_to method
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end # self.included
|
13
|
+
|
14
|
+
end # ArchiveTree
|
@@ -0,0 +1,98 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree do
|
4
|
+
|
5
|
+
describe "acts_as_archive" do
|
6
|
+
|
7
|
+
it "should be a class method of ActiveRecord::Base" do
|
8
|
+
ActiveRecord::Base.should respond_to :acts_as_archive
|
9
|
+
end
|
10
|
+
|
11
|
+
it "should raise exception for undefined fields" do
|
12
|
+
lambda do
|
13
|
+
class Post < ActiveRecord::Base
|
14
|
+
acts_as_archive :dummy
|
15
|
+
end
|
16
|
+
end.should raise_error(ArgumentError)
|
17
|
+
end
|
18
|
+
|
19
|
+
it "should raise exception for invalid fields" do
|
20
|
+
lambda do
|
21
|
+
class Post < ActiveRecord::Base
|
22
|
+
acts_as_archive :body
|
23
|
+
end
|
24
|
+
end.should raise_error(ArgumentError)
|
25
|
+
end
|
26
|
+
|
27
|
+
end # acts_as_archive
|
28
|
+
|
29
|
+
describe "archive tree" do
|
30
|
+
|
31
|
+
before :each do
|
32
|
+
[2007, 2008, 2009, 2010].each do |year|
|
33
|
+
5.times { |i| Factory.create(:post, :created_at => "#{year}-#{01 + i}-01 00:00:00") }
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe "default behavior" do
|
38
|
+
|
39
|
+
it "should return an empty hash when there are no records" do
|
40
|
+
Post.destroy_all
|
41
|
+
|
42
|
+
Post.archive_tree.should == {}
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should return the archive tree for all posts" do
|
46
|
+
tree = {}
|
47
|
+
[2007, 2008, 2009, 2010].each_with_index do |year, year_index|
|
48
|
+
tree[year] = {}
|
49
|
+
0.upto(4).each { |i| tree[year][i+1] = [Post.find(Post.first.id + year_index*5 + i)] }
|
50
|
+
end
|
51
|
+
|
52
|
+
Post.archive_tree.should == tree
|
53
|
+
end
|
54
|
+
|
55
|
+
end # default behavior
|
56
|
+
|
57
|
+
describe "years to sweep" do
|
58
|
+
|
59
|
+
it "accepts a years key in the options hash and complies to it" do
|
60
|
+
tree = {}
|
61
|
+
[2009, 2010].each_with_index do |year, year_index|
|
62
|
+
tree[year] = {}
|
63
|
+
0.upto(4).each { |i| tree[year][i+1] = [Post.find(10 + Post.first.id + year_index*5 + i)] }
|
64
|
+
end
|
65
|
+
|
66
|
+
Post.archive_tree(:years => [2009, 2010]).should == tree
|
67
|
+
end
|
68
|
+
|
69
|
+
end # years to sweep
|
70
|
+
|
71
|
+
describe "months to sweep" do
|
72
|
+
|
73
|
+
it "should only sweep January" do
|
74
|
+
tree = {}
|
75
|
+
[2007, 2008, 2009, 2010].each_with_index do |year, year_index|
|
76
|
+
tree[year] = {}
|
77
|
+
tree[year][1] = [Post.find(Post.first.id + year_index*5)]
|
78
|
+
end
|
79
|
+
|
80
|
+
Post.archive_tree(:months => [1]).should == tree
|
81
|
+
end
|
82
|
+
|
83
|
+
end # months to sweep
|
84
|
+
|
85
|
+
describe "years and months" do
|
86
|
+
|
87
|
+
it "should comply with the requested years and months filter" do
|
88
|
+
tree = { 2007 => { 1 => [Post.find(Post.first.id)] },
|
89
|
+
2008 => { 2 => [Post.find(Post.first.id + 6)], 3 => [Post.find(Post.first.id + 7)] } }
|
90
|
+
|
91
|
+
Post.archive_tree(:years_and_months => { 2007 => [1], 2008 => [2, 3] }).should == tree
|
92
|
+
end
|
93
|
+
|
94
|
+
end # years and months
|
95
|
+
|
96
|
+
end # archive_tree
|
97
|
+
|
98
|
+
end # ArchiveTree
|
@@ -0,0 +1,49 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree do
|
4
|
+
|
5
|
+
describe "archived months" do
|
6
|
+
|
7
|
+
before :each do
|
8
|
+
2.times do |i|
|
9
|
+
Factory.create(:post, :created_at => "#{Time.now.year + i}-01-01 00:00:00")
|
10
|
+
Factory.create(:post, :created_at => "#{Time.now.year + i}-02-01 00:00:00")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
|
14
|
+
it "returns an empty hash if no records exist for a given year" do
|
15
|
+
Post.archived_months(:year => 3000).should == {}
|
16
|
+
end
|
17
|
+
|
18
|
+
it "returns an integer months counter hash" do
|
19
|
+
Post.archived_months.should == { 1 => 1, 2 => 1 }
|
20
|
+
end
|
21
|
+
|
22
|
+
it "defaults it's sweep year to the current year" do
|
23
|
+
Factory.create :post, :created_at => "#{Time.now.year}-#{12}-01 00:00:00"
|
24
|
+
Post.archived_months == { 1 => 1, 2 => 1, 12 => 1 }
|
25
|
+
end
|
26
|
+
|
27
|
+
it "allows the invoker to specify the year being sweeped" do
|
28
|
+
Post.archived_months(:year => (Time.now.year + 1)).should == { 1 => 1, 2 => 1 }
|
29
|
+
end
|
30
|
+
|
31
|
+
it "allows the type of month name to be specified as short" do
|
32
|
+
Post.archived_months(:month_names => :short).should == { "Jan" => 1, "Feb" => 1 }
|
33
|
+
end
|
34
|
+
|
35
|
+
it "allows the type of month name to be specified as long" do
|
36
|
+
Post.archived_months(:month_names => :long).should == { "January" => 1, "February" => 1 }
|
37
|
+
end
|
38
|
+
|
39
|
+
it "defaults to :month_names => :int whenever an unknown value is passed" do
|
40
|
+
Post.archived_months(:month_names => :invalid_value).should == { 1 => 1, 2 => 1 }
|
41
|
+
end
|
42
|
+
|
43
|
+
it "discards dates that are null" do
|
44
|
+
Post.first.update_attributes(:created_at => nil)
|
45
|
+
Post.archived_months.should == { 2 => 1 }
|
46
|
+
end
|
47
|
+
end # archived_months
|
48
|
+
|
49
|
+
end # ArchiveTree
|
@@ -0,0 +1,27 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe ArchiveTree do
|
4
|
+
|
5
|
+
describe "archived years" do
|
6
|
+
|
7
|
+
it "returns an empty hash if no years are archived" do
|
8
|
+
Post.archived_years.should == {}
|
9
|
+
end
|
10
|
+
|
11
|
+
it "returns a years counter hash" do
|
12
|
+
2.times { |i| Factory.create(:post, :created_at => "#{Time.now.year + i}-#{01 + i}-01 00:00:00") }
|
13
|
+
|
14
|
+
Post.archived_years.should == { Time.now.year => 1, (Time.now.year + 1) => 1 }
|
15
|
+
end
|
16
|
+
|
17
|
+
it "discards dates that are null" do
|
18
|
+
2.times { |i| Factory.create(:post, :created_at => "#{Time.now.year + i}-#{01 + i}-01 00:00:00") }
|
19
|
+
|
20
|
+
Post.last.update_attributes(:created_at => nil)
|
21
|
+
|
22
|
+
Post.archived_years.should == { Time.now.year => 1 }
|
23
|
+
end
|
24
|
+
|
25
|
+
end # archived_years
|
26
|
+
|
27
|
+
end # ArchiveTree
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
$:.unshift File.dirname(__FILE__) unless $:.include? File.dirname(__FILE__)
|
2
|
+
$:.unshift File.join(File.dirname(__FILE__), '..') unless $:.include? File.join(File.dirname(__FILE__), '..')
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'init'
|
6
|
+
require 'erb'
|
7
|
+
require 'logger'
|
8
|
+
require 'rspec'
|
9
|
+
require 'active_record'
|
10
|
+
require 'database_cleaner'
|
11
|
+
require 'factory_girl'
|
12
|
+
|
13
|
+
RSpec.configure do |config|
|
14
|
+
config.debug = true
|
15
|
+
# == Mock Framework
|
16
|
+
config.mock_with :rspec
|
17
|
+
|
18
|
+
# database_cleaner
|
19
|
+
config.before(:suite) do
|
20
|
+
DatabaseCleaner.strategy = :transaction
|
21
|
+
DatabaseCleaner.clean_with(:truncation)
|
22
|
+
end
|
23
|
+
|
24
|
+
config.before(:each) do
|
25
|
+
DatabaseCleaner.start
|
26
|
+
end
|
27
|
+
|
28
|
+
config.after(:each) do
|
29
|
+
DatabaseCleaner.clean
|
30
|
+
end
|
31
|
+
end
|
32
|
+
rescue LoadError => load_error
|
33
|
+
puts "Please run bundle install"
|
34
|
+
rescue StandardError => e
|
35
|
+
puts "Something went wrong while loading the environment."
|
36
|
+
throw e
|
37
|
+
end
|
38
|
+
|
39
|
+
# Requires supporting files with custom matchers and macros, etc, in ./support/ and its subdirectories.
|
40
|
+
Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each { |f| require f }
|
41
|
+
|
42
|
+
# Requires all supporting factories
|
43
|
+
Dir.glob(File.join(File.dirname(__FILE__), 'factories', '*_factory.rb')).each { |f| require f }
|
44
|
+
|
45
|
+
# ActiveRecord Test database configurations
|
46
|
+
database_yml_file = File.expand_path('../config/database.yml', __FILE__)
|
47
|
+
|
48
|
+
begin
|
49
|
+
if File.exists?(database_yml_file)
|
50
|
+
active_record_configuration = YAML.load_file(database_yml_file)['test']
|
51
|
+
ActiveRecord::Base.establish_connection(active_record_configuration)
|
52
|
+
ActiveRecord::Base.logger = Logger.new(File.join(File.dirname(__FILE__), 'log', 'test.log'))
|
53
|
+
|
54
|
+
ActiveRecord::Base.silence do
|
55
|
+
ActiveRecord::Migration.verbose = false
|
56
|
+
|
57
|
+
load File.join(File.dirname(__FILE__), 'db', 'schema.rb')
|
58
|
+
load File.join(File.dirname(__FILE__), 'db' , 'models.rb')
|
59
|
+
end
|
60
|
+
|
61
|
+
# The config/database.yml is in the spec folder
|
62
|
+
DatabaseCleaner.app_root = File.expand_path('spec')
|
63
|
+
else
|
64
|
+
raise "Please create #{database_yml} first. Take a look at the database.sample.yml in the config folder."
|
65
|
+
end
|
66
|
+
rescue StandardError => e
|
67
|
+
puts "Something went wrong while attempting to load your database file, or while configuring ActiveRecord."
|
68
|
+
throw e
|
69
|
+
end
|
metadata
CHANGED
@@ -1,13 +1,12 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: archive_tree
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
prerelease:
|
4
|
+
prerelease: false
|
5
5
|
segments:
|
6
6
|
- 1
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
|
10
|
-
version: 1.0.0.rc3
|
9
|
+
version: 1.0.0
|
11
10
|
platform: ruby
|
12
11
|
authors:
|
13
12
|
- Diogo Almeida
|
@@ -16,7 +15,7 @@ autorequire:
|
|
16
15
|
bindir: bin
|
17
16
|
cert_chain: []
|
18
17
|
|
19
|
-
date: 2010-11-
|
18
|
+
date: 2010-11-09 00:00:00 +00:00
|
20
19
|
default_executable:
|
21
20
|
dependencies:
|
22
21
|
- !ruby/object:Gem::Dependency
|
@@ -30,36 +29,100 @@ dependencies:
|
|
30
29
|
segments:
|
31
30
|
- 3
|
32
31
|
- 0
|
33
|
-
-
|
34
|
-
version: 3.0.
|
32
|
+
- 1
|
33
|
+
version: 3.0.1
|
35
34
|
type: :runtime
|
36
35
|
version_requirements: *id001
|
37
36
|
- !ruby/object:Gem::Dependency
|
38
|
-
name:
|
37
|
+
name: actionpack
|
39
38
|
prerelease: false
|
40
39
|
requirement: &id002 !ruby/object:Gem::Requirement
|
41
40
|
none: false
|
42
41
|
requirements:
|
43
|
-
- -
|
42
|
+
- - ~>
|
44
43
|
- !ruby/object:Gem::Version
|
45
44
|
segments:
|
45
|
+
- 3
|
46
46
|
- 0
|
47
|
-
|
48
|
-
|
47
|
+
- 1
|
48
|
+
version: 3.0.1
|
49
|
+
type: :runtime
|
49
50
|
version_requirements: *id002
|
50
51
|
- !ruby/object:Gem::Dependency
|
51
|
-
name:
|
52
|
+
name: mysql
|
52
53
|
prerelease: false
|
53
54
|
requirement: &id003 !ruby/object:Gem::Requirement
|
54
55
|
none: false
|
55
56
|
requirements:
|
56
|
-
- -
|
57
|
+
- - ~>
|
57
58
|
- !ruby/object:Gem::Version
|
58
59
|
segments:
|
60
|
+
- 2
|
61
|
+
- 8
|
59
62
|
- 0
|
60
|
-
version:
|
63
|
+
version: 2.8.0
|
61
64
|
type: :development
|
62
65
|
version_requirements: *id003
|
66
|
+
- !ruby/object:Gem::Dependency
|
67
|
+
name: ruby-debug19
|
68
|
+
prerelease: false
|
69
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
70
|
+
none: false
|
71
|
+
requirements:
|
72
|
+
- - ~>
|
73
|
+
- !ruby/object:Gem::Version
|
74
|
+
segments:
|
75
|
+
- 0
|
76
|
+
- 11
|
77
|
+
- 0
|
78
|
+
version: 0.11.0
|
79
|
+
type: :development
|
80
|
+
version_requirements: *id004
|
81
|
+
- !ruby/object:Gem::Dependency
|
82
|
+
name: rspec
|
83
|
+
prerelease: false
|
84
|
+
requirement: &id005 !ruby/object:Gem::Requirement
|
85
|
+
none: false
|
86
|
+
requirements:
|
87
|
+
- - ~>
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
segments:
|
90
|
+
- 2
|
91
|
+
- 0
|
92
|
+
- 0
|
93
|
+
version: 2.0.0
|
94
|
+
type: :development
|
95
|
+
version_requirements: *id005
|
96
|
+
- !ruby/object:Gem::Dependency
|
97
|
+
name: factory_girl_rails
|
98
|
+
prerelease: false
|
99
|
+
requirement: &id006 !ruby/object:Gem::Requirement
|
100
|
+
none: false
|
101
|
+
requirements:
|
102
|
+
- - ~>
|
103
|
+
- !ruby/object:Gem::Version
|
104
|
+
segments:
|
105
|
+
- 1
|
106
|
+
- 0
|
107
|
+
- 0
|
108
|
+
version: 1.0.0
|
109
|
+
type: :development
|
110
|
+
version_requirements: *id006
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: database_cleaner
|
113
|
+
prerelease: false
|
114
|
+
requirement: &id007 !ruby/object:Gem::Requirement
|
115
|
+
none: false
|
116
|
+
requirements:
|
117
|
+
- - ~>
|
118
|
+
- !ruby/object:Gem::Version
|
119
|
+
segments:
|
120
|
+
- 0
|
121
|
+
- 6
|
122
|
+
- 0
|
123
|
+
version: 0.6.0
|
124
|
+
type: :development
|
125
|
+
version_requirements: *id007
|
63
126
|
description: ArchiveTree is a Ruby Gem that makes it easy for you to create beautiful chronological archive trees of your models. For instance, you can create a tree for your blog posts.
|
64
127
|
email:
|
65
128
|
- mail@gnomeslab.com
|
@@ -70,12 +133,24 @@ extensions: []
|
|
70
133
|
extra_rdoc_files: []
|
71
134
|
|
72
135
|
files:
|
73
|
-
- lib/archive_tree/action_view_extensions/draw_archive_tree.rb
|
74
136
|
- lib/archive_tree/action_view_extensions.rb
|
75
137
|
- lib/archive_tree/core.rb
|
76
138
|
- lib/archive_tree.rb
|
139
|
+
- Gemfile
|
140
|
+
- Gemfile.lock
|
77
141
|
- MIT-LICENSE
|
142
|
+
- Rakefile
|
78
143
|
- README.md
|
144
|
+
- spec/db/models.rb
|
145
|
+
- spec/db/schema.rb
|
146
|
+
- spec/factories/posts_factory.rb
|
147
|
+
- spec/lib/action_view_extensions/action_view_extensions_spec.rb
|
148
|
+
- spec/lib/archive_node_spec.rb
|
149
|
+
- spec/lib/archive_tree_core_spec.rb
|
150
|
+
- spec/lib/archive_tree_spec.rb
|
151
|
+
- spec/lib/archived_months_spec.rb
|
152
|
+
- spec/lib/archived_years_spec.rb
|
153
|
+
- spec/spec_helper.rb
|
79
154
|
has_rdoc: true
|
80
155
|
homepage: http://github.com/GnomesLab/archive_tree/
|
81
156
|
licenses: []
|
@@ -85,6 +160,7 @@ rdoc_options: []
|
|
85
160
|
|
86
161
|
require_paths:
|
87
162
|
- lib
|
163
|
+
- lib
|
88
164
|
required_ruby_version: !ruby/object:Gem::Requirement
|
89
165
|
none: false
|
90
166
|
requirements:
|
@@ -109,6 +185,6 @@ rubyforge_project:
|
|
109
185
|
rubygems_version: 1.3.7
|
110
186
|
signing_key:
|
111
187
|
specification_version: 3
|
112
|
-
summary: Creates chronological trees of your models based on
|
188
|
+
summary: Creates chronological trees of your models based on column of your choice.
|
113
189
|
test_files: []
|
114
190
|
|
@@ -1,76 +0,0 @@
|
|
1
|
-
module ArchiveTree
|
2
|
-
module ActionViewExtensions
|
3
|
-
|
4
|
-
# Defines the helper methods that will be included in the ActionView::Base in
|
5
|
-
# order to return the html representation of the archive tree
|
6
|
-
module DrawArchiveTree
|
7
|
-
|
8
|
-
# In the presence of records for a given model it draws the archive tree. Otherwise, returns an empty string
|
9
|
-
#
|
10
|
-
# This method relies on the following private methods:
|
11
|
-
# * +draw_years+
|
12
|
-
# * +draw_months+
|
13
|
-
#
|
14
|
-
# Default behavior
|
15
|
-
# * It will attempt to create a tree of your Post model
|
16
|
-
# * Will use the posts_path route
|
17
|
-
# * Will display a toggle link
|
18
|
-
# * Will use "[ + ]" as the text for the toggle link
|
19
|
-
#
|
20
|
-
# Options
|
21
|
-
# * model_sym #=> the symbol of the model to request the archive_nodes
|
22
|
-
# * route #=> the route that handles the archived posts requests
|
23
|
-
# * toggle #=> when true, includes a toggle link before the years
|
24
|
-
# * toggle_text #=> the text used in the toggle link
|
25
|
-
#
|
26
|
-
# Example using the default settings:
|
27
|
-
# <%= draw_archive_tree %>
|
28
|
-
#
|
29
|
-
# Overriding the defaults example:
|
30
|
-
# <%= draw_archive_tree :model_sym => :post, :route => :archive_published_at_path, :toggle => false %>
|
31
|
-
|
32
|
-
def draw_archive_tree(options = {})
|
33
|
-
options.reverse_merge!({ :model_sym => :post, :route => :posts_path, :toggle => true, :toggle_text => '[ + ]' })
|
34
|
-
model = options[:model_sym].to_s.capitalize.constantize
|
35
|
-
|
36
|
-
raw model.count > 0 ? draw_years(model, options[:route], options[:toggle], options[:toggle_text]) : ''
|
37
|
-
end # draw_archive_tree
|
38
|
-
|
39
|
-
private
|
40
|
-
def draw_years(model_sym, route, toggle, toggle_text) # :nodoc:
|
41
|
-
model = model_sym.to_s.capitalize.constantize
|
42
|
-
route = :posts_path unless self.respond_to? route
|
43
|
-
|
44
|
-
content_tag :ul do
|
45
|
-
ul_body = ""
|
46
|
-
|
47
|
-
model.archived_years.each_key do |year, count|
|
48
|
-
ul_body << content_tag(:li, :class => year == Time.now.year ? 'active' : 'inactive') do
|
49
|
-
(toggle ? link_to(toggle_text, "#", :class => "toggle") : '') + " " +
|
50
|
-
link_to(year, self.send(route, year)) +
|
51
|
-
draw_months(model_sym, route, year)
|
52
|
-
end
|
53
|
-
end
|
54
|
-
|
55
|
-
ul_body
|
56
|
-
end
|
57
|
-
end
|
58
|
-
|
59
|
-
def draw_months(model_sym, route, year) # :nodoc:
|
60
|
-
model = model_sym.to_s.capitalize.constantize
|
61
|
-
|
62
|
-
content_tag :ul do
|
63
|
-
ul_body = ""
|
64
|
-
|
65
|
-
model.archived_months(:year => year).each_pair do |month, count|
|
66
|
-
ul_body << content_tag(:li, link_to("#{Date::MONTHNAMES[month]} (#{count})",
|
67
|
-
self.send(route, year, month < 10 ? "0#{month}" : month)))
|
68
|
-
end
|
69
|
-
|
70
|
-
ul_body
|
71
|
-
end
|
72
|
-
end
|
73
|
-
end # DrawArchiveTree
|
74
|
-
|
75
|
-
end # ActionViewExtensions
|
76
|
-
end # ArchiveTree
|