Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

simplified tickets and projects and added comments

  • Loading branch information...
commit 34e59c412376b09856e9f28e8e395eb56070cd45 1 parent 9410fee
@kiafaldorius kiafaldorius authored
View
1  TODO
@@ -0,0 +1 @@
+1) A Cache system for the finders
View
8 lib/ticketmaster.rb
@@ -7,8 +7,11 @@ class TicketMaster
end
%w{
+ common
+ helper
project
ticket
+ comment
authenticator
provider
exception
@@ -18,7 +21,8 @@ class TicketMaster
# This is the TicketMaster class
#
class TicketMaster
- attr_reader :provider
+ attr_reader :provider, :symbol
+ attr_accessor :default_project
# This initializes the TicketMaster instance and prepares the provider
# If called without any arguments, it conveniently tries searching for the information in
@@ -35,6 +39,8 @@ def initialize(system = nil, authentication = nil)
end
self.extend TicketMaster::Provider.const_get(system.to_s.capitalize)
authorize authentication
+ @symbol = system.to_sym
+ @provider = TicketMaster::Provider.const_get(system.to_s.capitalize)
end
# Providers should over-write this method
View
97 lib/ticketmaster/comment.rb
@@ -0,0 +1,97 @@
+module TicketMaster::Provider
+ module Base
+ # The comment class
+ #
+ # This will probably one of the most troublesome parts of creating a provider for ticketmaster
+ # since there are so many different ways comments are handled by different APIs.
+ # Keep in mind that if you do need to change/overwrite the methods, you will most likely
+ # only need to overwrite #find_by_id, #find_by_attributes, #search, and possibly #initialize
+ # as long as their parameters conform to what the find method expects.
+ #
+ # Here are the expected attributes:
+ #
+ # * author
+ # * body
+ # * id
+ # * created_at
+ # * updated_at
+ # * ticket_id
+ # * project_id
+ class Comment < Hashie::Mash
+ include TicketMaster::Provider::Common
+ include TicketMaster::Provider::Helper
+ extend TicketMaster::Provider::Helper
+ attr_accessor :system, :system_data
+ API = nil # Replace with your comment's API's Class
+
+ # Find comment
+ # You can also retrieve an array of all comments by not specifying any query.
+ #
+ # * find(<project_id>, <ticket_id>) or find(<project_id>, <ticket_id>, :all) - Returns an array of all comments
+ # * find(<project_id>, <ticket_id>, ##) - Returns a comment based on that id or some other primary (unique) attribute
+ # * find(<project_id>, <ticket_id>, [#, #, #]) - Returns many comments with these ids
+ # * find(<project_id>, <ticket_id>, :first, :name => 'Project name') - Returns the first comment based on the comment's attribute(s)
+ # * find(<project_id>, <ticket_id>, :last, :name => 'Some project') - Returns the last comment based on the comment's attribute(s)
+ # * find(<project_id>, <ticket_id>, :all, :name => 'Test Project') - Returns all comments based on the given attribute(s)
+ def self.find(project_id, ticket_id, *options)
+ first, attributes = options
+ if first.nil? or (first == :all and attributes.nil?)
+ self.find_by_attributes(project_id, ticket_id)
+ elsif first.is_a? Fixnum
+ self.find_by_id(project_id, ticket_id, first)
+ elsif first.is_a? Array
+ first.collect { |id| self.find_by_id(project_id, ticket_id, id) }
+ elsif first == :first
+ comments = attributes.nil? ? self.find_by_attributes(project_id, ticket_id) : self.find_by_attributes(project_id, ticket_id, attributes)
+ comments.first
+ elsif first == :last
+ comments = attributes.nil? ? self.find_by_attributes(project_id, ticket_id) : self.find_by_attributes(project_id, ticket_id, attributes)
+ comments.last
+ elsif first == :all
+ self.find_by_attributes(project_id, ticket_id, attributes)
+ end
+ end
+
+ # The first of whatever comment
+ def self.first(project_id, ticket_id, *options)
+ self.find(project_id, ticket_id, :first, *options)
+ end
+
+ # The last of whatever comment
+ def self.last(project_id, ticket_id, *options)
+ self.find(project_id, ticket_id, :last, *options)
+ end
+
+ # Accepts an integer id and returns the single comment instance
+ # Must be defined by the provider
+ def self.find_by_id(project_id, ticket_id, id)
+ if self::API.is_a? Class
+ self.new self::API.find(id, :params => {:project_id => project_id, :ticket_id => ticket_id})
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # Accepts an attributes hash and returns all comments matching those attributes in an array
+ # Should return all comments if the attributes hash is empty
+ # Must be defined by the provider
+ def self.find_by_attributes(project_id, ticket_id, attributes = {})
+ if self::API.is_a? Class
+ self.search(project_id, ticket_id, attributes).collect { |thing| self.new thing }
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # This is a helper method to find
+ def self.search(project_id, ticket_id, options = {}, limit = 1000)
+ if self::API.is_a? Class
+ comments = self::API.find(:all, :params => {:project_id => project_id, :ticket_id => ticket_id})
+ search_by_attribute(comments, options, limit)
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+ end
+ end
+end
View
82 lib/ticketmaster/common.rb
@@ -0,0 +1,82 @@
+module TicketMaster::Provider
+ # Common module
+ # contains method definitions common to all or most of the models
+ module Common
+ module ClassMethods
+ # Create a something.
+ # Basically, a .new and .save in the same call. The default method assumes it is passed a
+ # single hash with attribute information
+ def create(*options)
+ if self::API.is_a? Class
+ something = self::API.new(*options)
+ something.save
+ self.new something
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+ end
+
+ # Automatic extension of class methods on include
+ def self.included(base)
+ base.extend ClassMethods
+ end
+
+ # The initializer
+ # It tries to do a default system for ActiveResource-based api providers
+ def initialize(*options)
+ @system_data ||= {}
+ @cache ||= {}
+ first = options.shift
+ case first
+ when ActiveResource::Base
+ @system_data[:client] = first
+ self.prefix_options=@system_data[:client].prefix_options if @system_data[:client].prefix_options
+ super(first.attributes)
+
+ when Hash
+ super(first.to_hash)
+ end
+ end
+
+ # Update the something and save
+ # As opposed to update which just updates the attributes
+ def update!(*options)
+ update(*options)
+ save
+ end
+
+ # Save changes to this project
+ # Returns true (success) or false (failure) or nil (no changes)
+ def save
+ if @system_data and (something = @system_data[:client]) and something.respond_to?(:attributes)
+ changes = 0
+ something.attributes.each do |k, v|
+ if self.send(k) != v
+ something.send(k + '=', self.send(k))
+ changes += 1
+ end
+ end
+ something.save if changes > 0
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # Delete this project
+ # Returns true (success) or false(failure)
+ def destroy
+ if @system_data and @system_data[:client] and @system_data[:client].respond_to?(:destroy)
+ return @system_data[:client].destroy
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ def respond_to?(symbol)
+ result = super(symbol)
+ return true if result or @system_data.nil? or @system_data[:client].nil?
+ @system_data[:client].respond_to?(symbol)
+ end
+ end
+end
View
61 lib/ticketmaster/helper.rb
@@ -0,0 +1,61 @@
+module TicketMaster::Provider
+ # Contains a series of helper methods
+ module Helper
+
+ # A helper method for easy finding
+ def easy_finder(api, symbol, options, at_index = 0)
+ if api.is_a? Class
+ return api if options.length == 0 and symbol == :first
+ options.insert(at_index, symbol) if options[at_index].is_a?(Hash)
+ api.find(*options)
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # This is a search filter that all parameters are passed through
+ # Redefine this method in your classes if you need specific functionality
+ def search_filter(k)
+ k
+ end
+
+ # Goes through all the things and returns results that match the options attributes hash
+ def search_by_attribute(things, options = {}, limit = 1000)
+ things.find_all do |thing|
+ options.reduce(true) do |memo, kv|
+ break unless memo
+ key, value = kv
+ begin
+ memo &= thing.send(key) == value
+ rescue NoMethodError
+ memo = false
+ end
+ memo
+ end and (limit -= 1) > 0
+ end
+ end
+
+ # Returns a filter-like string from a hash
+ # If array_join is given, arrays are joined rather than having their own separated key:values
+ #
+ # ex: filter_string({:name => 'some value', :tags => ['abc', 'def']}) = "name:'some value' tag:abc tag:def"
+ def filter_string(filter = {}, array_join = nil)
+ filter.reduce('') do |mem, kv|
+ key, value = kv
+ if value.is_a?(Array)
+ if !array_join.nil?
+ mem += value.reduce('') { |m, v|
+ v = "\"#{v}\"" if v.to_s.include?(' ')
+ m+= "#{key}:#{v}"
+ }
+ return mem
+ else
+ value = value.join(array_join)
+ end
+ end
+ value = "\"#{value}\"" if value.to_s.include?(' ')
+ mem += "#{key}:#{value} "
+ end
+ end
+ end
+end
View
131 lib/ticketmaster/project.rb
@@ -10,17 +10,21 @@ module Base
#
# Methods that must be implemented by the provider
#
- # * self.find
+ # * self.find_by_id
+ # * self.find_by_attributes
+ #
+ # Methods that might need to be implemented by the provider
# * tickets
# * ticket
- # * save
# * initialize
# * update
# * destroy
+ # * self.create
#
# Methods that would probably be okay if the provider left it alone:
#
- # * self.create
+ # * self.find - although you can define your own to optimize it a bit
+ # * update!
#
# A provider should define as many attributes as feasibly possible. The list below are
# some guidelines as to what attributes are necessary, if your provider's api does not
@@ -33,68 +37,101 @@ module Base
# * updated_at
# * description
class Project < Hashie::Mash
+ include TicketMaster::Provider::Common
+ include TicketMaster::Provider::Helper
+ extend TicketMaster::Provider::Helper
attr_accessor :system, :system_data
- # Find a project, or find more projects.
+ API = nil #Replace with your api digestor's class.
+
+ # Find project
# You can also retrieve an array of all projects by not specifying any query.
#
- # The implementation should be able to accept these cases if feasible:
- #
- # * find(:all) - Returns an array of all projects
+ # * find() or find(:all) - Returns an array of all projects
# * find(##) - Returns a project based on that id or some other primary (unique) attribute
- # * find(:first, :summary => 'Project name') - Returns a project based on the project's attributes
- # * find(:summary => 'Test Project') - Returns all projects based on the given attribute(s)
+ # * find([#, #, #]) - Returns many projects with these ids
+ # * find(:first, :name => 'Project name') - Returns the first project based on the project's attribute(s)
+ # * find(:last, :name => 'Some project') - Returns the last project based on the project's attribute(s)
+ # * find(:all, :name => 'Test Project') - Returns all projects based on the given attribute(s)
def self.find(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ first = options.shift
+ attributes = options.shift
+ if first.nil? or (first == :all and attributes.nil?)
+ self.find_by_attributes
+ elsif first.is_a? Fixnum
+ self.find_by_id(first)
+ elsif first.is_a? Array
+ first.collect { |id| self.find_by_id(id) }
+ elsif first == :first
+ projects = attributes.nil? ? self.find_by_attributes : self.find_by_attributes(attributes)
+ projects.first
+ elsif first == :last
+ projects = attributes.nil? ? self.find_by_attributes : self.find_by_attributes(attributes)
+ projects.last
+ elsif first == :all
+ self.find_by_attributes(attributes)
+ end
end
- # Create a project.
- # Basically, a .new and .save in the same call. The default method assumes it is passed a
- # single hash with attribute information
- def self.create(*options)
- project = self.new(options.first)
- project.save
- project
+ # The first of whatever project
+ def self.first(*options)
+ self.find(:first, *options)
end
- # The initializer
- def initialize(*options)
- super(options.shift)
- # do some other stuff
+ # The last of whatever project
+ def self.last(*options)
+ self.find(:last, *options)
+ end
+
+ # Accepts an integer id and returns the single project instance
+ # Must be defined by the provider
+ def self.find_by_id(id)
+ if self::API.is_a? Class
+ self.new self::API.find id
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # Accepts an attributes hash and returns all projects matching those attributes in an array
+ # Should return all projects if the attributes hash is empty
+ # Must be defined by the provider
+ def self.find_by_attributes(attributes = {})
+ if self::API.is_a? Class
+ self.search(attributes).collect { |thing| self.new thing }
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # This is a helper method to find
+ def self.search(options = {}, limit = 1000)
+ if self::API.is_a? Class
+ projects = self::API.find(:all)
+ search_by_attribute(projects, options, limit)
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
end
# Asks the provider's api for the tickets associated with the project,
# returns an array of Ticket objects.
def tickets(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
- end
-
- # Mainly here because it is more natural to do:
- # project.ticket.create(..)
- #
- # Than
- # project.tickets.create(..)
- #
- # returns a ticket object or ticket class that responds to .new and .create.
- def ticket(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
- end
-
- # Save changes to this project
- # Returns true (success) or false (failure)
- def save
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ options.insert 0, id
+ easy_finder(self.class.parent::Ticket, :all, options, 1)
end
- # Delete this project
- # Returns true (success) or false(failure)
- def destroy
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ # Very similar to tickets, and is practically an alias of it
+ # however this returns the ticket class if no parameter is given
+ # unlike tickets which returns an array of all tickets when given no parameters
+ def ticket(*options)
+ options.insert(0, id) if options.length > 0
+ easy_finder(self.class.parent::Ticket, :first, options, 1)
end
- # Update the project and save
- def update!(*options)
- update(*options)
- save
+ # Define some provider specific initalizations
+ def initialize(*options)
+ # @system_data = {'some' => 'data}
+ super(*options)
end
end
View
29 lib/ticketmaster/provider.rb
@@ -11,6 +11,11 @@
# We are also planning on standardizing non-standard/provider-specific object models
module TicketMaster::Provider
module Base
+ PROJECT_API = nil # The Class for the project api interaction
+ TICKET_API = nil # The Class for the ticket api interaction
+
+ include TicketMaster::Provider::Helper
+
# All providers must define this method.
# It doesn't *have* to do anything, it just has to be there. But since it's here, you don't
# have to worry about it as long as you "include TicketMaster::Provider::Base"
@@ -28,8 +33,15 @@ def authorize(authentication = {})
#
# Should try to implement a find :first (or find with singular result) if given parameters
def project(*options)
- return TicketMaster::Project.find(*options) if options.length > 0
- TicketMaster::Project
+ easy_finder(@provider::Project, :first, options)
+ end
+
+ # All providers should try to define this method.
+ #
+ # It returns all projects in an array
+ # Should try to implement a find :all if given parameters
+ def projects(*options)
+ easy_finder(@provider::Project, :all, options)
end
# Providers should try to define this method
@@ -43,16 +55,7 @@ def project(*options)
#
# Should try to implement a find :first (or find with singular result) if given parameters
def ticket(*options)
- return TicketMaster::Ticket.find(*options) if options.length > 0
- TicketMaster::Ticket
- end
-
- # All providers should try to define this method.
- #
- # It returns all projects in an array
- # Should try to implement a find :all if given parameters
- def projects(*options)
- []
+ easy_finder(@provider::Ticket, :first, options)
end
# All providers should try to define this method
@@ -60,7 +63,7 @@ def projects(*options)
# It returns all tickets in an array.
# Should try to implement a find :all if given parameters
def tickets(*options)
- []
+ easy_finder(@provider::Ticket, :all, options)
end
end
end
View
156 lib/ticketmaster/ticket.rb
@@ -8,111 +8,139 @@ module Base
# methods act based on a blank slate (which means the info to find a specific ticket has
# to be passed in the parameters in the ticket)
#
- # Methods that a provider must define:
- #
- # * self.find
- # * close
- # * save
- # * destroy
- #
# Methods that the provider should define if feasible:
#
# * reload!
# * initialize
+ # * close
+ # * save
+ # * destroy
#
# Methods that would probably be okay if the provider left it alone:
#
# * self.create
# * update
# * update!
+ # * self.find
#
# A provider should define as many attributes as feasibly possible. The list below are
# some guidelines as to what attributes are necessary, if your provider's api does not
- # implement them, point it to an attribute that is close to it. (for example, a summary
- # can point to title. and assignee might point to assigned_to. Remember to alias it in your class!)
+ # implement them, point it to an attribute that is close to it. (for example, a title
+ # can point to summary. and assignee might point to assigned_to. Remember to alias it in your class!)
#
# * id
# * status
# * priority
- # * summary
+ # * title
# * resolution
# * created_at
# * updated_at
# * description
# * assignee
+ # * requestor
+ # * project_id
class Ticket < Hashie::Mash
- @ignore_inspect = %w| system system_data |
- @system = nil # The symbol for the provider.
- @system_data = nil # The system info for the provider
+ include TicketMaster::Provider::Common
+ include TicketMaster::Provider::Helper
+ extend TicketMaster::Provider::Helper
attr_accessor :system, :system_data
- # Find a ticket
- #
- # The implementation should be able to accept these cases if feasible:
+ API = nil # Replace with your ticket API's Class
+
+ # Find ticket
+ # You can also retrieve an array of all tickets by not specifying any query.
#
- # * find(:all) - Returns an array of all tickets
- # * find(##) - Returns a project based on that id or some other primary (unique) attribute
- # * find(:first, :summary => 'Ticket title') - Returns a ticket based on the ticket's attributes
- # * find(:summary => 'Test Ticket') - Returns all tickets based on the given attributes
- def self.find(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ # * find(<project_id>) or find(<project_id>, :all) - Returns an array of all tickets
+ # * find(<project_id>, ##) - Returns a ticket based on that id or some other primary (unique) attribute
+ # * find(<project_id>, [#, #, #]) - Returns many tickets with these ids
+ # * find(<project_id>, :first, :title => 'ticket name') - Returns the first ticket based on the ticket's attribute(s)
+ # * find(<project_id>, :last, :title => 'Some ticket') - Returns the last ticket based on the ticket's attribute(s)
+ # * find(<project_id>, :all, :title => 'Test ticket') - Returns all tickets based on the given attribute(s)
+ def self.find(project_id, *options)
+ first, attributes = options
+ if first.nil? or (first == :all and attributes.nil?)
+ self.find_by_attributes(project_id)
+ elsif first.is_a? Fixnum
+ self.find_by_id(project_id, first)
+ elsif first.is_a? Array
+ first.collect { |id| self.find_by_id(project_id, id) }
+ elsif first == :first
+ tickets = attributes.nil? ? self.find_by_attributes(project_id) : self.find_by_attributes(project_id, attributes)
+ tickets.first
+ elsif first == :last
+ tickets = attributes.nil? ? self.find_by_attributes(project_id) : self.find_by_attributes(project_id, attributes)
+ tickets.last
+ elsif first == :all
+ self.find_by_attributes(project_id, attributes)
+ end
end
- # Create a ticket.
- # Basically, a .new and .save in the same call. The default method assumes it is passed a
- # single hash with attribute information
- def self.create(*options)
- ticket = self.new(options.first)
- ticket.save
+ # The first of whatever ticket
+ def self.first(project_id, *options)
+ self.find(project_id, :first, *options)
end
- # Instantiate a new ticket (but don't save yet!)
- # The default method assumes a single hash with all the parameters is passed to Ticket.new
- def initialize(*options)
- super(options.first)
- # do some other stuff
+ # The last of whatever ticket
+ def self.last(project_id, *options)
+ self.find(project_id, :last, *options)
end
-
- # Close this ticket
- #
- # On success it should return true, otherwise false
- def close(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+
+ # Accepts an integer id and returns the single ticket instance
+ # Must be defined by the provider
+ def self.find_by_id(project_id, ticket_id)
+ if self::API.is_a? Class
+ self.new self::API.find(ticket_id, :params => {:project_id => project_id})
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
end
- # Save this ticket
- # Expected return value of true (successful) or false (failure)
- def save(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ # Accepts an attributes hash and returns all tickets matching those attributes in an array
+ # Should return all tickets if the attributes hash is empty
+ # Must be defined by the provider
+ def self.find_by_attributes(project_id, attributes = {})
+ if self::API.is_a? Class
+ self.search(project_id, attributes).collect { |thing| self.new thing }
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
end
- # Reload this ticket
- def reload!(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ # This is a helper method to find
+ def self.search(project_id, options = {}, limit = 1000)
+ if self::API.is_a? Class
+ tickets = self::API.find(:all, :params => {:project_id => project_id})
+ search_by_attribute(tickets, options, limit)
+ else
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ end
+ end
+
+ # Asks the provider's api for the comment associated with the project,
+ # returns an array of Comment objects.
+ def comments(*options)
+ options.insert 0, project_id
+ options.insert 1, id
+ easy_finder(self.class.parent::Comment, :all, options, 2)
end
- # Delete this ticket
- #
- # If your provider doesn't have a delete or trash option for tickets:
- # raise TicketMaster::Exception.new("Tickets can not be destroyed on SomeProviderAPI")
- def destroy(*options)
- raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
+ def comment(*options)
+ if options.length > 0
+ options.insert(0, project_id)
+ options.insert(1, id)
+ end
+ easy_finder(self.class.parent::Comment, :first, options, 2)
end
- # Update a ticket and save
+ # Close this ticket
#
- # The default assumes the options passed to it is a single hash with the attributes to update
- def update!(*options)
- update(options.first)
- save
+ # On success it should return true, otherwise false
+ def close(*options)
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
end
- # Update a ticket's attributes, but no save
- # Used when you need to do mass attribute assignment
- def update(*options)
- options.first.each do |k, v|
- self.send(k + '=', v)
- end
- self
+ # Reload this ticket
+ def reload!(*options)
+ raise TicketMaster::Exception.new("This method must be reimplemented in the provider")
end
end
View
9 ticketmaster.gemspec
@@ -9,14 +9,15 @@ Gem::Specification.new do |s|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
s.authors = ["Sirupsen", "deadprogrammer"]
- s.date = %q{2010-06-26}
+ s.date = %q{2010-07-02}
s.default_executable = %q{ticket}
s.description = %q{Ticketmaster provides a universal API to trouble ticket and project management systems.}
s.email = %q{simon@hybridgroup.com}
s.executables = ["ticket"]
s.extra_rdoc_files = [
"LICENSE",
- "README.md"
+ "README.md",
+ "TODO"
]
s.files = [
".document",
@@ -25,6 +26,7 @@ Gem::Specification.new do |s|
"NOTES",
"README.md",
"Rakefile",
+ "TODO",
"VERSION",
"bin/ticket",
"lib/ticketmaster.rb",
@@ -41,10 +43,13 @@ Gem::Specification.new do |s|
"lib/ticketmaster/cli/commands/ticket.rb",
"lib/ticketmaster/cli/common.rb",
"lib/ticketmaster/cli/init.rb",
+ "lib/ticketmaster/comment.rb",
+ "lib/ticketmaster/common.rb",
"lib/ticketmaster/dummy/dummy.rb",
"lib/ticketmaster/dummy/project.rb",
"lib/ticketmaster/dummy/ticket.rb",
"lib/ticketmaster/exception.rb",
+ "lib/ticketmaster/helper.rb",
"lib/ticketmaster/project.rb",
"lib/ticketmaster/provider.rb",
"lib/ticketmaster/ticket.rb",
Please sign in to comment.
Something went wrong with that request. Please try again.