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 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 plugin for your Ruby on Rails application that makes it easy for you to generate structured trees of your records.
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 makes use of your model's _created_at_ column, ArchiveTree is ultimately compatible with most ActiveRecord Models out there.
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
- ### Views
71
+ ### View
58
72
 
59
73
  <pre>
60
- draw_archive_tree(:model_sym => :post, :route => :archive_published_at_path, :toggle => false)
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://yardoc.org/docs/GnomesLab-archive_tree
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
- require 'archive_tree/action_view_extensions/draw_archive_tree'
5
- ::ActionView::Base.send :include, DrawArchiveTree
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
@@ -0,0 +1,3 @@
1
+ class Post < ActiveRecord::Base
2
+ acts_as_archive
3
+ end
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
@@ -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: true
4
+ prerelease: false
5
5
  segments:
6
6
  - 1
7
7
  - 0
8
8
  - 0
9
- - rc3
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-03 00:00:00 +00:00
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
- - 0
34
- version: 3.0.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: rspec
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
- version: "0"
48
- type: :development
47
+ - 1
48
+ version: 3.0.1
49
+ type: :runtime
49
50
  version_requirements: *id002
50
51
  - !ruby/object:Gem::Dependency
51
- name: database_cleaner
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: "0"
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 their created_at column value.
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