peaty 0.3.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 +24 -0
- data/Gemfile.lock +62 -0
- data/Rakefile +55 -0
- data/Readme.textile +67 -0
- data/VERSION +1 -0
- data/lib/peaty/base.rb +104 -0
- data/lib/peaty/integration.rb +37 -0
- data/lib/peaty/iteration.rb +25 -0
- data/lib/peaty/project.rb +47 -0
- data/lib/peaty/proxy.rb +29 -0
- data/lib/peaty/story.rb +39 -0
- data/lib/peaty/user.rb +15 -0
- data/lib/peaty.rb +33 -0
- data/peaty.gemspec +126 -0
- data/test/.gitignore +1 -0
- data/test/fixtures/bugs.xml +15 -0
- data/test/fixtures/chores.xml +15 -0
- data/test/fixtures/features.xml +120 -0
- data/test/fixtures/iterations.xml +197 -0
- data/test/fixtures/iterations_done.xml +25 -0
- data/test/fixtures/project.xml +42 -0
- data/test/fixtures/projects.xml +35 -0
- data/test/fixtures/release.xml +13 -0
- data/test/fixtures/releases.xml +31 -0
- data/test/fixtures/stories.xml +156 -0
- data/test/fixtures/stories_with_done.xml +186 -0
- data/test/fixtures/story.xml +14 -0
- data/test/peaty_test.rb +90 -0
- data/test/test_helper.rb +38 -0
- metadata +402 -0
    
        data/Gemfile
    ADDED
    
    | @@ -0,0 +1,24 @@ | |
| 1 | 
            +
            source "http://rubygems.org"
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            gem 'activesupport', '~> 3.0.1'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            gem 'nokogiri'
         | 
| 6 | 
            +
            gem 'nokogiri-happymapper'
         | 
| 7 | 
            +
             | 
| 8 | 
            +
            gem 'rest-client'
         | 
| 9 | 
            +
            gem 'xml_to_json', '0.0.1'
         | 
| 10 | 
            +
            gem 'yajl-ruby'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            group :development do
         | 
| 13 | 
            +
              gem 'yajl-ruby'
         | 
| 14 | 
            +
              gem 'builder'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
              gem "rspec", "2.1.0"
         | 
| 17 | 
            +
              gem "bundler", "~> 1.0.0"
         | 
| 18 | 
            +
              gem "jeweler", "~> 1.5.0.pre6"
         | 
| 19 | 
            +
              gem "rails_code_qa", ">= 0"
         | 
| 20 | 
            +
            end
         | 
| 21 | 
            +
             | 
| 22 | 
            +
            group :test do
         | 
| 23 | 
            +
              gem "fakeweb", "1.3.0"
         | 
| 24 | 
            +
            end
         | 
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,62 @@ | |
| 1 | 
            +
            GEM
         | 
| 2 | 
            +
              remote: http://rubygems.org/
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                activesupport (3.0.1)
         | 
| 5 | 
            +
                builder (3.0.0)
         | 
| 6 | 
            +
                diff-lcs (1.1.2)
         | 
| 7 | 
            +
                fakeweb (1.3.0)
         | 
| 8 | 
            +
                flay (1.4.1)
         | 
| 9 | 
            +
                  ruby_parser (~> 2.0)
         | 
| 10 | 
            +
                  sexp_processor (~> 3.0)
         | 
| 11 | 
            +
                flog (2.5.0)
         | 
| 12 | 
            +
                  ruby_parser (~> 2.0)
         | 
| 13 | 
            +
                  sexp_processor (~> 3.0)
         | 
| 14 | 
            +
                git (1.2.5)
         | 
| 15 | 
            +
                jeweler (1.5.1)
         | 
| 16 | 
            +
                  bundler (~> 1.0.0)
         | 
| 17 | 
            +
                  git (>= 1.2.5)
         | 
| 18 | 
            +
                  rake
         | 
| 19 | 
            +
                mime-types (1.16)
         | 
| 20 | 
            +
                nokogiri (1.4.3.1)
         | 
| 21 | 
            +
                nokogiri-happymapper (0.3.4)
         | 
| 22 | 
            +
                  nokogiri (>= 1.4.0)
         | 
| 23 | 
            +
                rails_code_qa (0.4.1)
         | 
| 24 | 
            +
                  flay (= 1.4.1)
         | 
| 25 | 
            +
                  flog (= 2.5.0)
         | 
| 26 | 
            +
                  rcov (= 0.9.9)
         | 
| 27 | 
            +
                rake (0.8.7)
         | 
| 28 | 
            +
                rcov (0.9.9)
         | 
| 29 | 
            +
                rest-client (1.6.1)
         | 
| 30 | 
            +
                  mime-types (>= 1.16)
         | 
| 31 | 
            +
                rspec (2.1.0)
         | 
| 32 | 
            +
                  rspec-core (~> 2.1.0)
         | 
| 33 | 
            +
                  rspec-expectations (~> 2.1.0)
         | 
| 34 | 
            +
                  rspec-mocks (~> 2.1.0)
         | 
| 35 | 
            +
                rspec-core (2.1.0)
         | 
| 36 | 
            +
                rspec-expectations (2.1.0)
         | 
| 37 | 
            +
                  diff-lcs (~> 1.1.2)
         | 
| 38 | 
            +
                rspec-mocks (2.1.0)
         | 
| 39 | 
            +
                ruby_parser (2.0.5)
         | 
| 40 | 
            +
                  sexp_processor (~> 3.0)
         | 
| 41 | 
            +
                sexp_processor (3.0.5)
         | 
| 42 | 
            +
                xml_to_json (0.0.1)
         | 
| 43 | 
            +
                  nokogiri
         | 
| 44 | 
            +
                  nokogiri (= 1.4.3.1)
         | 
| 45 | 
            +
                yajl-ruby (0.7.8)
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            PLATFORMS
         | 
| 48 | 
            +
              ruby
         | 
| 49 | 
            +
             | 
| 50 | 
            +
            DEPENDENCIES
         | 
| 51 | 
            +
              activesupport (~> 3.0.1)
         | 
| 52 | 
            +
              builder
         | 
| 53 | 
            +
              bundler (~> 1.0.0)
         | 
| 54 | 
            +
              fakeweb (= 1.3.0)
         | 
| 55 | 
            +
              jeweler (~> 1.5.0.pre6)
         | 
| 56 | 
            +
              nokogiri
         | 
| 57 | 
            +
              nokogiri-happymapper
         | 
| 58 | 
            +
              rails_code_qa
         | 
| 59 | 
            +
              rest-client
         | 
| 60 | 
            +
              rspec (= 2.1.0)
         | 
| 61 | 
            +
              xml_to_json (= 0.0.1)
         | 
| 62 | 
            +
              yajl-ruby
         | 
    
        data/Rakefile
    ADDED
    
    | @@ -0,0 +1,55 @@ | |
| 1 | 
            +
            require 'rubygems'
         | 
| 2 | 
            +
            require 'bundler'
         | 
| 3 | 
            +
            begin
         | 
| 4 | 
            +
              Bundler.setup(:default, :development)
         | 
| 5 | 
            +
            rescue Bundler::BundlerError => e
         | 
| 6 | 
            +
              $stderr.puts e.message
         | 
| 7 | 
            +
              $stderr.puts "Run `bundle install` to install missing gems"
         | 
| 8 | 
            +
              exit e.status_code
         | 
| 9 | 
            +
            end
         | 
| 10 | 
            +
            require 'rake'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
            require 'jeweler'
         | 
| 13 | 
            +
            Jeweler::Tasks.new do |gem|
         | 
| 14 | 
            +
              # gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
         | 
| 15 | 
            +
              gem.name = "peaty"
         | 
| 16 | 
            +
              gem.homepage = "http://github.com/mtodd/peaty"
         | 
| 17 | 
            +
              gem.license = "MIT"
         | 
| 18 | 
            +
              gem.summary = %Q{Pivotal Tracker API Implementation}
         | 
| 19 | 
            +
              gem.description = %Q{Just another Pivotal Tracker API Implementation}
         | 
| 20 | 
            +
              gem.email = "chiology@gmail.com"
         | 
| 21 | 
            +
              gem.authors = ["Matt Todd"]
         | 
| 22 | 
            +
              
         | 
| 23 | 
            +
              gem.add_runtime_dependency 'nokogiri', '1.4.3.1'
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
              gem.add_development_dependency 'yajl-ruby', '0.7.8'
         | 
| 26 | 
            +
              gem.add_development_dependency 'activesupport', '~> 3.0.1'
         | 
| 27 | 
            +
              gem.add_development_dependency 'builder', '2.1.2'
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              gem.add_development_dependency 'rspec', '2.1.0'
         | 
| 30 | 
            +
              gem.add_development_dependency 'bundler', '~> 1.0.0'
         | 
| 31 | 
            +
              gem.add_development_dependency 'jeweler', '~> 1.5.0.pre6'
         | 
| 32 | 
            +
              gem.add_development_dependency 'rails_code_qa', '>= 0'
         | 
| 33 | 
            +
            end
         | 
| 34 | 
            +
            Jeweler::RubygemsDotOrgTasks.new
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            require 'rake/testtask'
         | 
| 37 | 
            +
             | 
| 38 | 
            +
            Rake::TestTask.new("test") do |t|
         | 
| 39 | 
            +
              t.libs << "test"
         | 
| 40 | 
            +
              t.pattern = 'test/*_test.rb'
         | 
| 41 | 
            +
              t.verbose = true
         | 
| 42 | 
            +
              t.warning = true
         | 
| 43 | 
            +
            end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            task :default => :test
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            require 'rake/rdoctask'
         | 
| 48 | 
            +
            Rake::RDocTask.new do |rdoc|
         | 
| 49 | 
            +
              version = File.exist?('VERSION') ? File.read('VERSION') : ""
         | 
| 50 | 
            +
             | 
| 51 | 
            +
              rdoc.rdoc_dir = 'rdoc'
         | 
| 52 | 
            +
              rdoc.title = "xml_to_json #{version}"
         | 
| 53 | 
            +
              rdoc.rdoc_files.include('README*')
         | 
| 54 | 
            +
              rdoc.rdoc_files.include('lib/**/*.rb')
         | 
| 55 | 
            +
            end
         | 
    
        data/Readme.textile
    ADDED
    
    | @@ -0,0 +1,67 @@ | |
| 1 | 
            +
            h1. Peaty
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            Peaty (PT, 'pee-tee'): A PivotalTracker API Client
         | 
| 4 | 
            +
             | 
| 5 | 
            +
            h2. Usage
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            NOTE: This is not live and only reference while development is still early.
         | 
| 8 | 
            +
             | 
| 9 | 
            +
            <pre>
         | 
| 10 | 
            +
            class User < ActiveRecord::Base
         | 
| 11 | 
            +
              pivotal_tracker_for :pivotal_tracker_api_key, :method_prefix => :pt, :table_prefix => :pt
         | 
| 12 | 
            +
            end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
            u = User.first
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            team = []
         | 
| 17 | 
            +
            releases = []
         | 
| 18 | 
            +
             | 
| 19 | 
            +
            u.pt_projects.each do |project|
         | 
| 20 | 
            +
              project.stories.all
         | 
| 21 | 
            +
              project.releases.all
         | 
| 22 | 
            +
              project.stories(:type => :release)
         | 
| 23 | 
            +
              
         | 
| 24 | 
            +
              # add team members to team list
         | 
| 25 | 
            +
              team.concat project.users # but ensure uniqueness later
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              # collect our releases
         | 
| 28 | 
            +
              releases.concat project.releases
         | 
| 29 | 
            +
            end
         | 
| 30 | 
            +
            </pre>
         | 
| 31 | 
            +
             | 
| 32 | 
            +
            See how current API works for selecting types of stories (chores, bugs, releases, and features)
         | 
| 33 | 
            +
             | 
| 34 | 
            +
            h2. Contributing
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            Step 1: Submit a failing test.
         | 
| 37 | 
            +
            Step 2: ???
         | 
| 38 | 
            +
            Step 3: Profit.
         | 
| 39 | 
            +
             | 
| 40 | 
            +
            h2. Other PivotalTracker RubyGems
         | 
| 41 | 
            +
             | 
| 42 | 
            +
            * https://github.com/joslynesser/pivotal_tracker
         | 
| 43 | 
            +
            * https://github.com/jsmestad/pivotal-tracker
         | 
| 44 | 
            +
             | 
| 45 | 
            +
            h2. License
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            The MIT License
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            Copyright (c) 2010 Matt Todd, Highgroove Studios.
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            Permission is hereby granted, free of charge, to any person obtaining a copy
         | 
| 52 | 
            +
            of this software and associated documentation files (the "Software"), to deal
         | 
| 53 | 
            +
            in the Software without restriction, including without limitation the rights
         | 
| 54 | 
            +
            to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
         | 
| 55 | 
            +
            copies of the Software, and to permit persons to whom the Software is
         | 
| 56 | 
            +
            furnished to do so, subject to the following conditions:
         | 
| 57 | 
            +
             | 
| 58 | 
            +
            The above copyright notice and this permission notice shall be included in
         | 
| 59 | 
            +
            all copies or substantial portions of the Software.
         | 
| 60 | 
            +
             | 
| 61 | 
            +
            THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
         | 
| 62 | 
            +
            IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
         | 
| 63 | 
            +
            FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
         | 
| 64 | 
            +
            AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
         | 
| 65 | 
            +
            LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
         | 
| 66 | 
            +
            OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
         | 
| 67 | 
            +
            THE SOFTWARE.
         | 
    
        data/VERSION
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            0.3.0
         | 
    
        data/lib/peaty/base.rb
    ADDED
    
    | @@ -0,0 +1,104 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              class Base
         | 
| 4 | 
            +
                attr_accessor :attributes, :connection
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                FILTERS = [
         | 
| 7 | 
            +
                  :id, :type, :state, :label, :has_attachment,
         | 
| 8 | 
            +
                  :created_since, :modified_since,
         | 
| 9 | 
            +
                  :requester, :owner,
         | 
| 10 | 
            +
                  :mywork,
         | 
| 11 | 
            +
                  :integration, :external_id, :has_external_id,
         | 
| 12 | 
            +
                  :includedone
         | 
| 13 | 
            +
                ]
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                def initialize(attrs)
         | 
| 16 | 
            +
                  raise ArgumentError unless attrs.is_a?(Hash)
         | 
| 17 | 
            +
                  @connection = self.class.connection
         | 
| 18 | 
            +
                  # if we get a hash like {"item"=>{...}}, pull out the attributes
         | 
| 19 | 
            +
                  @attributes = if attrs.key?(self.class.element);  attrs.dup.delete(self.class.element) 
         | 
| 20 | 
            +
                                else                                attrs.dup
         | 
| 21 | 
            +
                                end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                
         | 
| 24 | 
            +
                def method_missing(method, *args)
         | 
| 25 | 
            +
                  return self.attributes[method.to_s] if respond_to?(method)
         | 
| 26 | 
            +
                  super
         | 
| 27 | 
            +
                end
         | 
| 28 | 
            +
                def respond_to?(method)
         | 
| 29 | 
            +
                  super or self.attributes.key?(method.to_s)
         | 
| 30 | 
            +
                end
         | 
| 31 | 
            +
                
         | 
| 32 | 
            +
                def id
         | 
| 33 | 
            +
                  self.attributes["id"]
         | 
| 34 | 
            +
                end
         | 
| 35 | 
            +
                
         | 
| 36 | 
            +
                class << self
         | 
| 37 | 
            +
                  attr_accessor :connection
         | 
| 38 | 
            +
                  
         | 
| 39 | 
            +
                  def with_connection(connection)
         | 
| 40 | 
            +
                    @connection = connection
         | 
| 41 | 
            +
                    self # chaining
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                  
         | 
| 44 | 
            +
                  # Takes the XML result, transforms to JSON, parses to objects, and
         | 
| 45 | 
            +
                  # returns an array of results, regardless of one or many results.
         | 
| 46 | 
            +
                  def parse(response, element)
         | 
| 47 | 
            +
                    result = JSON.parse(XmlToJson.transform(response))
         | 
| 48 | 
            +
                    Array.wrap(result[element] || result[element.pluralize]).map{ |r| new(r) }
         | 
| 49 | 
            +
                  end
         | 
| 50 | 
            +
                  
         | 
| 51 | 
            +
                  def find(*args)
         | 
| 52 | 
            +
                    options = args.extract_options!
         | 
| 53 | 
            +
                    selection = args.shift
         | 
| 54 | 
            +
                    case selection
         | 
| 55 | 
            +
                    when :first;  self.first(options)
         | 
| 56 | 
            +
                    when :all;    self.all(options)
         | 
| 57 | 
            +
                    when Array;   selection.map{ |s| self.find_by_id(s, options) }
         | 
| 58 | 
            +
                    when Numeric; self.find_by_id(selection, options)
         | 
| 59 | 
            +
                    else          self.find_by_id(selection, options)
         | 
| 60 | 
            +
                    end
         | 
| 61 | 
            +
                  end
         | 
| 62 | 
            +
                  
         | 
| 63 | 
            +
                  def find_by_id(id, options = {})
         | 
| 64 | 
            +
                    self.parse(self.connection[self.member_path(id, options)].get(:params => self.filter_options(options)).body, self.element).
         | 
| 65 | 
            +
                      first.
         | 
| 66 | 
            +
                      tap{ |e| e.connection = self.connection }
         | 
| 67 | 
            +
                  end
         | 
| 68 | 
            +
                  
         | 
| 69 | 
            +
                  def all(options = {})
         | 
| 70 | 
            +
                    self.parse(self.connection[self.collection_path(options)].get(:params => self.filter_options(options)).body, self.element).
         | 
| 71 | 
            +
                      each { |e| e.connection = self.connection }
         | 
| 72 | 
            +
                  end
         | 
| 73 | 
            +
                  
         | 
| 74 | 
            +
                  def first(options = {})
         | 
| 75 | 
            +
                    self.all(options).first
         | 
| 76 | 
            +
                  end
         | 
| 77 | 
            +
                  
         | 
| 78 | 
            +
                  def filter_options(options = {}, filter = [])
         | 
| 79 | 
            +
                    options = options.dup # make sure we're working on a copy
         | 
| 80 | 
            +
                    # and delete any keys not supported for queries
         | 
| 81 | 
            +
                    options.each { |(k,_)| options.delete(k) unless FILTERS.include?(k.to_sym) }
         | 
| 82 | 
            +
                    
         | 
| 83 | 
            +
                    FILTERS.each do |term|
         | 
| 84 | 
            +
                      value = Array.wrap(options.delete(term))
         | 
| 85 | 
            +
                      filter << "%s:%s" % [ term,
         | 
| 86 | 
            +
                                            value.map do |v|
         | 
| 87 | 
            +
                                              v = %("%s") % v if v.to_s =~ /\s/
         | 
| 88 | 
            +
                                              v
         | 
| 89 | 
            +
                                            end.join(',') ] unless value.empty?
         | 
| 90 | 
            +
                    end
         | 
| 91 | 
            +
                    
         | 
| 92 | 
            +
                    # handle the rest of the filter strings
         | 
| 93 | 
            +
                    Array.wrap(options.delete(:rest)).each do |value|
         | 
| 94 | 
            +
                      value = %("%s") % value if value.to_s =~ /\s/
         | 
| 95 | 
            +
                      filter << value
         | 
| 96 | 
            +
                    end
         | 
| 97 | 
            +
                    
         | 
| 98 | 
            +
                    return options if filter.empty?
         | 
| 99 | 
            +
                    options.merge(:filter => filter.join(" "))
         | 
| 100 | 
            +
                  end
         | 
| 101 | 
            +
                end
         | 
| 102 | 
            +
              end
         | 
| 103 | 
            +
              
         | 
| 104 | 
            +
            end
         | 
| @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              module Integration
         | 
| 4 | 
            +
                extend ActiveSupport::Concern
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                included do
         | 
| 7 | 
            +
                  self.__pivotal_tracker_options.tap do |opts|
         | 
| 8 | 
            +
                    alias_method [opts[:method_prefix], :projects].compact.map(&:to_s).join('_').to_sym, :__pivotal_tracker_projects
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                
         | 
| 12 | 
            +
                module InstanceMethods
         | 
| 13 | 
            +
                  def __pivotal_tracker_connection
         | 
| 14 | 
            +
                    @__pivotal_tracker_connection ||= begin
         | 
| 15 | 
            +
                      RestClient.log ||= STDOUT
         | 
| 16 | 
            +
                      RestClient::Resource.new("http://www.pivotaltracker.com/services/v3", :headers => {"X-TrackerToken" => self.send(self.class.__pivotal_tracker_options[:attribute])})
         | 
| 17 | 
            +
                    end
         | 
| 18 | 
            +
                  end
         | 
| 19 | 
            +
                  def __pivotal_tracker_projects
         | 
| 20 | 
            +
                    Proxy.new(Project, self.__pivotal_tracker_connection, :user => self)
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
            end
         | 
| 26 | 
            +
             | 
| 27 | 
            +
            class Object
         | 
| 28 | 
            +
              def self.pivotal_tracker_for(attribute, options = {})
         | 
| 29 | 
            +
                options = options.with_indifferent_access
         | 
| 30 | 
            +
                options.reverse_merge!( :attribute => attribute,
         | 
| 31 | 
            +
                                        :method_prefix => :pivotal_tracker )
         | 
| 32 | 
            +
                
         | 
| 33 | 
            +
                class << self; attr_accessor :__pivotal_tracker_options; end
         | 
| 34 | 
            +
                self.__pivotal_tracker_options = options
         | 
| 35 | 
            +
                self.send(:include, Peaty::Integration)
         | 
| 36 | 
            +
              end
         | 
| 37 | 
            +
            end
         | 
| @@ -0,0 +1,25 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              class Iteration < Base
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                def stories(options = {})
         | 
| 6 | 
            +
                  Array.wrap(self.attributes["stories"]).map do |story|
         | 
| 7 | 
            +
                    Story.with_connection(self.connection).new(story)
         | 
| 8 | 
            +
                  end
         | 
| 9 | 
            +
                end
         | 
| 10 | 
            +
                
         | 
| 11 | 
            +
                class << self
         | 
| 12 | 
            +
                  def element
         | 
| 13 | 
            +
                    "iteration"
         | 
| 14 | 
            +
                  end
         | 
| 15 | 
            +
                  def collection_path(options = {})
         | 
| 16 | 
            +
                    "/projects/%i/iterations" % options[:project_id].to_i
         | 
| 17 | 
            +
                  end
         | 
| 18 | 
            +
                  def member_path(group, options = {})
         | 
| 19 | 
            +
                    "/projects/%i/iterations/%s" % [options[:project_id].to_i, group]
         | 
| 20 | 
            +
                  end
         | 
| 21 | 
            +
                end
         | 
| 22 | 
            +
                
         | 
| 23 | 
            +
              end
         | 
| 24 | 
            +
              
         | 
| 25 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              class Project < Base
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                def users(options = {})
         | 
| 6 | 
            +
                  Array.wrap(self.memberships).map do |membership|
         | 
| 7 | 
            +
                    membership = membership["membership"] if membership.key?("membership")
         | 
| 8 | 
            +
                    User.with_connection(self.connection).new(membership["person"])
         | 
| 9 | 
            +
                  end
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
                
         | 
| 12 | 
            +
                def stories(options = {})
         | 
| 13 | 
            +
                  Proxy.new(Story, self.class.connection, options.merge(:project_id => self.id))
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
                
         | 
| 16 | 
            +
                def iterations(options = {})
         | 
| 17 | 
            +
                  Proxy.new(Iteration, self.class.connection, options.merge(:project_id => self.id))
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
                
         | 
| 20 | 
            +
                def features(options = {})
         | 
| 21 | 
            +
                  self.stories.filter(:type => :feature)
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
                def releases(options = {})
         | 
| 24 | 
            +
                  self.stories.filter(:type => :release)
         | 
| 25 | 
            +
                end
         | 
| 26 | 
            +
                def chores(options = {})
         | 
| 27 | 
            +
                  self.stories.filter(:type => :chore)
         | 
| 28 | 
            +
                end
         | 
| 29 | 
            +
                def bugs(options = {})
         | 
| 30 | 
            +
                  self.stories.filter(:type => :bug)
         | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
                
         | 
| 33 | 
            +
                class << self
         | 
| 34 | 
            +
                  def element
         | 
| 35 | 
            +
                    "project"
         | 
| 36 | 
            +
                  end
         | 
| 37 | 
            +
                  def collection_path(options = {})
         | 
| 38 | 
            +
                    "/projects"
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
                  def member_path(id, options = {})
         | 
| 41 | 
            +
                    "/projects/%i" % id
         | 
| 42 | 
            +
                  end
         | 
| 43 | 
            +
                end
         | 
| 44 | 
            +
                
         | 
| 45 | 
            +
              end
         | 
| 46 | 
            +
              
         | 
| 47 | 
            +
            end
         | 
    
        data/lib/peaty/proxy.rb
    ADDED
    
    | @@ -0,0 +1,29 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              class Proxy
         | 
| 4 | 
            +
                attr_accessor :target, :connection, :options
         | 
| 5 | 
            +
                
         | 
| 6 | 
            +
                def initialize(target, connection, options = {})
         | 
| 7 | 
            +
                  @target, @connection, @options = target, connection, options
         | 
| 8 | 
            +
                end
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                def method_missing(method, *args)
         | 
| 11 | 
            +
                  return @target.method(method).unbind.bind(self).call(*args) if @target.class.respond_to?(method)
         | 
| 12 | 
            +
                  options = args.extract_options!
         | 
| 13 | 
            +
                  args << @options.merge(options)
         | 
| 14 | 
            +
                  @target.with_connection(@connection).send(method, *args)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
                
         | 
| 17 | 
            +
                def filter(*args)
         | 
| 18 | 
            +
                  options = args.extract_options!
         | 
| 19 | 
            +
                  options.each do |(key, value)|
         | 
| 20 | 
            +
                    @options[key] = Array.wrap(@options.delete(:key)).concat(Array.wrap(value))
         | 
| 21 | 
            +
                  end
         | 
| 22 | 
            +
                  
         | 
| 23 | 
            +
                  @options[:rest] = Array.wrap(@options.delete(:rest)).concat(args)
         | 
| 24 | 
            +
                  
         | 
| 25 | 
            +
                  self
         | 
| 26 | 
            +
                end
         | 
| 27 | 
            +
              end
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
            end
         | 
    
        data/lib/peaty/story.rb
    ADDED
    
    | @@ -0,0 +1,39 @@ | |
| 1 | 
            +
            module Peaty
         | 
| 2 | 
            +
              
         | 
| 3 | 
            +
              class Story < Base
         | 
| 4 | 
            +
                
         | 
| 5 | 
            +
                def story_type
         | 
| 6 | 
            +
                  self.attributes["story_type"].to_sym
         | 
| 7 | 
            +
                end
         | 
| 8 | 
            +
                alias type story_type
         | 
| 9 | 
            +
                
         | 
| 10 | 
            +
                # chores, bugs, releases may or may not have estimates
         | 
| 11 | 
            +
                def estimate
         | 
| 12 | 
            +
                  self.attributes["estimate"].to_i
         | 
| 13 | 
            +
                end
         | 
| 14 | 
            +
                
         | 
| 15 | 
            +
                def project
         | 
| 16 | 
            +
                  Project.with_connection(self.class.connection).find(self.project_id)
         | 
| 17 | 
            +
                end
         | 
| 18 | 
            +
                
         | 
| 19 | 
            +
                class << self
         | 
| 20 | 
            +
                  def element
         | 
| 21 | 
            +
                    "story"
         | 
| 22 | 
            +
                  end
         | 
| 23 | 
            +
                  def collection_path(options = {})
         | 
| 24 | 
            +
                    "/projects/%i/stories" % options[:project_id].to_i
         | 
| 25 | 
            +
                  end
         | 
| 26 | 
            +
                  def member_path(id, options = {})
         | 
| 27 | 
            +
                    "/projects/%i/stories/%i" % [options[:project_id].to_i, id]
         | 
| 28 | 
            +
                  end
         | 
| 29 | 
            +
                  
         | 
| 30 | 
            +
                  ### Filters
         | 
| 31 | 
            +
                  
         | 
| 32 | 
            +
                  def releases(options = {})
         | 
| 33 | 
            +
                    self.filter(:type => :release)
         | 
| 34 | 
            +
                  end
         | 
| 35 | 
            +
                end
         | 
| 36 | 
            +
                
         | 
| 37 | 
            +
              end
         | 
| 38 | 
            +
              
         | 
| 39 | 
            +
            end
         | 
    
        data/lib/peaty/user.rb
    ADDED
    
    
    
        data/lib/peaty.rb
    ADDED
    
    | @@ -0,0 +1,33 @@ | |
| 1 | 
            +
            require 'logger'
         | 
| 2 | 
            +
             | 
| 3 | 
            +
            require 'active_support/concern'
         | 
| 4 | 
            +
            require 'active_support/inflector'
         | 
| 5 | 
            +
            require 'active_support/core_ext/benchmark'
         | 
| 6 | 
            +
            require 'active_support/core_ext/array/extract_options'
         | 
| 7 | 
            +
            require 'active_support/core_ext/array/wrap'
         | 
| 8 | 
            +
            require 'active_support/core_ext/hash/indifferent_access'
         | 
| 9 | 
            +
            require 'active_support/core_ext/hash/reverse_merge'
         | 
| 10 | 
            +
             | 
| 11 | 
            +
            require 'rest-client'
         | 
| 12 | 
            +
            require 'nokogiri'
         | 
| 13 | 
            +
            require 'xml_to_json'
         | 
| 14 | 
            +
            require 'yajl/json_gem'
         | 
| 15 | 
            +
             | 
| 16 | 
            +
            $:.unshift Pathname.new(__FILE__).dirname
         | 
| 17 | 
            +
            require 'peaty/integration'
         | 
| 18 | 
            +
            require 'peaty/proxy'
         | 
| 19 | 
            +
            require 'peaty/base'
         | 
| 20 | 
            +
            require 'peaty/project'
         | 
| 21 | 
            +
            require 'peaty/iteration'
         | 
| 22 | 
            +
            require 'peaty/story'
         | 
| 23 | 
            +
            require 'peaty/user'
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            module Peaty
         | 
| 26 | 
            +
              
         | 
| 27 | 
            +
              VERSION = "0.0.0"
         | 
| 28 | 
            +
              
         | 
| 29 | 
            +
              def self.root
         | 
| 30 | 
            +
                @root ||= Pathname.new(__FILE__).dirname.parent
         | 
| 31 | 
            +
              end
         | 
| 32 | 
            +
              
         | 
| 33 | 
            +
            end
         | 
    
        data/peaty.gemspec
    ADDED
    
    | @@ -0,0 +1,126 @@ | |
| 1 | 
            +
            # Generated by jeweler
         | 
| 2 | 
            +
            # DO NOT EDIT THIS FILE DIRECTLY
         | 
| 3 | 
            +
            # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
         | 
| 4 | 
            +
            # -*- encoding: utf-8 -*-
         | 
| 5 | 
            +
             | 
| 6 | 
            +
            Gem::Specification.new do |s|
         | 
| 7 | 
            +
              s.name = %q{peaty}
         | 
| 8 | 
            +
              s.version = "0.3.0"
         | 
| 9 | 
            +
             | 
| 10 | 
            +
              s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
         | 
| 11 | 
            +
              s.authors = ["Matt Todd"]
         | 
| 12 | 
            +
              s.date = %q{2010-12-01}
         | 
| 13 | 
            +
              s.description = %q{Just another Pivotal Tracker API Implementation}
         | 
| 14 | 
            +
              s.email = %q{chiology@gmail.com}
         | 
| 15 | 
            +
              s.files = [
         | 
| 16 | 
            +
                "Gemfile",
         | 
| 17 | 
            +
                "Gemfile.lock",
         | 
| 18 | 
            +
                "Rakefile",
         | 
| 19 | 
            +
                "Readme.textile",
         | 
| 20 | 
            +
                "VERSION",
         | 
| 21 | 
            +
                "lib/peaty.rb",
         | 
| 22 | 
            +
                "lib/peaty/base.rb",
         | 
| 23 | 
            +
                "lib/peaty/integration.rb",
         | 
| 24 | 
            +
                "lib/peaty/iteration.rb",
         | 
| 25 | 
            +
                "lib/peaty/project.rb",
         | 
| 26 | 
            +
                "lib/peaty/proxy.rb",
         | 
| 27 | 
            +
                "lib/peaty/story.rb",
         | 
| 28 | 
            +
                "lib/peaty/user.rb",
         | 
| 29 | 
            +
                "peaty.gemspec",
         | 
| 30 | 
            +
                "test/.gitignore",
         | 
| 31 | 
            +
                "test/fixtures/bugs.xml",
         | 
| 32 | 
            +
                "test/fixtures/chores.xml",
         | 
| 33 | 
            +
                "test/fixtures/features.xml",
         | 
| 34 | 
            +
                "test/fixtures/iterations.xml",
         | 
| 35 | 
            +
                "test/fixtures/iterations_done.xml",
         | 
| 36 | 
            +
                "test/fixtures/project.xml",
         | 
| 37 | 
            +
                "test/fixtures/projects.xml",
         | 
| 38 | 
            +
                "test/fixtures/release.xml",
         | 
| 39 | 
            +
                "test/fixtures/releases.xml",
         | 
| 40 | 
            +
                "test/fixtures/stories.xml",
         | 
| 41 | 
            +
                "test/fixtures/stories_with_done.xml",
         | 
| 42 | 
            +
                "test/fixtures/story.xml",
         | 
| 43 | 
            +
                "test/peaty_test.rb",
         | 
| 44 | 
            +
                "test/test_helper.rb"
         | 
| 45 | 
            +
              ]
         | 
| 46 | 
            +
              s.homepage = %q{http://github.com/mtodd/peaty}
         | 
| 47 | 
            +
              s.licenses = ["MIT"]
         | 
| 48 | 
            +
              s.require_paths = ["lib"]
         | 
| 49 | 
            +
              s.rubygems_version = %q{1.3.7}
         | 
| 50 | 
            +
              s.summary = %q{Pivotal Tracker API Implementation}
         | 
| 51 | 
            +
              s.test_files = [
         | 
| 52 | 
            +
                "test/peaty_test.rb",
         | 
| 53 | 
            +
                "test/test_helper.rb"
         | 
| 54 | 
            +
              ]
         | 
| 55 | 
            +
             | 
| 56 | 
            +
              if s.respond_to? :specification_version then
         | 
| 57 | 
            +
                current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
         | 
| 58 | 
            +
                s.specification_version = 3
         | 
| 59 | 
            +
             | 
| 60 | 
            +
                if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
         | 
| 61 | 
            +
                  s.add_runtime_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 62 | 
            +
                  s.add_runtime_dependency(%q<nokogiri>, [">= 0"])
         | 
| 63 | 
            +
                  s.add_runtime_dependency(%q<nokogiri-happymapper>, [">= 0"])
         | 
| 64 | 
            +
                  s.add_runtime_dependency(%q<rest-client>, [">= 0"])
         | 
| 65 | 
            +
                  s.add_runtime_dependency(%q<xml_to_json>, ["= 0.0.1"])
         | 
| 66 | 
            +
                  s.add_runtime_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 67 | 
            +
                  s.add_development_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 68 | 
            +
                  s.add_development_dependency(%q<builder>, [">= 0"])
         | 
| 69 | 
            +
                  s.add_development_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 70 | 
            +
                  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 71 | 
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 72 | 
            +
                  s.add_development_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 73 | 
            +
                  s.add_runtime_dependency(%q<nokogiri>, ["= 1.4.3.1"])
         | 
| 74 | 
            +
                  s.add_development_dependency(%q<yajl-ruby>, ["= 0.7.8"])
         | 
| 75 | 
            +
                  s.add_development_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 76 | 
            +
                  s.add_development_dependency(%q<builder>, ["= 2.1.2"])
         | 
| 77 | 
            +
                  s.add_development_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 78 | 
            +
                  s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 79 | 
            +
                  s.add_development_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 80 | 
            +
                  s.add_development_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 81 | 
            +
                else
         | 
| 82 | 
            +
                  s.add_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 83 | 
            +
                  s.add_dependency(%q<nokogiri>, [">= 0"])
         | 
| 84 | 
            +
                  s.add_dependency(%q<nokogiri-happymapper>, [">= 0"])
         | 
| 85 | 
            +
                  s.add_dependency(%q<rest-client>, [">= 0"])
         | 
| 86 | 
            +
                  s.add_dependency(%q<xml_to_json>, ["= 0.0.1"])
         | 
| 87 | 
            +
                  s.add_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 88 | 
            +
                  s.add_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 89 | 
            +
                  s.add_dependency(%q<builder>, [">= 0"])
         | 
| 90 | 
            +
                  s.add_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 91 | 
            +
                  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 92 | 
            +
                  s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 93 | 
            +
                  s.add_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 94 | 
            +
                  s.add_dependency(%q<nokogiri>, ["= 1.4.3.1"])
         | 
| 95 | 
            +
                  s.add_dependency(%q<yajl-ruby>, ["= 0.7.8"])
         | 
| 96 | 
            +
                  s.add_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 97 | 
            +
                  s.add_dependency(%q<builder>, ["= 2.1.2"])
         | 
| 98 | 
            +
                  s.add_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 99 | 
            +
                  s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 100 | 
            +
                  s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 101 | 
            +
                  s.add_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 102 | 
            +
                end
         | 
| 103 | 
            +
              else
         | 
| 104 | 
            +
                s.add_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 105 | 
            +
                s.add_dependency(%q<nokogiri>, [">= 0"])
         | 
| 106 | 
            +
                s.add_dependency(%q<nokogiri-happymapper>, [">= 0"])
         | 
| 107 | 
            +
                s.add_dependency(%q<rest-client>, [">= 0"])
         | 
| 108 | 
            +
                s.add_dependency(%q<xml_to_json>, ["= 0.0.1"])
         | 
| 109 | 
            +
                s.add_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 110 | 
            +
                s.add_dependency(%q<yajl-ruby>, [">= 0"])
         | 
| 111 | 
            +
                s.add_dependency(%q<builder>, [">= 0"])
         | 
| 112 | 
            +
                s.add_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 113 | 
            +
                s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 114 | 
            +
                s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 115 | 
            +
                s.add_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 116 | 
            +
                s.add_dependency(%q<nokogiri>, ["= 1.4.3.1"])
         | 
| 117 | 
            +
                s.add_dependency(%q<yajl-ruby>, ["= 0.7.8"])
         | 
| 118 | 
            +
                s.add_dependency(%q<activesupport>, ["~> 3.0.1"])
         | 
| 119 | 
            +
                s.add_dependency(%q<builder>, ["= 2.1.2"])
         | 
| 120 | 
            +
                s.add_dependency(%q<rspec>, ["= 2.1.0"])
         | 
| 121 | 
            +
                s.add_dependency(%q<bundler>, ["~> 1.0.0"])
         | 
| 122 | 
            +
                s.add_dependency(%q<jeweler>, ["~> 1.5.0.pre6"])
         | 
| 123 | 
            +
                s.add_dependency(%q<rails_code_qa>, [">= 0"])
         | 
| 124 | 
            +
              end
         | 
| 125 | 
            +
            end
         | 
| 126 | 
            +
             | 
    
        data/test/.gitignore
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            *.log
         |