table_print 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +13 -0
- data/Gemfile.lock +20 -0
- data/LICENSE.txt +20 -0
- data/README.rdoc +62 -0
- data/Rakefile +53 -0
- data/VERSION +1 -0
- data/lib/table_print.rb +187 -0
- data/test/helper.rb +18 -0
- data/test/test_table_print.rb +159 -0
- metadata +137 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,13 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
# Add dependencies required to use your gem here.
|
3
|
+
# Example:
|
4
|
+
# gem "activesupport", ">= 2.3.5"
|
5
|
+
|
6
|
+
# Add dependencies to develop your gem here.
|
7
|
+
# Include everything needed to run rake, tests, features, etc.
|
8
|
+
group :development do
|
9
|
+
gem "shoulda", ">= 0"
|
10
|
+
gem "bundler", "~> 1.0.0"
|
11
|
+
gem "jeweler", "~> 1.5.2"
|
12
|
+
gem "rcov", ">= 0"
|
13
|
+
end
|
data/Gemfile.lock
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
GEM
|
2
|
+
remote: http://rubygems.org/
|
3
|
+
specs:
|
4
|
+
git (1.2.5)
|
5
|
+
jeweler (1.5.2)
|
6
|
+
bundler (~> 1.0.0)
|
7
|
+
git (>= 1.2.5)
|
8
|
+
rake
|
9
|
+
rake (0.8.7)
|
10
|
+
rcov (0.9.9)
|
11
|
+
shoulda (2.11.3)
|
12
|
+
|
13
|
+
PLATFORMS
|
14
|
+
ruby
|
15
|
+
|
16
|
+
DEPENDENCIES
|
17
|
+
bundler (~> 1.0.0)
|
18
|
+
jeweler (~> 1.5.2)
|
19
|
+
rcov
|
20
|
+
shoulda
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2011 Chris Doyle
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
@@ -0,0 +1,62 @@
|
|
1
|
+
= table_print
|
2
|
+
|
3
|
+
Turn objects into nicely formatted columns for easy reading
|
4
|
+
|
5
|
+
TablePrint formats an object or array of objects into columns for easy reading. To do this,
|
6
|
+
it assumes the objects in your array all respond to the same methods.
|
7
|
+
|
8
|
+
== Installation
|
9
|
+
|
10
|
+
# Install as a standalone gem
|
11
|
+
$ gem install table_print
|
12
|
+
|
13
|
+
# Install within rails
|
14
|
+
In your Gemfile: gem 'table_print'
|
15
|
+
$ bundle install
|
16
|
+
|
17
|
+
== Usage
|
18
|
+
|
19
|
+
# Outside rails
|
20
|
+
$ irb
|
21
|
+
> require 'table_print'
|
22
|
+
> tp array_of_objects, options = {}
|
23
|
+
|
24
|
+
# Inside rails, the gem has already been required by your Gemfile so all you need to do is
|
25
|
+
$ rails c
|
26
|
+
> tp array_of_objects, options = {}
|
27
|
+
|
28
|
+
And you should see something like this:
|
29
|
+
|
30
|
+
NAME | SUMMARY | TITLE
|
31
|
+
-----------------------------------------------------------------------
|
32
|
+
Michael Connelly | Another book by Michael Con... | The Fifth Witness
|
33
|
+
Manning Mardale | From acclaimed historian Ma... | Malcolm X
|
34
|
+
Tina Fey | Worth it. -Trees | Bossypants
|
35
|
+
|
36
|
+
TablePrint tries to use sensible defaults to choose the columns to show. If you're inspecting ActiveRecord objects, it
|
37
|
+
uses the ActiveRecord column names. You can customize the output to show fewer columns, or show other methods you've written
|
38
|
+
on your model.
|
39
|
+
|
40
|
+
# Maybe you story a user's hourly rate but you want to see their yearly income
|
41
|
+
> tp User.limit(30), {:include => :yearly_income, :except => :hourly_rate}
|
42
|
+
|
43
|
+
# Maybe all you care about is their mailing info
|
44
|
+
> tp User.limit(30), {:only => [:address, :city, :state, :zip]}
|
45
|
+
|
46
|
+
If you're not using ActiveRecord, the TablePrint default is to show all the methods on your object. Thus, the <b>:include</b>
|
47
|
+
option is useless at the moment. You are still able to use <b>:only</b> and <b>:include</b>.
|
48
|
+
|
49
|
+
== Contributing to table_print
|
50
|
+
|
51
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet
|
52
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it
|
53
|
+
* Fork the project
|
54
|
+
* Start a feature/bugfix branch
|
55
|
+
* Commit and push until you are happy with your contribution
|
56
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
57
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
58
|
+
|
59
|
+
== Copyright
|
60
|
+
|
61
|
+
Copyright (c) 2011 Chris Doyle. See LICENSE.txt for further details.
|
62
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1,53 @@
|
|
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 = "table_print"
|
16
|
+
gem.homepage = "http://github.com/arches/table_print"
|
17
|
+
gem.license = "MIT"
|
18
|
+
gem.summary = %Q{Turn objects into nicely formatted columns for easy reading}
|
19
|
+
gem.description = %Q{TablePrint formats an object or array of objects into columns for easy reading. To do this, it assumes the objects in your array all respond to the same methods (vs pretty_print or awesome_print, who can't create columns because your objects could be entirely different).}
|
20
|
+
gem.email = "archslide@gmail.com"
|
21
|
+
gem.authors = ["Chris Doyle"]
|
22
|
+
# Include your dependencies below. Runtime dependencies are required when using your gem,
|
23
|
+
# and development dependencies are only needed for development (ie running rake tasks, tests, etc)
|
24
|
+
# gem.add_runtime_dependency 'jabber4r', '> 0.1'
|
25
|
+
# gem.add_development_dependency 'rspec', '> 1.2.3'
|
26
|
+
end
|
27
|
+
Jeweler::RubygemsDotOrgTasks.new
|
28
|
+
|
29
|
+
require 'rake/testtask'
|
30
|
+
Rake::TestTask.new(:test) do |test|
|
31
|
+
test.libs << 'lib' << 'test'
|
32
|
+
test.pattern = 'test/**/test_*.rb'
|
33
|
+
test.verbose = true
|
34
|
+
end
|
35
|
+
|
36
|
+
require 'rcov/rcovtask'
|
37
|
+
Rcov::RcovTask.new do |test|
|
38
|
+
test.libs << 'test'
|
39
|
+
test.pattern = 'test/**/test_*.rb'
|
40
|
+
test.verbose = true
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
48
|
+
|
49
|
+
rdoc.rdoc_dir = 'rdoc'
|
50
|
+
rdoc.title = "table_print #{version}"
|
51
|
+
rdoc.rdoc_files.include('README*')
|
52
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
53
|
+
end
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.0
|
data/lib/table_print.rb
ADDED
@@ -0,0 +1,187 @@
|
|
1
|
+
# future work:
|
2
|
+
#
|
3
|
+
# handle multi-level includes like 'tp User.all, :include => "blogs.title"' and ActiveRecord associations
|
4
|
+
# allow other output venues besides 'puts'
|
5
|
+
# allow fine-grained formatting
|
6
|
+
#
|
7
|
+
# bugs
|
8
|
+
#
|
9
|
+
# handle multibyte (see https://skitch.com/arches/r3cbg/multibyte-bug)
|
10
|
+
|
11
|
+
class TablePrint
|
12
|
+
|
13
|
+
MAX_FIELD_LENGTH = 30
|
14
|
+
|
15
|
+
# TODO: make options for things like MAX_FIELD_LENGTH
|
16
|
+
# TODO: make options for things like separator
|
17
|
+
# TODO: make options for things like column order
|
18
|
+
def initialize(options = {})
|
19
|
+
end
|
20
|
+
|
21
|
+
# TODO: show documentation if invoked with no arguments
|
22
|
+
# TODO: use *args instead of options
|
23
|
+
def tp(data, options = {})
|
24
|
+
data = wrap(data).compact
|
25
|
+
|
26
|
+
# nothing to see here
|
27
|
+
if data.empty?
|
28
|
+
return "No data."
|
29
|
+
end
|
30
|
+
|
31
|
+
separator = " | "
|
32
|
+
|
33
|
+
display_methods = get_display_methods(data.first, options)
|
34
|
+
unless display_methods.length > 0
|
35
|
+
return data.inspect.to_s
|
36
|
+
end
|
37
|
+
|
38
|
+
# we're going to load all the data into memory so we can calculate field lengths.
|
39
|
+
# TODO: there has to be a better way than loading everything into memory
|
40
|
+
# TODO: stop checking field length once we hit the max
|
41
|
+
# TODO: don't check field length on fixed-width columns
|
42
|
+
|
43
|
+
field_lengths = {}
|
44
|
+
|
45
|
+
# column headers
|
46
|
+
display_methods.each do |m|
|
47
|
+
field_lengths[m] = m.to_s.length
|
48
|
+
end
|
49
|
+
|
50
|
+
data.each do |obj|
|
51
|
+
display_methods.each do |m|
|
52
|
+
field_value = truncate(obj.send(m).to_s)
|
53
|
+
field_lengths[m] = [field_lengths[m], field_value.length].max
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
output = []
|
58
|
+
|
59
|
+
row = []
|
60
|
+
display_methods.each do |m|
|
61
|
+
field_value = truncate(m.to_s)
|
62
|
+
field_length = field_lengths[m]
|
63
|
+
row << ("%-#{field_length}s" % field_value.upcase)
|
64
|
+
end
|
65
|
+
output << row.join(separator)
|
66
|
+
output << ("-" * row.join(separator).length)
|
67
|
+
|
68
|
+
data.each do |obj|
|
69
|
+
row = []
|
70
|
+
display_methods.each do |m|
|
71
|
+
field_value = truncate(obj.send(m).to_s)
|
72
|
+
field_length = field_lengths[m]
|
73
|
+
row << ("%-#{field_length}s" % field_value)
|
74
|
+
end
|
75
|
+
output << row.join(separator)
|
76
|
+
end
|
77
|
+
|
78
|
+
output.join("\n")
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def truncate(field_value)
|
84
|
+
if field_value.length > MAX_FIELD_LENGTH
|
85
|
+
field_value = field_value[0..MAX_FIELD_LENGTH-1]
|
86
|
+
field_value[-3..-1] = "..."
|
87
|
+
end
|
88
|
+
field_value
|
89
|
+
end
|
90
|
+
|
91
|
+
def get_display_methods(data_obj, options)
|
92
|
+
# determine what methods we're going to use
|
93
|
+
|
94
|
+
# using options:
|
95
|
+
# TODO: maybe rename these a little? cascade/include are somewhat mixed with respect to rails lexicon
|
96
|
+
# :except - use the default set of methods but NOT the ones passed here
|
97
|
+
# :include - use the default set of methods AND the ones passed here
|
98
|
+
# :only - discard the default set of methods in favor of this list
|
99
|
+
# :cascade -
|
100
|
+
#
|
101
|
+
# eg
|
102
|
+
#
|
103
|
+
# tp User.limit(30) # default to using AR columns
|
104
|
+
# tp User.limit(30) :except => :display_name
|
105
|
+
# tp User.limit(30) :except => [:display_name, :created_at]
|
106
|
+
# tp User.limit(30) :except => [:display_name, :timestamps] # a rails convention - but this could just be a type-based filter instead of method-based?
|
107
|
+
# tp User.limit(30) :include => :status # not an AR column
|
108
|
+
# tp User.limit(30) :except => :display_name
|
109
|
+
# tp User.limit(30) :except => :display_name
|
110
|
+
# tp User.limit(30) :except => :display_name
|
111
|
+
# tp User.limit(30) :except => :display_name
|
112
|
+
#
|
113
|
+
# tp User.include(:blogs).limit(30) :cascade => :blog
|
114
|
+
# tp User.limit(30) :include => "blog.title" # use dot notation to traverse children
|
115
|
+
# TODO: how to handle multiple children? eg, a user has fifteen blogs
|
116
|
+
#
|
117
|
+
# tp [myClassInstance1, ...] # default to using non-base methods
|
118
|
+
# tp [myClassInstance1, ...] :except => :blah
|
119
|
+
# tp [myClassInstance1, ...] :except => [:blah, :blow]
|
120
|
+
# tp [myClassInstance1, ...] :include => :blah
|
121
|
+
# tp [myClassInstance1, ...] :include => [:blah, :blow]
|
122
|
+
# tp [myClassInstance1, ...] :include => :blah, :except => :blow
|
123
|
+
# tp [myClassInstance1, ...] :only => [:one, :two, :three]
|
124
|
+
|
125
|
+
if options.has_key? :only or options.has_key? "only"
|
126
|
+
display_methods = clean_display_methods(data_obj, wrap(options[:only]))
|
127
|
+
return display_methods if display_methods.length > 0
|
128
|
+
end
|
129
|
+
|
130
|
+
# make all the options into arrays
|
131
|
+
methods_to_include = clean_display_methods(data_obj, wrap(options[:include]))
|
132
|
+
methods_to_except = clean_display_methods(data_obj, wrap(options[:except]))
|
133
|
+
|
134
|
+
# add/remove the includes/excludes from the defaults
|
135
|
+
display_methods = get_default_display_methods(data_obj)
|
136
|
+
display_methods.concat(methods_to_include).uniq!
|
137
|
+
display_methods - methods_to_except
|
138
|
+
end
|
139
|
+
|
140
|
+
def get_default_display_methods(data_obj)
|
141
|
+
# ActiveRecord
|
142
|
+
return data_obj.class.columns.collect { |c| c.name } if defined?(ActiveRecord) and data_obj.is_a? ActiveRecord::Base
|
143
|
+
|
144
|
+
# base types
|
145
|
+
# TODO: fill out this list. any way to get this programatically? do we actually want to filter out all base ruby types? important question for custom classes inheriting from base types
|
146
|
+
return [] if [Float, Fixnum, String, Numeric, Array, Hash].include? data_obj.class
|
147
|
+
|
148
|
+
# custom class
|
149
|
+
methods = data_obj.class.instance_methods - Object.instance_methods
|
150
|
+
methods.delete_if { |m| m[-1].chr == "=" } # don't use assignment methods
|
151
|
+
methods.map! { |m| m.to_s } # make any symbols into strings
|
152
|
+
methods
|
153
|
+
end
|
154
|
+
|
155
|
+
def clean_display_methods(data_obj, display_methods)
|
156
|
+
clean_methods = []
|
157
|
+
display_methods.each do |m|
|
158
|
+
next if m.nil?
|
159
|
+
next if m == ""
|
160
|
+
next unless data_obj.respond_to? m
|
161
|
+
clean_methods << m.to_s
|
162
|
+
end
|
163
|
+
clean_methods.uniq
|
164
|
+
end
|
165
|
+
|
166
|
+
# borrowed from rails
|
167
|
+
def wrap(object)
|
168
|
+
if object.nil?
|
169
|
+
[]
|
170
|
+
elsif object.respond_to?(:to_ary)
|
171
|
+
object.to_ary
|
172
|
+
else
|
173
|
+
[object]
|
174
|
+
end
|
175
|
+
end
|
176
|
+
end
|
177
|
+
|
178
|
+
module Kernel
|
179
|
+
def tp(data, options = {})
|
180
|
+
start = Time.now
|
181
|
+
table_print = TablePrint.new
|
182
|
+
puts table_print.tp(data, options)
|
183
|
+
return Time.now - start
|
184
|
+
end
|
185
|
+
|
186
|
+
module_function :tp
|
187
|
+
end
|
data/test/helper.rb
ADDED
@@ -0,0 +1,18 @@
|
|
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 'test/unit'
|
11
|
+
require 'shoulda'
|
12
|
+
|
13
|
+
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
14
|
+
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
15
|
+
require 'table_print'
|
16
|
+
|
17
|
+
class Test::Unit::TestCase
|
18
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'helper'
|
2
|
+
|
3
|
+
class MyClass
|
4
|
+
attr_accessor :title, :name, :summary
|
5
|
+
|
6
|
+
def initialize(title, name, summary)
|
7
|
+
self.title = title
|
8
|
+
self.name = name
|
9
|
+
self.summary = summary
|
10
|
+
end
|
11
|
+
|
12
|
+
def self.setup
|
13
|
+
[["how to", "bert", "bertto"],
|
14
|
+
["enemies", "ernie", "ernieenemies"],
|
15
|
+
["a walk to forget", "big bird", "bigbirdforget"],
|
16
|
+
["cookies", "cookie monster", "cookiemonstercookies"],
|
17
|
+
["your mom", "the count", "thecountmom"],
|
18
|
+
["fire!", "elmo", "elmofire!"],
|
19
|
+
["eat your veggies", "michelle obama", "michelleobamaveggies"],
|
20
|
+
["wakka wakka", "ellen degeneres", "ellendegenereswakka"],
|
21
|
+
["peas and carrots", "the hulk", "thehulkcarrots"],
|
22
|
+
["juan valdez", "camaro", "camaravaldez"],
|
23
|
+
["fish fish fish", "alaska", "alaskafish"],
|
24
|
+
["tracks", "sir toppem hat", "sirtoppemhattracks"],
|
25
|
+
["smoking stacked", "thomas", "thomasstacked"],
|
26
|
+
["cannes", "alpo", "alpocannes"],
|
27
|
+
].collect { |a| MyClass.new(a[0], a[1], a[2]) }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
class TablePrint
|
32
|
+
def _truncate(field_value)
|
33
|
+
truncate(field_value)
|
34
|
+
end
|
35
|
+
|
36
|
+
def _get_display_methods(data_obj, options)
|
37
|
+
get_display_methods(data_obj, options)
|
38
|
+
end
|
39
|
+
|
40
|
+
def _get_default_display_methods(data_obj)
|
41
|
+
get_default_display_methods(data_obj)
|
42
|
+
end
|
43
|
+
|
44
|
+
def _clean_display_methods(data_obj, display_methods)
|
45
|
+
clean_display_methods(data_obj, display_methods)
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
class OneMethod
|
50
|
+
def title
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
class OneAttrAccessor
|
55
|
+
attr_accessor :title
|
56
|
+
end
|
57
|
+
|
58
|
+
class ManyMethods
|
59
|
+
def title
|
60
|
+
end
|
61
|
+
def author
|
62
|
+
end
|
63
|
+
def summary
|
64
|
+
end
|
65
|
+
end
|
66
|
+
|
67
|
+
class TestTablePrint < Test::Unit::TestCase
|
68
|
+
|
69
|
+
# TODO: active record tests if defined?(ActiveRecord)
|
70
|
+
|
71
|
+
# Vaguely ordered from most to least granular
|
72
|
+
|
73
|
+
context '' do
|
74
|
+
setup do
|
75
|
+
@tp = TablePrint.new
|
76
|
+
end
|
77
|
+
|
78
|
+
context 'The default display methods for ruby base types' do
|
79
|
+
should 'be empty' do
|
80
|
+
assert_equal [], @tp._get_default_display_methods([])
|
81
|
+
assert_equal [], @tp._get_default_display_methods("")
|
82
|
+
assert_equal [], @tp._get_default_display_methods({})
|
83
|
+
assert_equal [], @tp._get_default_display_methods(10)
|
84
|
+
assert_equal [], @tp._get_default_display_methods(1.0)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
88
|
+
context 'The truncate function' do
|
89
|
+
should 'let short strings pass through' do
|
90
|
+
assert_equal "asdf", @tp._truncate("asdf")
|
91
|
+
end
|
92
|
+
|
93
|
+
should 'truncate long strings with ellipses' do
|
94
|
+
assert_equal "123456789012345678901234567...", @tp._truncate("1234567890123456789012345678901234567890")
|
95
|
+
end
|
96
|
+
end
|
97
|
+
|
98
|
+
context 'The clean_display_methods function' do
|
99
|
+
should 'only give back valid methods' do
|
100
|
+
assert_equal [], @tp._clean_display_methods(ManyMethods.new, [""])
|
101
|
+
assert_equal [], @tp._clean_display_methods(ManyMethods.new, [nil])
|
102
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, ["title"])
|
103
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, [:title])
|
104
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, ["title", "title"])
|
105
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, ["title", :title])
|
106
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, [:title, :title])
|
107
|
+
assert_equal ["title"], @tp._clean_display_methods(ManyMethods.new, ["title", "january1985"])
|
108
|
+
end
|
109
|
+
end
|
110
|
+
|
111
|
+
context 'The default display methods for a custom class with one method' do
|
112
|
+
should 'be that method' do
|
113
|
+
assert_equal ["title"], @tp._get_default_display_methods(OneMethod.new)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
context 'The default display methods for a custom class with one attr_accessor' do
|
118
|
+
should 'only be the attr setter' do
|
119
|
+
assert_equal ["title"], @tp._get_default_display_methods(OneAttrAccessor.new)
|
120
|
+
end
|
121
|
+
end
|
122
|
+
|
123
|
+
context 'The display methods for a custom class using the :only option' do
|
124
|
+
should 'be an array containing the methods specified in the :only option' do
|
125
|
+
assert_equal ["title"], @tp._get_display_methods(ManyMethods.new, {:only => :title})
|
126
|
+
assert_equal ["title"], @tp._get_display_methods(ManyMethods.new, {:only => "title"})
|
127
|
+
assert_equal ["title"], @tp._get_display_methods(ManyMethods.new, {:only => [:title]})
|
128
|
+
assert_equal ["title"], @tp._get_display_methods(ManyMethods.new, {:only => ["title"]})
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
# The :include option is more for ActiveRecord. It will only affect custom classes once multi-level methods are implemented.
|
133
|
+
context 'The display methods for a custom class using the :include option' do
|
134
|
+
should "be the same as if it weren't used" do
|
135
|
+
assert_equal ["author", "summary", "title"], @tp._get_display_methods(ManyMethods.new, {:include => :title}).sort
|
136
|
+
assert_equal ["author", "summary", "title"], @tp._get_display_methods(ManyMethods.new, {:include => "title"}).sort
|
137
|
+
assert_equal ["author", "summary", "title"], @tp._get_display_methods(ManyMethods.new, {:include => [:title]}).sort
|
138
|
+
assert_equal ["author", "summary", "title"], @tp._get_display_methods(ManyMethods.new, {:include => ["title"]}).sort
|
139
|
+
end
|
140
|
+
end
|
141
|
+
|
142
|
+
context 'The display methods for a custom class using the :except option' do
|
143
|
+
should "not include any specified methods" do
|
144
|
+
assert_equal ["author", "summary"], @tp._get_display_methods(ManyMethods.new, {:except => :title}).sort
|
145
|
+
assert_equal ["author", "summary"], @tp._get_display_methods(ManyMethods.new, {:except => "title"}).sort
|
146
|
+
assert_equal ["author", "summary"], @tp._get_display_methods(ManyMethods.new, {:except => [:title]}).sort
|
147
|
+
assert_equal ["summary"], @tp._get_display_methods(ManyMethods.new, {:except => ["title", :author]}).sort
|
148
|
+
end
|
149
|
+
end
|
150
|
+
|
151
|
+
context 'An empty input' do
|
152
|
+
should 'say as much in the output' do
|
153
|
+
assert_equal "No data.", @tp.tp(nil)
|
154
|
+
assert_equal "No data.", @tp.tp([])
|
155
|
+
assert_equal "No data.", @tp.tp([nil])
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|
metadata
ADDED
@@ -0,0 +1,137 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: table_print
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 27
|
5
|
+
prerelease:
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 1
|
9
|
+
- 0
|
10
|
+
version: 0.1.0
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Chris Doyle
|
14
|
+
autorequire:
|
15
|
+
bindir: bin
|
16
|
+
cert_chain: []
|
17
|
+
|
18
|
+
date: 2011-04-11 00:00:00 -07:00
|
19
|
+
default_executable:
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
prerelease: false
|
23
|
+
type: :development
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
name: shoulda
|
34
|
+
version_requirements: *id001
|
35
|
+
- !ruby/object:Gem::Dependency
|
36
|
+
prerelease: false
|
37
|
+
type: :development
|
38
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
39
|
+
none: false
|
40
|
+
requirements:
|
41
|
+
- - ~>
|
42
|
+
- !ruby/object:Gem::Version
|
43
|
+
hash: 23
|
44
|
+
segments:
|
45
|
+
- 1
|
46
|
+
- 0
|
47
|
+
- 0
|
48
|
+
version: 1.0.0
|
49
|
+
name: bundler
|
50
|
+
version_requirements: *id002
|
51
|
+
- !ruby/object:Gem::Dependency
|
52
|
+
prerelease: false
|
53
|
+
type: :development
|
54
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
55
|
+
none: false
|
56
|
+
requirements:
|
57
|
+
- - ~>
|
58
|
+
- !ruby/object:Gem::Version
|
59
|
+
hash: 7
|
60
|
+
segments:
|
61
|
+
- 1
|
62
|
+
- 5
|
63
|
+
- 2
|
64
|
+
version: 1.5.2
|
65
|
+
name: jeweler
|
66
|
+
version_requirements: *id003
|
67
|
+
- !ruby/object:Gem::Dependency
|
68
|
+
prerelease: false
|
69
|
+
type: :development
|
70
|
+
requirement: &id004 !ruby/object:Gem::Requirement
|
71
|
+
none: false
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
hash: 3
|
76
|
+
segments:
|
77
|
+
- 0
|
78
|
+
version: "0"
|
79
|
+
name: rcov
|
80
|
+
version_requirements: *id004
|
81
|
+
description: TablePrint formats an object or array of objects into columns for easy reading. To do this, it assumes the objects in your array all respond to the same methods (vs pretty_print or awesome_print, who can't create columns because your objects could be entirely different).
|
82
|
+
email: archslide@gmail.com
|
83
|
+
executables: []
|
84
|
+
|
85
|
+
extensions: []
|
86
|
+
|
87
|
+
extra_rdoc_files:
|
88
|
+
- LICENSE.txt
|
89
|
+
- README.rdoc
|
90
|
+
files:
|
91
|
+
- .document
|
92
|
+
- Gemfile
|
93
|
+
- Gemfile.lock
|
94
|
+
- LICENSE.txt
|
95
|
+
- README.rdoc
|
96
|
+
- Rakefile
|
97
|
+
- VERSION
|
98
|
+
- lib/table_print.rb
|
99
|
+
- test/helper.rb
|
100
|
+
- test/test_table_print.rb
|
101
|
+
has_rdoc: true
|
102
|
+
homepage: http://github.com/arches/table_print
|
103
|
+
licenses:
|
104
|
+
- MIT
|
105
|
+
post_install_message:
|
106
|
+
rdoc_options: []
|
107
|
+
|
108
|
+
require_paths:
|
109
|
+
- lib
|
110
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
+
none: false
|
112
|
+
requirements:
|
113
|
+
- - ">="
|
114
|
+
- !ruby/object:Gem::Version
|
115
|
+
hash: 3
|
116
|
+
segments:
|
117
|
+
- 0
|
118
|
+
version: "0"
|
119
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
+
none: false
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
hash: 3
|
125
|
+
segments:
|
126
|
+
- 0
|
127
|
+
version: "0"
|
128
|
+
requirements: []
|
129
|
+
|
130
|
+
rubyforge_project:
|
131
|
+
rubygems_version: 1.5.2
|
132
|
+
signing_key:
|
133
|
+
specification_version: 3
|
134
|
+
summary: Turn objects into nicely formatted columns for easy reading
|
135
|
+
test_files:
|
136
|
+
- test/helper.rb
|
137
|
+
- test/test_table_print.rb
|