gyunyu 0.1.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/.document +5 -0
 - data/.rspec +1 -0
 - data/Gemfile +26 -0
 - data/LICENSE.txt +20 -0
 - data/README.rdoc +35 -0
 - data/Rakefile +46 -0
 - data/VERSION +1 -0
 - data/bin/gyunyu +11 -0
 - data/gyunyu.gemspec +92 -0
 - data/lib/gyunyu.rb +9 -0
 - data/lib/gyunyu/app.rb +4 -0
 - data/lib/gyunyu/command.rb +21 -0
 - data/lib/gyunyu/command/export/app.rb +150 -0
 - data/lib/gyunyu/command/export/format/csv.rb +27 -0
 - data/lib/gyunyu/command/export/format/json.rb +16 -0
 - data/lib/gyunyu/command/export/format/yaml.rb +16 -0
 - data/lib/gyunyu/command/export/option.rb +63 -0
 - data/lib/gyunyu/expander.rb +40 -0
 - data/lib/gyunyu/token.rb +89 -0
 - data/spec/app/.gitkeep +0 -0
 - data/spec/app/command/export/option_spec.rb +137 -0
 - data/spec/app/command_spec.rb +62 -0
 - data/spec/app/expander_spec.rb +140 -0
 - data/spec/spec_helper.rb +12 -0
 - data/spec/token/token_spec.rb +87 -0
 - data/tasks/git.rake +7 -0
 - data/tasks/spec.rake +11 -0
 - data/tmp/.gitkeep +0 -0
 - metadata +178 -0
 
| 
         @@ -0,0 +1,63 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require 'optparse'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            module Gyunyu
         
     | 
| 
      
 5 
     | 
    
         
            +
              module Command
         
     | 
| 
      
 6 
     | 
    
         
            +
                module Export
         
     | 
| 
      
 7 
     | 
    
         
            +
                  class Option
         
     | 
| 
      
 8 
     | 
    
         
            +
                    class FormatNotFound < StandardError; end
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                    FIELD_SEP = ','
         
     | 
| 
      
 11 
     | 
    
         
            +
             
     | 
| 
      
 12 
     | 
    
         
            +
                    def initialize( argv = [] )
         
     | 
| 
      
 13 
     | 
    
         
            +
                      @lists  = []
         
     | 
| 
      
 14 
     | 
    
         
            +
                      @filter = nil
         
     | 
| 
      
 15 
     | 
    
         
            +
                      @fields = []
         
     | 
| 
      
 16 
     | 
    
         
            +
                      @format = :csv
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                      parser.parse( argv )
         
     | 
| 
      
 19 
     | 
    
         
            +
                    end
         
     | 
| 
      
 20 
     | 
    
         
            +
                    attr_reader :lists, :filter, :fields, :format
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                    def fields
         
     | 
| 
      
 23 
     | 
    
         
            +
                      if @fields.size > 0
         
     | 
| 
      
 24 
     | 
    
         
            +
                        @fields
         
     | 
| 
      
 25 
     | 
    
         
            +
                      else
         
     | 
| 
      
 26 
     | 
    
         
            +
                        %w( task_id name due )
         
     | 
| 
      
 27 
     | 
    
         
            +
                      end
         
     | 
| 
      
 28 
     | 
    
         
            +
                    end
         
     | 
| 
      
 29 
     | 
    
         
            +
             
     | 
| 
      
 30 
     | 
    
         
            +
                    def parser
         
     | 
| 
      
 31 
     | 
    
         
            +
                      OptionParser.new do |opt|
         
     | 
| 
      
 32 
     | 
    
         
            +
                        opt.on('-l', '--list LIST') { |list|
         
     | 
| 
      
 33 
     | 
    
         
            +
                          if !@lists.include?( list )
         
     | 
| 
      
 34 
     | 
    
         
            +
                            @lists << list
         
     | 
| 
      
 35 
     | 
    
         
            +
                          end
         
     | 
| 
      
 36 
     | 
    
         
            +
                        }
         
     | 
| 
      
 37 
     | 
    
         
            +
                        opt.on('-f', '--filter FILTER') { |filter|
         
     | 
| 
      
 38 
     | 
    
         
            +
                          @filter = filter if filter.size > 0
         
     | 
| 
      
 39 
     | 
    
         
            +
                        }
         
     | 
| 
      
 40 
     | 
    
         
            +
                        opt.on('-d', '--field FIELD') { |field|
         
     | 
| 
      
 41 
     | 
    
         
            +
                          if field.include?( FIELD_SEP )
         
     | 
| 
      
 42 
     | 
    
         
            +
                            @fields = field.split( FIELD_SEP )
         
     | 
| 
      
 43 
     | 
    
         
            +
                          elsif !@fields.include?( field )
         
     | 
| 
      
 44 
     | 
    
         
            +
                            @fields << field
         
     | 
| 
      
 45 
     | 
    
         
            +
                          end
         
     | 
| 
      
 46 
     | 
    
         
            +
                        }
         
     | 
| 
      
 47 
     | 
    
         
            +
                        opt.on('-o', '--format FORMAT') { |format|
         
     | 
| 
      
 48 
     | 
    
         
            +
                          format.downcase!
         
     | 
| 
      
 49 
     | 
    
         
            +
                          formats = Format.constants.map { |e|
         
     | 
| 
      
 50 
     | 
    
         
            +
                            e.to_s.downcase
         
     | 
| 
      
 51 
     | 
    
         
            +
                          }
         
     | 
| 
      
 52 
     | 
    
         
            +
                          if formats.include?( format )
         
     | 
| 
      
 53 
     | 
    
         
            +
                            @format = format
         
     | 
| 
      
 54 
     | 
    
         
            +
                          else
         
     | 
| 
      
 55 
     | 
    
         
            +
                            raise FormatNotFound
         
     | 
| 
      
 56 
     | 
    
         
            +
                          end
         
     | 
| 
      
 57 
     | 
    
         
            +
                        }
         
     | 
| 
      
 58 
     | 
    
         
            +
                      end
         
     | 
| 
      
 59 
     | 
    
         
            +
                    end
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
                end
         
     | 
| 
      
 62 
     | 
    
         
            +
              end
         
     | 
| 
      
 63 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,40 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            module Gyunyu
         
     | 
| 
      
 2 
     | 
    
         
            +
              module Expander
         
     | 
| 
      
 3 
     | 
    
         
            +
                class << self
         
     | 
| 
      
 4 
     | 
    
         
            +
                  #
         
     | 
| 
      
 5 
     | 
    
         
            +
                  # [param]  Array or Hash taskseries
         
     | 
| 
      
 6 
     | 
    
         
            +
                  # [return] Array
         
     | 
| 
      
 7 
     | 
    
         
            +
                  #
         
     | 
| 
      
 8 
     | 
    
         
            +
                  def taskseries( list )
         
     | 
| 
      
 9 
     | 
    
         
            +
                    expanded = []
         
     | 
| 
      
 10 
     | 
    
         
            +
             
     | 
| 
      
 11 
     | 
    
         
            +
                    if list.is_a?( Hash ) and list.has_key?( 'taskseries' )
         
     | 
| 
      
 12 
     | 
    
         
            +
                      list = list['taskseries']
         
     | 
| 
      
 13 
     | 
    
         
            +
                    end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                    list.each { |series|
         
     | 
| 
      
 16 
     | 
    
         
            +
                      expanded += tasks( series )
         
     | 
| 
      
 17 
     | 
    
         
            +
                    }
         
     | 
| 
      
 18 
     | 
    
         
            +
             
     | 
| 
      
 19 
     | 
    
         
            +
                    expanded
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
             
     | 
| 
      
 22 
     | 
    
         
            +
                  #
         
     | 
| 
      
 23 
     | 
    
         
            +
                  # [param]  Hash taskseries
         
     | 
| 
      
 24 
     | 
    
         
            +
                  # [return] Array
         
     | 
| 
      
 25 
     | 
    
         
            +
                  #
         
     | 
| 
      
 26 
     | 
    
         
            +
                  def tasks( taskseries )
         
     | 
| 
      
 27 
     | 
    
         
            +
                    task = Marshal.load( Marshal.dump( taskseries ) )
         
     | 
| 
      
 28 
     | 
    
         
            +
                    task.delete('id')
         
     | 
| 
      
 29 
     | 
    
         
            +
                    task.delete('task')
         
     | 
| 
      
 30 
     | 
    
         
            +
                    task['taskseries_id'] = taskseries['id']
         
     | 
| 
      
 31 
     | 
    
         
            +
             
     | 
| 
      
 32 
     | 
    
         
            +
                    taskseries['task'].map { |t|
         
     | 
| 
      
 33 
     | 
    
         
            +
                      t['task_id'] = t['id']
         
     | 
| 
      
 34 
     | 
    
         
            +
                      t.delete( 'id' )
         
     | 
| 
      
 35 
     | 
    
         
            +
                      task.merge( t )
         
     | 
| 
      
 36 
     | 
    
         
            +
                    }
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                end # of << self
         
     | 
| 
      
 39 
     | 
    
         
            +
              end
         
     | 
| 
      
 40 
     | 
    
         
            +
            end
         
     | 
    
        data/lib/gyunyu/token.rb
    ADDED
    
    | 
         @@ -0,0 +1,89 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require 'fileutils'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            module Gyunyu
         
     | 
| 
      
 4 
     | 
    
         
            +
              class Token
         
     | 
| 
      
 5 
     | 
    
         
            +
                API_KEY       = '0af285d87a0798cdd4751acfb02fc058'
         
     | 
| 
      
 6 
     | 
    
         
            +
                SHARED_SECRET = 'f0611feb04a04e1d'
         
     | 
| 
      
 7 
     | 
    
         
            +
             
     | 
| 
      
 8 
     | 
    
         
            +
                include ::FileUtils
         
     | 
| 
      
 9 
     | 
    
         
            +
             
     | 
| 
      
 10 
     | 
    
         
            +
                def initialize
         
     | 
| 
      
 11 
     | 
    
         
            +
                  RTM::API.init( API_KEY, SHARED_SECRET )
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
             
     | 
| 
      
 14 
     | 
    
         
            +
                def self.get
         
     | 
| 
      
 15 
     | 
    
         
            +
                  @self = self.new
         
     | 
| 
      
 16 
     | 
    
         
            +
                  token = @self.load
         
     | 
| 
      
 17 
     | 
    
         
            +
             
     | 
| 
      
 18 
     | 
    
         
            +
                  if ( !token )
         
     | 
| 
      
 19 
     | 
    
         
            +
                    token = @self.request
         
     | 
| 
      
 20 
     | 
    
         
            +
                    @self.save( token )
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
             
     | 
| 
      
 23 
     | 
    
         
            +
                  RTM::API.token = token
         
     | 
| 
      
 24 
     | 
    
         
            +
                  token
         
     | 
| 
      
 25 
     | 
    
         
            +
                end
         
     | 
| 
      
 26 
     | 
    
         
            +
             
     | 
| 
      
 27 
     | 
    
         
            +
                def self.purge
         
     | 
| 
      
 28 
     | 
    
         
            +
                  RTM::API.token = nil
         
     | 
| 
      
 29 
     | 
    
         
            +
                  self.new.instance_eval {
         
     | 
| 
      
 30 
     | 
    
         
            +
                    while ( File.exist?( magazine ) )
         
     | 
| 
      
 31 
     | 
    
         
            +
                      rm( magazine )
         
     | 
| 
      
 32 
     | 
    
         
            +
                    end
         
     | 
| 
      
 33 
     | 
    
         
            +
                  }
         
     | 
| 
      
 34 
     | 
    
         
            +
                end
         
     | 
| 
      
 35 
     | 
    
         
            +
             
     | 
| 
      
 36 
     | 
    
         
            +
                def save( token )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  if ( !File.exist?( magazine ) )
         
     | 
| 
      
 38 
     | 
    
         
            +
                    open( magazine, 'w', 0600 ) { }
         
     | 
| 
      
 39 
     | 
    
         
            +
                  end
         
     | 
| 
      
 40 
     | 
    
         
            +
             
     | 
| 
      
 41 
     | 
    
         
            +
                  open( magazine, 'r+b', 0600 ) { |f|
         
     | 
| 
      
 42 
     | 
    
         
            +
                    f.flock( File::LOCK_EX )
         
     | 
| 
      
 43 
     | 
    
         
            +
                    f.truncate(0)
         
     | 
| 
      
 44 
     | 
    
         
            +
                    f.print token
         
     | 
| 
      
 45 
     | 
    
         
            +
                    f.flock( File::LOCK_UN )
         
     | 
| 
      
 46 
     | 
    
         
            +
                  }
         
     | 
| 
      
 47 
     | 
    
         
            +
                  token
         
     | 
| 
      
 48 
     | 
    
         
            +
                end
         
     | 
| 
      
 49 
     | 
    
         
            +
             
     | 
| 
      
 50 
     | 
    
         
            +
                def load
         
     | 
| 
      
 51 
     | 
    
         
            +
                  token = nil
         
     | 
| 
      
 52 
     | 
    
         
            +
             
     | 
| 
      
 53 
     | 
    
         
            +
                  if ( File.exist?( magazine ) )
         
     | 
| 
      
 54 
     | 
    
         
            +
                    open( magazine, 'r+b' ) { |f|
         
     | 
| 
      
 55 
     | 
    
         
            +
                      # TODO WARN if permission is too loose
         
     | 
| 
      
 56 
     | 
    
         
            +
                      f.flock( File::LOCK_SH )
         
     | 
| 
      
 57 
     | 
    
         
            +
                      token = f.read
         
     | 
| 
      
 58 
     | 
    
         
            +
                      f.flock( File::LOCK_UN )
         
     | 
| 
      
 59 
     | 
    
         
            +
                    }
         
     | 
| 
      
 60 
     | 
    
         
            +
                  end
         
     | 
| 
      
 61 
     | 
    
         
            +
             
     | 
| 
      
 62 
     | 
    
         
            +
                  token
         
     | 
| 
      
 63 
     | 
    
         
            +
                end
         
     | 
| 
      
 64 
     | 
    
         
            +
             
     | 
| 
      
 65 
     | 
    
         
            +
                def magazine
         
     | 
| 
      
 66 
     | 
    
         
            +
                  env || dotfile
         
     | 
| 
      
 67 
     | 
    
         
            +
                end
         
     | 
| 
      
 68 
     | 
    
         
            +
             
     | 
| 
      
 69 
     | 
    
         
            +
                def env
         
     | 
| 
      
 70 
     | 
    
         
            +
                  ENV['RTMSTAT_TOKEN']
         
     | 
| 
      
 71 
     | 
    
         
            +
                end
         
     | 
| 
      
 72 
     | 
    
         
            +
             
     | 
| 
      
 73 
     | 
    
         
            +
                def dotfile
         
     | 
| 
      
 74 
     | 
    
         
            +
                  File.join( ENV['HOME'], '.gyunyu' )
         
     | 
| 
      
 75 
     | 
    
         
            +
                end
         
     | 
| 
      
 76 
     | 
    
         
            +
             
     | 
| 
      
 77 
     | 
    
         
            +
                def request
         
     | 
| 
      
 78 
     | 
    
         
            +
                  frob = RTM::Auth::GetFrob.new.invoke
         
     | 
| 
      
 79 
     | 
    
         
            +
                  url  = RTM::API.get_auth_url('read', frob)
         
     | 
| 
      
 80 
     | 
    
         
            +
                  puts "open RTM with browser and accept API KEY."
         
     | 
| 
      
 81 
     | 
    
         
            +
                  puts "and hit enter."
         
     | 
| 
      
 82 
     | 
    
         
            +
                  system("open '#{url}'")
         
     | 
| 
      
 83 
     | 
    
         
            +
                  STDIN.gets
         
     | 
| 
      
 84 
     | 
    
         
            +
             
     | 
| 
      
 85 
     | 
    
         
            +
                  res = RTM::Auth::GetToken.new(frob).invoke
         
     | 
| 
      
 86 
     | 
    
         
            +
                  res[:token]
         
     | 
| 
      
 87 
     | 
    
         
            +
                end
         
     | 
| 
      
 88 
     | 
    
         
            +
              end
         
     | 
| 
      
 89 
     | 
    
         
            +
            end
         
     | 
    
        data/spec/app/.gitkeep
    ADDED
    
    | 
         
            File without changes
         
     | 
| 
         @@ -0,0 +1,137 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../../../spec_helper'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe Gyunyu::Command::Export::Option do
         
     | 
| 
      
 5 
     | 
    
         
            +
              describe 'parser' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                subject {
         
     | 
| 
      
 7 
     | 
    
         
            +
                  Gyunyu::Command::Export::Option.new.parser
         
     | 
| 
      
 8 
     | 
    
         
            +
                }
         
     | 
| 
      
 9 
     | 
    
         
            +
                it {
         
     | 
| 
      
 10 
     | 
    
         
            +
                  subject.class.should == OptionParser
         
     | 
| 
      
 11 
     | 
    
         
            +
                }
         
     | 
| 
      
 12 
     | 
    
         
            +
             
     | 
| 
      
 13 
     | 
    
         
            +
                describe 'lists' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  context 'no lists' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 16 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new.lists
         
     | 
| 
      
 17 
     | 
    
         
            +
                    }
         
     | 
| 
      
 18 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 19 
     | 
    
         
            +
                      should == []
         
     | 
| 
      
 20 
     | 
    
         
            +
                    }
         
     | 
| 
      
 21 
     | 
    
         
            +
                  end
         
     | 
| 
      
 22 
     | 
    
         
            +
                  context 'one list' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 24 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -l 仕事 ) ).lists
         
     | 
| 
      
 25 
     | 
    
         
            +
                    }
         
     | 
| 
      
 26 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 27 
     | 
    
         
            +
                      should == %w( 仕事 )
         
     | 
| 
      
 28 
     | 
    
         
            +
                    }
         
     | 
| 
      
 29 
     | 
    
         
            +
                  end
         
     | 
| 
      
 30 
     | 
    
         
            +
                  context 'two lists' do
         
     | 
| 
      
 31 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 32 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -l 仕事 -l 勉強 ) ).lists
         
     | 
| 
      
 33 
     | 
    
         
            +
                    }
         
     | 
| 
      
 34 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 35 
     | 
    
         
            +
                      should == %w( 仕事 勉強 )
         
     | 
| 
      
 36 
     | 
    
         
            +
                    }
         
     | 
| 
      
 37 
     | 
    
         
            +
                  end
         
     | 
| 
      
 38 
     | 
    
         
            +
                  context 'twice same list' do
         
     | 
| 
      
 39 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 40 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -l 仕事 -l 仕事 ) ).lists
         
     | 
| 
      
 41 
     | 
    
         
            +
                    }
         
     | 
| 
      
 42 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 43 
     | 
    
         
            +
                      should == %w( 仕事 )
         
     | 
| 
      
 44 
     | 
    
         
            +
                    }
         
     | 
| 
      
 45 
     | 
    
         
            +
                  end
         
     | 
| 
      
 46 
     | 
    
         
            +
                end
         
     | 
| 
      
 47 
     | 
    
         
            +
             
     | 
| 
      
 48 
     | 
    
         
            +
                describe 'filter' do
         
     | 
| 
      
 49 
     | 
    
         
            +
                  context 'no filter' do
         
     | 
| 
      
 50 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 51 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w() ).filter
         
     | 
| 
      
 52 
     | 
    
         
            +
                    }
         
     | 
| 
      
 53 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 54 
     | 
    
         
            +
                      should be_nil
         
     | 
| 
      
 55 
     | 
    
         
            +
                    }
         
     | 
| 
      
 56 
     | 
    
         
            +
                  end
         
     | 
| 
      
 57 
     | 
    
         
            +
                  context 'one filter' do
         
     | 
| 
      
 58 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 59 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -f filter ) ).filter
         
     | 
| 
      
 60 
     | 
    
         
            +
                    }
         
     | 
| 
      
 61 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 62 
     | 
    
         
            +
                      should == 'filter'
         
     | 
| 
      
 63 
     | 
    
         
            +
                    }
         
     | 
| 
      
 64 
     | 
    
         
            +
                  end
         
     | 
| 
      
 65 
     | 
    
         
            +
                  context 'multiple filters' do
         
     | 
| 
      
 66 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 67 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %W( -f first\ one -f last\ one ) ).filter
         
     | 
| 
      
 68 
     | 
    
         
            +
                    }
         
     | 
| 
      
 69 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 70 
     | 
    
         
            +
                      should == 'last one'
         
     | 
| 
      
 71 
     | 
    
         
            +
                    }
         
     | 
| 
      
 72 
     | 
    
         
            +
                  end
         
     | 
| 
      
 73 
     | 
    
         
            +
                end
         
     | 
| 
      
 74 
     | 
    
         
            +
             
     | 
| 
      
 75 
     | 
    
         
            +
                describe 'fields' do
         
     | 
| 
      
 76 
     | 
    
         
            +
                  context 'no fields' do
         
     | 
| 
      
 77 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 78 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new().fields
         
     | 
| 
      
 79 
     | 
    
         
            +
                    }
         
     | 
| 
      
 80 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 81 
     | 
    
         
            +
                      should == %w( task_id name due )
         
     | 
| 
      
 82 
     | 
    
         
            +
                    }
         
     | 
| 
      
 83 
     | 
    
         
            +
                  end
         
     | 
| 
      
 84 
     | 
    
         
            +
                  context 'specified fields' do
         
     | 
| 
      
 85 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 86 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -d id ) ).fields
         
     | 
| 
      
 87 
     | 
    
         
            +
                    }
         
     | 
| 
      
 88 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 89 
     | 
    
         
            +
                      should == %w( id )
         
     | 
| 
      
 90 
     | 
    
         
            +
                    }
         
     | 
| 
      
 91 
     | 
    
         
            +
                  end
         
     | 
| 
      
 92 
     | 
    
         
            +
                  context 'duplicated fields' do
         
     | 
| 
      
 93 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 94 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -d id -d name -d id ) ).fields
         
     | 
| 
      
 95 
     | 
    
         
            +
                    }
         
     | 
| 
      
 96 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 97 
     | 
    
         
            +
                      should == %w( id name )
         
     | 
| 
      
 98 
     | 
    
         
            +
                    }
         
     | 
| 
      
 99 
     | 
    
         
            +
                  end
         
     | 
| 
      
 100 
     | 
    
         
            +
                  context 'include #{FIELD_SEP}' do
         
     | 
| 
      
 101 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 102 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -d id,name,taskseries_id,due ) ).fields
         
     | 
| 
      
 103 
     | 
    
         
            +
                    }
         
     | 
| 
      
 104 
     | 
    
         
            +
                    it 'bulk definition' do
         
     | 
| 
      
 105 
     | 
    
         
            +
                      should == %w( id name taskseries_id due )
         
     | 
| 
      
 106 
     | 
    
         
            +
                    end
         
     | 
| 
      
 107 
     | 
    
         
            +
                  end
         
     | 
| 
      
 108 
     | 
    
         
            +
                end
         
     | 
| 
      
 109 
     | 
    
         
            +
             
     | 
| 
      
 110 
     | 
    
         
            +
                describe 'format' do
         
     | 
| 
      
 111 
     | 
    
         
            +
                  context 'no format' do
         
     | 
| 
      
 112 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 113 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new().format
         
     | 
| 
      
 114 
     | 
    
         
            +
                    }
         
     | 
| 
      
 115 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 116 
     | 
    
         
            +
                      should == :csv
         
     | 
| 
      
 117 
     | 
    
         
            +
                    }
         
     | 
| 
      
 118 
     | 
    
         
            +
                  end
         
     | 
| 
      
 119 
     | 
    
         
            +
                  context 'correct format' do
         
     | 
| 
      
 120 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 121 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -o json ) ).format
         
     | 
| 
      
 122 
     | 
    
         
            +
                    }
         
     | 
| 
      
 123 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 124 
     | 
    
         
            +
                      should == 'json'
         
     | 
| 
      
 125 
     | 
    
         
            +
                    }
         
     | 
| 
      
 126 
     | 
    
         
            +
                  end
         
     | 
| 
      
 127 
     | 
    
         
            +
                  context 'wrong format' do
         
     | 
| 
      
 128 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 129 
     | 
    
         
            +
                      Gyunyu::Command::Export::Option.new( %w( -o atom ) ).format
         
     | 
| 
      
 130 
     | 
    
         
            +
                    }
         
     | 
| 
      
 131 
     | 
    
         
            +
                    it {
         
     | 
| 
      
 132 
     | 
    
         
            +
                      lambda { subject }.should raise_error( Gyunyu::Command::Export::Option::FormatNotFound )
         
     | 
| 
      
 133 
     | 
    
         
            +
                    }
         
     | 
| 
      
 134 
     | 
    
         
            +
                  end
         
     | 
| 
      
 135 
     | 
    
         
            +
                end
         
     | 
| 
      
 136 
     | 
    
         
            +
              end
         
     | 
| 
      
 137 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,62 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../spec_helper'
         
     | 
| 
      
 2 
     | 
    
         
            +
             
     | 
| 
      
 3 
     | 
    
         
            +
            describe Gyunyu::Command do
         
     | 
| 
      
 4 
     | 
    
         
            +
              describe 'commands' do
         
     | 
| 
      
 5 
     | 
    
         
            +
                let(:commands) {
         
     | 
| 
      
 6 
     | 
    
         
            +
                  Gyunyu::Command.commands
         
     | 
| 
      
 7 
     | 
    
         
            +
                }
         
     | 
| 
      
 8 
     | 
    
         
            +
                describe 'array' do
         
     | 
| 
      
 9 
     | 
    
         
            +
                  it {
         
     | 
| 
      
 10 
     | 
    
         
            +
                    commands.size.should > 0
         
     | 
| 
      
 11 
     | 
    
         
            +
                  }
         
     | 
| 
      
 12 
     | 
    
         
            +
                end
         
     | 
| 
      
 13 
     | 
    
         
            +
                describe 'array of strings' do
         
     | 
| 
      
 14 
     | 
    
         
            +
                  it 'array of strings' do
         
     | 
| 
      
 15 
     | 
    
         
            +
                    commands.map { |e| e.should.class == String }
         
     | 
| 
      
 16 
     | 
    
         
            +
                  end
         
     | 
| 
      
 17 
     | 
    
         
            +
                end
         
     | 
| 
      
 18 
     | 
    
         
            +
              end
         
     | 
| 
      
 19 
     | 
    
         
            +
             
     | 
| 
      
 20 
     | 
    
         
            +
              describe 'dispatch' do
         
     | 
| 
      
 21 
     | 
    
         
            +
                context 'correct command' do
         
     | 
| 
      
 22 
     | 
    
         
            +
                  before {
         
     | 
| 
      
 23 
     | 
    
         
            +
                    stub.instance_of(Gyunyu::Command::Export::App).run {
         
     | 
| 
      
 24 
     | 
    
         
            +
                      "`export' dispatched"
         
     | 
| 
      
 25 
     | 
    
         
            +
                    }
         
     | 
| 
      
 26 
     | 
    
         
            +
                  }
         
     | 
| 
      
 27 
     | 
    
         
            +
                  subject {
         
     | 
| 
      
 28 
     | 
    
         
            +
                    Gyunyu::Command.dispatch( 'export' )
         
     | 
| 
      
 29 
     | 
    
         
            +
                  }
         
     | 
| 
      
 30 
     | 
    
         
            +
                  it {
         
     | 
| 
      
 31 
     | 
    
         
            +
                    should == "`export' dispatched"
         
     | 
| 
      
 32 
     | 
    
         
            +
                  }
         
     | 
| 
      
 33 
     | 
    
         
            +
                end
         
     | 
| 
      
 34 
     | 
    
         
            +
                context 'wrong command' do
         
     | 
| 
      
 35 
     | 
    
         
            +
                  subject {
         
     | 
| 
      
 36 
     | 
    
         
            +
                    Gyunyu::Command.dispatch( 'foo' )
         
     | 
| 
      
 37 
     | 
    
         
            +
                  }
         
     | 
| 
      
 38 
     | 
    
         
            +
                  it {
         
     | 
| 
      
 39 
     | 
    
         
            +
                    lambda {subject}.should raise_error(Gyunyu::Command::NotFound)
         
     | 
| 
      
 40 
     | 
    
         
            +
                  }
         
     | 
| 
      
 41 
     | 
    
         
            +
                end
         
     | 
| 
      
 42 
     | 
    
         
            +
              end
         
     | 
| 
      
 43 
     | 
    
         
            +
             
     | 
| 
      
 44 
     | 
    
         
            +
              describe 'app_const' do
         
     | 
| 
      
 45 
     | 
    
         
            +
                context 'correct app' do
         
     | 
| 
      
 46 
     | 
    
         
            +
                  subject {
         
     | 
| 
      
 47 
     | 
    
         
            +
                    Gyunyu::Command.app_const( 'export' )
         
     | 
| 
      
 48 
     | 
    
         
            +
                  }
         
     | 
| 
      
 49 
     | 
    
         
            +
                  it {
         
     | 
| 
      
 50 
     | 
    
         
            +
                    should == Gyunyu::Command::Export::App
         
     | 
| 
      
 51 
     | 
    
         
            +
                  }
         
     | 
| 
      
 52 
     | 
    
         
            +
                end
         
     | 
| 
      
 53 
     | 
    
         
            +
                context 'wrong app' do
         
     | 
| 
      
 54 
     | 
    
         
            +
                  subject {
         
     | 
| 
      
 55 
     | 
    
         
            +
                    Gyunyu::Command.app_const( 'foo' )
         
     | 
| 
      
 56 
     | 
    
         
            +
                  }
         
     | 
| 
      
 57 
     | 
    
         
            +
                  it {
         
     | 
| 
      
 58 
     | 
    
         
            +
                    lambda {subject}.should raise_error( NameError )
         
     | 
| 
      
 59 
     | 
    
         
            +
                  }
         
     | 
| 
      
 60 
     | 
    
         
            +
                end
         
     | 
| 
      
 61 
     | 
    
         
            +
              end
         
     | 
| 
      
 62 
     | 
    
         
            +
            end
         
     | 
| 
         @@ -0,0 +1,140 @@ 
     | 
|
| 
      
 1 
     | 
    
         
            +
            # -*- coding: utf-8 -*-
         
     | 
| 
      
 2 
     | 
    
         
            +
            require File.dirname(__FILE__) + '/../spec_helper'
         
     | 
| 
      
 3 
     | 
    
         
            +
             
     | 
| 
      
 4 
     | 
    
         
            +
            describe Gyunyu::Expander do
         
     | 
| 
      
 5 
     | 
    
         
            +
              describe 'taskseries' do
         
     | 
| 
      
 6 
     | 
    
         
            +
                shared_examples_for :taskseries do
         
     | 
| 
      
 7 
     | 
    
         
            +
                  it 'array of hash' do
         
     | 
| 
      
 8 
     | 
    
         
            +
                    subject.class.should == Array
         
     | 
| 
      
 9 
     | 
    
         
            +
                    subject.each { |e|
         
     | 
| 
      
 10 
     | 
    
         
            +
                      e.class.should == Hash
         
     | 
| 
      
 11 
     | 
    
         
            +
                    }
         
     | 
| 
      
 12 
     | 
    
         
            +
                  end
         
     | 
| 
      
 13 
     | 
    
         
            +
                end
         
     | 
| 
      
 14 
     | 
    
         
            +
             
     | 
| 
      
 15 
     | 
    
         
            +
                context 'array given' do
         
     | 
| 
      
 16 
     | 
    
         
            +
                  it_should_behave_like :taskseries do
         
     | 
| 
      
 17 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 18 
     | 
    
         
            +
                      Gyunyu::Expander.taskseries( task_raw_data.first['taskseries'] )
         
     | 
| 
      
 19 
     | 
    
         
            +
                    }
         
     | 
| 
      
 20 
     | 
    
         
            +
                  end
         
     | 
| 
      
 21 
     | 
    
         
            +
                end
         
     | 
| 
      
 22 
     | 
    
         
            +
                context 'hash given' do
         
     | 
| 
      
 23 
     | 
    
         
            +
                  it_should_behave_like :taskseries do
         
     | 
| 
      
 24 
     | 
    
         
            +
                    subject {
         
     | 
| 
      
 25 
     | 
    
         
            +
                      Gyunyu::Expander.taskseries( task_raw_data.first )
         
     | 
| 
      
 26 
     | 
    
         
            +
                    }
         
     | 
| 
      
 27 
     | 
    
         
            +
                  end
         
     | 
| 
      
 28 
     | 
    
         
            +
                end
         
     | 
| 
      
 29 
     | 
    
         
            +
              end
         
     | 
| 
      
 30 
     | 
    
         
            +
             
     | 
| 
      
 31 
     | 
    
         
            +
              describe 'tasks' do
         
     | 
| 
      
 32 
     | 
    
         
            +
                subject {
         
     | 
| 
      
 33 
     | 
    
         
            +
                  Gyunyu::Expander.tasks(task_raw_data.first['taskseries'].first)
         
     | 
| 
      
 34 
     | 
    
         
            +
                }
         
     | 
| 
      
 35 
     | 
    
         
            +
                it {
         
     | 
| 
      
 36 
     | 
    
         
            +
                  should == [
         
     | 
| 
      
 37 
     | 
    
         
            +
                    { "taskseries_id"=>"118872028",
         
     | 
| 
      
 38 
     | 
    
         
            +
                      "created"=>"2011-05-28T01:04:49Z",
         
     | 
| 
      
 39 
     | 
    
         
            +
                      "modified"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 40 
     | 
    
         
            +
                      "name"=>"jsのlintについて",
         
     | 
| 
      
 41 
     | 
    
         
            +
                      "source"=>"js",
         
     | 
| 
      
 42 
     | 
    
         
            +
                      "url"=>"",
         
     | 
| 
      
 43 
     | 
    
         
            +
                      "location_id"=>"",
         
     | 
| 
      
 44 
     | 
    
         
            +
                      "tags"=>[{"tag"=>["research", "writing"]}],
         
     | 
| 
      
 45 
     | 
    
         
            +
                      "participants"=>[{}],
         
     | 
| 
      
 46 
     | 
    
         
            +
                      "notes"=>
         
     | 
| 
      
 47 
     | 
    
         
            +
                      [{"note"=>
         
     | 
| 
      
 48 
     | 
    
         
            +
                          [{"id"=>"26111105",
         
     | 
| 
      
 49 
     | 
    
         
            +
                              "created"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 50 
     | 
    
         
            +
                              "modified"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 51 
     | 
    
         
            +
                              "title"=>"",
         
     | 
| 
      
 52 
     | 
    
         
            +
                              "content"=>"意図が分かんないな、このメモ。結局何をしたかった?"}]}],
         
     | 
| 
      
 53 
     | 
    
         
            +
                      "task_id"=>"181820465",
         
     | 
| 
      
 54 
     | 
    
         
            +
                      "due"=>"",
         
     | 
| 
      
 55 
     | 
    
         
            +
                      "has_due_time"=>"0",
         
     | 
| 
      
 56 
     | 
    
         
            +
                      "added"=>"2011-05-28T01:04:49Z",
         
     | 
| 
      
 57 
     | 
    
         
            +
                      "completed"=>"",
         
     | 
| 
      
 58 
     | 
    
         
            +
                      "deleted"=>"",
         
     | 
| 
      
 59 
     | 
    
         
            +
                      "priority"=>"1",
         
     | 
| 
      
 60 
     | 
    
         
            +
                      "postponed"=>"0",
         
     | 
| 
      
 61 
     | 
    
         
            +
                      "estimate"=>""}]
         
     | 
| 
      
 62 
     | 
    
         
            +
                }
         
     | 
| 
      
 63 
     | 
    
         
            +
              end
         
     | 
| 
      
 64 
     | 
    
         
            +
            end
         
     | 
| 
      
 65 
     | 
    
         
            +
             
     | 
| 
      
 66 
     | 
    
         
            +
            def task_raw_data
         
     | 
| 
      
 67 
     | 
    
         
            +
              # [{'id' => list id,
         
     | 
| 
      
 68 
     | 
    
         
            +
              #   'taskseries' =>
         
     | 
| 
      
 69 
     | 
    
         
            +
              #   []
         
     | 
| 
      
 70 
     | 
    
         
            +
              #  }]
         
     | 
| 
      
 71 
     | 
    
         
            +
            [{"id"=>"135243",
         
     | 
| 
      
 72 
     | 
    
         
            +
              "taskseries"=>
         
     | 
| 
      
 73 
     | 
    
         
            +
               [{"id"=>"118872028",
         
     | 
| 
      
 74 
     | 
    
         
            +
                 "created"=>"2011-05-28T01:04:49Z",
         
     | 
| 
      
 75 
     | 
    
         
            +
                 "modified"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 76 
     | 
    
         
            +
                 "name"=>"jsのlintについて",
         
     | 
| 
      
 77 
     | 
    
         
            +
                 "source"=>"js",
         
     | 
| 
      
 78 
     | 
    
         
            +
                 "url"=>"",
         
     | 
| 
      
 79 
     | 
    
         
            +
                 "location_id"=>"",
         
     | 
| 
      
 80 
     | 
    
         
            +
                 "tags"=>[{"tag"=>["research", "writing"]}],
         
     | 
| 
      
 81 
     | 
    
         
            +
                 "participants"=>[{}],
         
     | 
| 
      
 82 
     | 
    
         
            +
                 "notes"=>
         
     | 
| 
      
 83 
     | 
    
         
            +
                  [{"note"=>
         
     | 
| 
      
 84 
     | 
    
         
            +
                     [{"id"=>"26111105",
         
     | 
| 
      
 85 
     | 
    
         
            +
                       "created"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 86 
     | 
    
         
            +
                       "modified"=>"2011-10-10T22:00:53Z",
         
     | 
| 
      
 87 
     | 
    
         
            +
                       "title"=>"",
         
     | 
| 
      
 88 
     | 
    
         
            +
                       "content"=>"意図が分かんないな、このメモ。結局何をしたかった?"}]}],
         
     | 
| 
      
 89 
     | 
    
         
            +
                 "task"=>
         
     | 
| 
      
 90 
     | 
    
         
            +
                  [{"id"=>"181820465",
         
     | 
| 
      
 91 
     | 
    
         
            +
                    "due"=>"",
         
     | 
| 
      
 92 
     | 
    
         
            +
                    "has_due_time"=>"0",
         
     | 
| 
      
 93 
     | 
    
         
            +
                    "added"=>"2011-05-28T01:04:49Z",
         
     | 
| 
      
 94 
     | 
    
         
            +
                    "completed"=>"",
         
     | 
| 
      
 95 
     | 
    
         
            +
                    "deleted"=>"",
         
     | 
| 
      
 96 
     | 
    
         
            +
                    "priority"=>"1",
         
     | 
| 
      
 97 
     | 
    
         
            +
                    "postponed"=>"0",
         
     | 
| 
      
 98 
     | 
    
         
            +
                    "estimate"=>""}]},
         
     | 
| 
      
 99 
     | 
    
         
            +
                {"id"=>"46116936",
         
     | 
| 
      
 100 
     | 
    
         
            +
                 "created"=>"2009-08-01T08:35:30Z",
         
     | 
| 
      
 101 
     | 
    
         
            +
                 "modified"=>"2010-05-10T03:18:43Z",
         
     | 
| 
      
 102 
     | 
    
         
            +
                 "name"=>"あの本読む",
         
     | 
| 
      
 103 
     | 
    
         
            +
                 "source"=>"js",
         
     | 
| 
      
 104 
     | 
    
         
            +
                 "url"=>"",
         
     | 
| 
      
 105 
     | 
    
         
            +
                 "location_id"=>"",
         
     | 
| 
      
 106 
     | 
    
         
            +
                 "tags"=>[{"tag"=>["reading"]}],
         
     | 
| 
      
 107 
     | 
    
         
            +
                 "participants"=>[{}],
         
     | 
| 
      
 108 
     | 
    
         
            +
                 "notes"=>[{}],
         
     | 
| 
      
 109 
     | 
    
         
            +
                 "task"=>
         
     | 
| 
      
 110 
     | 
    
         
            +
                  [{"id"=>"65881131",
         
     | 
| 
      
 111 
     | 
    
         
            +
                    "due"=>"",
         
     | 
| 
      
 112 
     | 
    
         
            +
                    "has_due_time"=>"0",
         
     | 
| 
      
 113 
     | 
    
         
            +
                    "added"=>"2009-08-01T08:35:30Z",
         
     | 
| 
      
 114 
     | 
    
         
            +
                    "completed"=>"",
         
     | 
| 
      
 115 
     | 
    
         
            +
                    "deleted"=>"",
         
     | 
| 
      
 116 
     | 
    
         
            +
                    "priority"=>"N",
         
     | 
| 
      
 117 
     | 
    
         
            +
                    "postponed"=>"0",
         
     | 
| 
      
 118 
     | 
    
         
            +
                    "estimate"=>"1時間"}]},
         
     | 
| 
      
 119 
     | 
    
         
            +
                {"id"=>"115609158",
         
     | 
| 
      
 120 
     | 
    
         
            +
                 "created"=>"2011-05-02T10:13:47Z",
         
     | 
| 
      
 121 
     | 
    
         
            +
                 "modified"=>"2011-05-07T12:26:43Z",
         
     | 
| 
      
 122 
     | 
    
         
            +
                 "name"=>"この本読む",
         
     | 
| 
      
 123 
     | 
    
         
            +
                 "source"=>"js",
         
     | 
| 
      
 124 
     | 
    
         
            +
                 "url"=>"",
         
     | 
| 
      
 125 
     | 
    
         
            +
                 "location_id"=>"",
         
     | 
| 
      
 126 
     | 
    
         
            +
                 "tags"=>[{"tag"=>["reading"]}],
         
     | 
| 
      
 127 
     | 
    
         
            +
                 "participants"=>[{}],
         
     | 
| 
      
 128 
     | 
    
         
            +
                 "notes"=>[{}],
         
     | 
| 
      
 129 
     | 
    
         
            +
                 "task"=>
         
     | 
| 
      
 130 
     | 
    
         
            +
                  [{"id"=>"176273444",
         
     | 
| 
      
 131 
     | 
    
         
            +
                    "due"=>"",
         
     | 
| 
      
 132 
     | 
    
         
            +
                    "has_due_time"=>"0",
         
     | 
| 
      
 133 
     | 
    
         
            +
                    "added"=>"2011-05-02T10:13:47Z",
         
     | 
| 
      
 134 
     | 
    
         
            +
                    "completed"=>"",
         
     | 
| 
      
 135 
     | 
    
         
            +
                    "deleted"=>"",
         
     | 
| 
      
 136 
     | 
    
         
            +
                    "priority"=>"1",
         
     | 
| 
      
 137 
     | 
    
         
            +
                    "postponed"=>"0",
         
     | 
| 
      
 138 
     | 
    
         
            +
                    "estimate"=>"8h"}]}
         
     | 
| 
      
 139 
     | 
    
         
            +
                  ]}]
         
     | 
| 
      
 140 
     | 
    
         
            +
            end
         
     |