<?xml version="1.0" encoding="UTF-8"?>
<commit>
  <added type="array">
    <added>
      <filename>app/views/stories/_tags.html.erb</filename>
    </added>
    <added>
      <filename>app/views/tags/_header.html.erb</filename>
    </added>
    <added>
      <filename>app/views/tags/_list.html.erb</filename>
    </added>
    <added>
      <filename>app/views/tags/_stories.html.erb</filename>
    </added>
    <added>
      <filename>app/views/tags/_tag.html.erb</filename>
    </added>
    <added>
      <filename>doc/TODO</filename>
    </added>
    <added>
      <filename>lib/story_tags_presenter.rb</filename>
    </added>
    <added>
      <filename>spec/objects/story_tags_presenter_spec.rb</filename>
    </added>
    <added>
      <filename>spec/views/stories/_tags.html.erb_spec.rb</filename>
    </added>
    <added>
      <filename>stories/helpers/states.rb</filename>
    </added>
  </added>
  <modified type="array">
    <modified>
      <diff>@@ -9,5 +9,5 @@ module IterationsHelper
         :loading =&gt; &quot;Element.update('notice', 'Loading #{iteration.name}...') ; Element.show('notice')&quot;, 
         :success =&gt; &quot;Element.hide('notice')&quot;
     end
-  end
+  end  
 end</diff>
      <filename>app/helpers/iterations_helper.rb</filename>
    </modified>
    <modified>
      <diff>@@ -29,6 +29,23 @@ class Project &lt; ActiveRecord::Base
       find_current || build( :name =&gt; &quot;Iteration #{size + 1}&quot;, :start_date =&gt; Date.today, :end_date =&gt;  Date.today + 7 )
     end
   end
+  has_many :story_tags, :class_name =&gt; Tag.name, :finder_sql =&gt; '
+    SELECT tags.*
+    FROM projects
+    INNER JOIN stories ON stories.project_id=projects.id
+    INNER JOIN taggings ON (taggings.taggable_id=stories.id AND taggings.taggable_type=\'Story\')
+    INNER JOIN tags ON tags.id=taggings.tag_id
+    WHERE
+      projects.id = #{id}
+    GROUP BY tags.id'
+  has_many :tagless_stories, :class_name =&gt; Story.name, :finder_sql =&gt; '
+    SELECT stories.*
+    FROM projects
+    INNER JOIN stories ON stories.project_id=projects.id
+    LEFT JOIN taggings ON (taggings.taggable_id=stories.id AND taggings.taggable_type=\'Story\')
+    WHERE
+      projects.id = #{id} AND
+      taggings.taggable_id IS NULL'
 
   
   def iterations_ordered_by_start_date</diff>
      <filename>app/models/project.rb</filename>
    </modified>
    <modified>
      <diff>@@ -2,6 +2,10 @@
   &lt;div class=&quot;section_header&quot;&gt;Stories&lt;/div&gt;
 
   &lt;div id=&quot;stories&quot; class=&quot;section_content&quot;&gt;
-    &lt;%= render :partial =&gt; 'stories/iterations', :locals =&gt; { :iterations =&gt; @stories_presenter.iterations_presenter } %&gt;
+    &lt;% if @stories_presenter.iterations? %&gt;
+      &lt;%= render :partial =&gt; 'stories/iterations', :locals =&gt; { :iterations =&gt; @stories_presenter.iterations } %&gt;
+    &lt;% elsif @stories_presenter.tags? %&gt;
+      &lt;%= render :partial =&gt; 'stories/tags', :locals =&gt; { :tags =&gt; @stories_presenter.tags } %&gt;    
+    &lt;% end %&gt;
   &lt;/div&gt;
 &lt;/div&gt;</diff>
      <filename>app/views/stories/index.html.erb</filename>
    </modified>
    <modified>
      <diff>@@ -19,6 +19,7 @@ Rails::Initializer.run do |config|
   # Only load the plugins named here, in the order given. By default all plugins in vendor/plugins are loaded, in alphabetical order
   # :all can be used as a placeholder for all plugins not explicitly named.
   # config.plugins = [ :exception_notification, :ssl_requirement, :all ]
+  config.plugins = [ :acts_as_textiled, :has_many_polymorphs, :all ]
 
   # Add additional load paths for your own custom dirs
   config.load_paths += %W( #{RAILS_ROOT}/app/observers #{RAILS_ROOT}/app/mailers )</diff>
      <filename>config/environment.rb</filename>
    </modified>
    <modified>
      <diff>@@ -12,10 +12,17 @@ class StoriesIndexPresenter &lt; PresentationObject
     VIEWS.include?(@view) ? @view : VIEWS.first
   end
     
-  declare :iterations_presenter do
+  declare :iterations do
     IterationsPresenter.new(
       :iterations =&gt; @project.iterations_ordered_by_start_date,
       :backlog =&gt; @project.backlog_iteration,
       :project =&gt; @project)
   end
+  
+  declare :tags do
+    StoryTagsPresenter.new(
+      :tags =&gt; @project.story_tags,
+      :project =&gt; @project
+    )
+  end
 end
\ No newline at end of file</diff>
      <filename>lib/stories_index_presenter.rb</filename>
    </modified>
    <modified>
      <diff>@@ -26,6 +26,46 @@ describe Project, &quot;#new with name attribute&quot; do
   end
 end
 
+describe Project, '#story_tags' do
+  before do
+    @project = Generate.project :name =&gt; &quot;foo&quot;
+    @stories = [
+      Generate.story(&quot;story 1&quot;, :project =&gt; @project),
+      Generate.story(&quot;story 2&quot;, :project =&gt; @project) ]
+    @stories.first.tag_list = &quot;foo, baz&quot;
+    @stories.last.tag_list = &quot;foo, baz, bar&quot;
+    @stories.each{ |s| s.save! }
+  end
+  
+  it &quot;returns the unique tags that belong to the stories on this project&quot; do
+    @project.story_tags.should == (@stories.first.tags + @stories.last.tags).uniq
+  end
+end
+
+describe Project, '#tagless_stories' do
+  before do
+    @project = Generate.project :name =&gt; &quot;foo&quot;
+    @stories = [
+      Generate.story(&quot;story1&quot;, :project =&gt; @project),
+      Generate.story(&quot;story2&quot;, :project =&gt; @project),
+      Generate.story(&quot;story3&quot;, :project =&gt; @project) ]
+    @stories[0].tag_list = &quot;&quot;
+    @stories[1].tag_list = &quot;foo, baz, bar&quot;    
+    @stories[2].tag_list = &quot;&quot;
+    @stories.each{ |s| s.save! }
+  end
+  
+  it &quot;returns stories which are not tagged&quot; do
+    @project.tagless_stories.should == [@stories[0], @stories[2]]
+  end
+  
+  it &quot;doesn't include stories from other projects&quot; do
+    @project2 = Generate.project :name =&gt; &quot;baz&quot;
+    @story2 = Generate.story &quot;another project's story&quot;, :project =&gt; @project2
+    @project.tagless_stories.should_not include(@story2)
+  end
+end
+
 describe Project, &quot;#total_points&quot; do
   before do
     Story.delete_all</diff>
      <filename>spec/models/project_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -44,7 +44,7 @@ describe StoriesIndexPresenter, '#tags?' do
   end
 end
 
-describe StoriesIndexPresenter, '#iterations_presenter' do
+describe StoriesIndexPresenter, '#iterations' do
   before do
     @project = stub(&quot;project&quot;, 
       :iterations_ordered_by_start_date =&gt; nil, 
@@ -55,12 +55,12 @@ describe StoriesIndexPresenter, '#iterations_presenter' do
   
   it &quot;finds all iterations ordered by start date&quot; do
     @project.should_receive(:iterations_ordered_by_start_date)
-    @presenter.iterations_presenter
+    @presenter.iterations
   end
   
   it &quot;finds the backlog iteration&quot; do
     @project.should_receive(:backlog_iteration)
-    @presenter.iterations_presenter
+    @presenter.iterations
   end
   
   it &quot;creates a new IterationsPresenter&quot; do
@@ -71,18 +71,48 @@ describe StoriesIndexPresenter, '#iterations_presenter' do
       :iterations =&gt; iterations, 
       :backlog =&gt; backlog_iteration,
       :project =&gt; @project)
-    @presenter.iterations_presenter
+    @presenter.iterations
   end
   
-  it &quot;returns the newly created iterations_presenter&quot; do
-    iterations_presenter = stub(&quot;iterations presenter&quot;)
-    IterationsPresenter.stub!(:new).and_return(iterations_presenter)
-    @presenter.iterations_presenter.should == iterations_presenter
+  it &quot;returns the newly created iterations&quot; do
+    iterations = stub(&quot;iterations presenter&quot;)
+    IterationsPresenter.stub!(:new).and_return(iterations)
+    @presenter.iterations.should == iterations
   end
   
   it &quot;caches the return value for subsequent calls&quot; do
     IterationsPresenter.should_receive(:new).once.and_return(:foo)
-    @presenter.iterations_presenter.should == :foo
-    @presenter.iterations_presenter.should == :foo # only the call is executed, this one is cached
+    @presenter.iterations.should == :foo
+    @presenter.iterations.should == :foo 
   end
 end
+
+describe StoriesIndexPresenter, '#tags' do
+  before do
+    @tags = stub(&quot;tags&quot;)
+    @stories = stub(&quot;tagless stories&quot;)
+    @project = stub(&quot;project&quot;, :story_tags =&gt; @tags)
+    @presenter = StoriesIndexPresenter.new :project =&gt; @project
+    StoryTagsPresenter.stub!(:new)
+  end
+
+  it &quot;finds all tags that belong to the project&quot; do
+    @project.should_receive(:story_tags).and_return(@tags)
+    @presenter.tags
+  end
+  
+  it &quot;creates a new StoryTagsPresenter&quot; do
+    @project.stub!(:story_tags).and_return(@tags)
+    StoryTagsPresenter.should_receive(:new).with(
+      :tags =&gt; @tags,
+      :project =&gt; @project)
+    @presenter.tags
+  end
+  
+  it &quot;caches the return value for subsequent calls&quot; do
+    StoryTagsPresenter.stub!(:new).once.and_return(:foo)
+    @presenter.tags.should == :foo
+    @presenter.tags.should == :foo
+  end
+  
+end</diff>
      <filename>spec/objects/stories_index_presenter_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -9,14 +9,35 @@ describe &quot;/stories/index.html.erb&quot; do
   
   before do
     @iterations = mock &quot;iterations presenter&quot;
-    @stories_presenter = stub(&quot;stories presenter&quot;, :iterations_presenter =&gt; @iterations)
+    @tags = mock &quot;tags presenter&quot;
+    @stories_presenter = stub(&quot;stories presenter&quot;, :iterations =&gt; @iterations, :tags =&gt; @tags)
     assigns[:stories_presenter] = @stories_presenter
-    template.expect_render(:partial =&gt; &quot;stories/iterations&quot;, :locals =&gt; {:iterations=&gt;@iterations}).and_return(%|&lt;p id=&quot;iterations-partial&quot; /&gt;|)
   end
 
-  it &quot;should render the iterations partial&quot; do
-    render_it
-    response.should have_tag(&quot;#iterations-partial&quot;)
+  describe &quot;when the the stories presenter is presenting on iterations&quot; do
+    before do
+      @stories_presenter.stub!(:iterations?).and_return(true)
+      template.expect_render(:partial =&gt; &quot;stories/iterations&quot;, :locals =&gt; {:iterations=&gt;@iterations}).and_return(%|&lt;p id=&quot;iterations-partial&quot; /&gt;|)
+    end
+    
+    it &quot;renders the stories/iterations partial&quot; do
+      render_it
+      response.should have_tag(&quot;#iterations-partial&quot;)
+    end
   end
+  
+  describe &quot;when the the stories presenter is presenting on tags&quot; do
+    before do
+      @stories_presenter.stub!(:iterations?).and_return(false)
+      @stories_presenter.stub!(:tags?).and_return(true)
+      template.expect_render(:partial =&gt; &quot;stories/tags&quot;, :locals =&gt; {:tags=&gt;@tags}).and_return(%|&lt;p id=&quot;tags-partial&quot; /&gt;|)
+    end
+    
+    it &quot;renders the stories/tags partial&quot; do
+      render_it
+      response.should have_tag(&quot;#tags-partial&quot;)
+    end
+  end
+  
 end
 </diff>
      <filename>spec/views/stories/index.html.erb_spec.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,4 +1,3 @@
 require File.dirname(__FILE__) + '/lib/acts_as_taggable'
-
 require File.dirname(__FILE__) + '/lib/tagging'
 require File.dirname(__FILE__) + '/lib/tag'</diff>
      <filename>vendor/plugins/acts_as_taggable_on_steroids/init.rb</filename>
    </modified>
    <modified>
      <diff>@@ -1,5 +1,9 @@
 class Tag &lt; ActiveRecord::Base
   has_many :taggings
+  # extend the existing Tag class
+  # Tag.class_eval do
+    has_many_polymorphs :taggables, :from =&gt; [:stories], :through =&gt; :taggings
+  # end
   
   def self.parse(list)
     tags = []</diff>
      <filename>vendor/plugins/acts_as_taggable_on_steroids/lib/tag.rb</filename>
    </modified>
  </modified>
  <removed type="array"/>
  <parents type="array">
    <parent>
      <id>c6ce48df1811e3ef65cc5ae67d1f934eb03d158a</id>
    </parent>
  </parents>
  <author>
    <name>zdennis</name>
    <email>zdennis@b1a0fcd8-281e-0410-b946-bf040eef99c3</email>
  </author>
  <url>http://github.com/zdennis/strac/commit/7b9decbbe06a5f01d58f1ebcb824c33ca6c433d4</url>
  <id>7b9decbbe06a5f01d58f1ebcb824c33ca6c433d4</id>
  <committed-date>2007-12-13T20:48:59-08:00</committed-date>
  <authored-date>2007-12-13T20:48:59-08:00</authored-date>
  <message>[BROKEN COMMIT] This starts the implementation of a tag-based view for stories. It is functional, but not complete so some stories regarding the tag based view will die. This further extracts out another layer of presenters which is keeping things really simple.

git-svn-id: http://rails.lotswholetime.com/svn/strac/trunk@720 b1a0fcd8-281e-0410-b946-bf040eef99c3</message>
  <tree>6125d3fdc20c43c97c95feac0dbb7eeccb92bc6c</tree>
  <committer>
    <name>zdennis</name>
    <email>zdennis@b1a0fcd8-281e-0410-b946-bf040eef99c3</email>
  </committer>
</commit>
